From nobody Tue Jan 27 00:09:31 2026 Received: from out-183.mta1.migadu.com (out-183.mta1.migadu.com [95.215.58.183]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EC8523EBF21 for ; Mon, 26 Jan 2026 15:16:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.183 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769440575; cv=none; b=hreVknjuc6teje1CTV8Tl4VjDYBkQ4sPcCLJiD8UKpET1rthnSFJSgT0/QY2p8wLdoXiG2XHKLjLcZz5vJgzpA2Fz2os3vChKNTBYxp7UjDW9Y9mwA8RUb8jGQwf7dbK+jxUs4/VEf+65kAbHd9YbMhvwvPm865mgL9t6D9dj58= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1769440575; c=relaxed/simple; bh=jFbFzaLQVKRbg8pqCam/KLxE2rR+AZ8YnXVgAtjdnJA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aWHhfN9PxHy2g4cVlHJZb425H2Ls/2Ve9bfLfXsiQpYWCrt4SKo6Kb+GmN45TSlYTznIHO/Qzr+G7nSCxZn58+24I9d9H39iDAohF76ZoGzdm7PN79M7h224BwBJm88Po+7EHlE4Ocwzi1q9Csv2qAiTBXGNILxR7VPopw45Xzk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=GiLZ5Hcv; arc=none smtp.client-ip=95.215.58.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="GiLZ5Hcv" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1769440571; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=nJlY7pNuViDwTIygCdfwSue8vGZGp+4ZNyXH17+V1/E=; b=GiLZ5HcvR3XxMi+Vws3yhVQDdkQKkF7rZah6msxuCZzdPojhGNYczEygw08S5DPSHMLjVF pQdjuPbPG7TKjNLCZ50VCpY/B7rN66mwtsHnZX55P9Php6tfnM2SJrFwYHp30M/QsmwOrr 6Tpv5yaC45+b7SRkg7bVKvUxno5T9Gk= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan , Christian Brauner , Seth Forshee , Yuichiro Tsuji , Andrey Albershteyn , Leon Hwang , Willem de Bruijn , Jason Xing , Tao Chen , Mykyta Yatsenko , Kumar Kartikeya Dwivedi , Anton Protopopov , Amery Hung , Rong Tao , linux-kernel@vger.kernel.org, linux-api@vger.kernel.org, linux-kselftest@vger.kernel.org, kernel-patches-bot@fb.com Subject: [PATCH bpf-next v8 7/9] bpf: Add syscall common attributes support for map_create Date: Mon, 26 Jan 2026 23:14:07 +0800 Message-ID: <20260126151409.52072-8-leon.hwang@linux.dev> In-Reply-To: <20260126151409.52072-1-leon.hwang@linux.dev> References: <20260126151409.52072-1-leon.hwang@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" Currently, many BPF_MAP_CREATE failures return -EINVAL without providing any explanation to userspace. With extended BPF syscall support, detailed error messages can now be reported via the log buffer, allowing users to understand the specific reason for a failed map creation. Signed-off-by: Leon Hwang --- include/linux/bpf_verifier.h | 2 ++ kernel/bpf/log.c | 30 +++++++++++++++++ kernel/bpf/syscall.c | 65 ++++++++++++++++++++++++++++++------ 3 files changed, 87 insertions(+), 10 deletions(-) diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index 732bc4baee1c..917293a552b6 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -644,6 +644,8 @@ int bpf_prog_load_log_attr_init(struct bpf_log_attr *lo= g_attr, struct bpf_attrs struct bpf_attrs *attrs_common); int bpf_btf_load_log_attr_init(struct bpf_log_attr *log_attr, struct bpf_a= ttrs *attrs, struct bpf_attrs *attrs_common); +struct bpf_verifier_log *bpf_log_attr_create_vlog(struct bpf_log_attr *log= _attr, + struct bpf_attrs *attrs_common); int bpf_log_attr_finalize(struct bpf_log_attr *log_attr, struct bpf_verifi= er_log *log); =20 #define BPF_MAX_SUBPROGS 256 diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c index 3cccb0c5e482..d7933a412c36 100644 --- a/kernel/bpf/log.c +++ b/kernel/bpf/log.c @@ -912,6 +912,36 @@ int bpf_btf_load_log_attr_init(struct bpf_log_attr *lo= g_attr, struct bpf_attrs * attrs_common); } =20 +struct bpf_verifier_log *bpf_log_attr_create_vlog(struct bpf_log_attr *log= _attr, + struct bpf_attrs *attrs_common) +{ + const struct bpf_common_attr *common =3D attrs_common->attr; + struct bpf_verifier_log *log; + int err; + + memset(log_attr, 0, sizeof(*log_attr)); + log_attr->log_buf =3D common->log_buf; + log_attr->log_size =3D common->log_size; + log_attr->log_level =3D common->log_level; + log_attr->attrs_common =3D attrs_common; + + if (!log_attr->log_buf) + return NULL; + + log =3D kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return ERR_PTR(-ENOMEM); + + err =3D bpf_vlog_init(log, log_attr->log_level, u64_to_user_ptr(log_attr-= >log_buf), + log_attr->log_size); + if (err) { + kfree(log); + return ERR_PTR(err); + } + + return log; +} + int bpf_log_attr_finalize(struct bpf_log_attr *log_attr, struct bpf_verifi= er_log *log) { u32 log_true_size, off; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 040b105ab676..a596a3f22ade 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1370,7 +1370,7 @@ static bool bpf_net_capable(void) =20 #define BPF_MAP_CREATE_LAST_FIELD excl_prog_hash_size /* called via syscall */ -static int map_create(union bpf_attr *attr, bpfptr_t uattr) +static int __map_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_v= erifier_log *log) { const struct bpf_map_ops *ops; struct bpf_token *token =3D NULL; @@ -1382,8 +1382,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t= uattr) int err; =20 err =3D CHECK_ATTR(BPF_MAP_CREATE); - if (err) + if (err) { + bpf_log(log, "Invalid attr.\n"); return -EINVAL; + } =20 /* check BPF_F_TOKEN_FD flag, remember if it's set, and then clear it * to avoid per-map type checks tripping on unknown flag @@ -1392,17 +1394,25 @@ static int map_create(union bpf_attr *attr, bpfptr_= t uattr) attr->map_flags &=3D ~BPF_F_TOKEN_FD; =20 if (attr->btf_vmlinux_value_type_id) { - if (attr->map_type !=3D BPF_MAP_TYPE_STRUCT_OPS || - attr->btf_key_type_id || attr->btf_value_type_id) + if (attr->map_type !=3D BPF_MAP_TYPE_STRUCT_OPS) { + bpf_log(log, "btf_vmlinux_value_type_id can only be used with struct_op= s maps.\n"); return -EINVAL; + } + if (attr->btf_key_type_id || attr->btf_value_type_id) { + bpf_log(log, "btf_vmlinux_value_type_id is mutually exclusive with btf_= key_type_id and btf_value_type_id.\n"); + return -EINVAL; + } } else if (attr->btf_key_type_id && !attr->btf_value_type_id) { + bpf_log(log, "Invalid btf_value_type_id.\n"); return -EINVAL; } =20 if (attr->map_type !=3D BPF_MAP_TYPE_BLOOM_FILTER && attr->map_type !=3D BPF_MAP_TYPE_ARENA && - attr->map_extra !=3D 0) + attr->map_extra !=3D 0) { + bpf_log(log, "Invalid map_extra.\n"); return -EINVAL; + } =20 f_flags =3D bpf_get_file_flag(attr->map_flags); if (f_flags < 0) @@ -1410,13 +1420,17 @@ static int map_create(union bpf_attr *attr, bpfptr_= t uattr) =20 if (numa_node !=3D NUMA_NO_NODE && ((unsigned int)numa_node >=3D nr_node_ids || - !node_online(numa_node))) + !node_online(numa_node))) { + bpf_log(log, "Invalid numa_node.\n"); return -EINVAL; + } =20 /* find map type and init map: hashtable vs rbtree vs bloom vs ... */ map_type =3D attr->map_type; - if (map_type >=3D ARRAY_SIZE(bpf_map_types)) + if (map_type >=3D ARRAY_SIZE(bpf_map_types)) { + bpf_log(log, "Invalid map_type.\n"); return -EINVAL; + } map_type =3D array_index_nospec(map_type, ARRAY_SIZE(bpf_map_types)); ops =3D bpf_map_types[map_type]; if (!ops) @@ -1434,8 +1448,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t= uattr) =20 if (token_flag) { token =3D bpf_token_get_from_fd(attr->map_token_fd); - if (IS_ERR(token)) + if (IS_ERR(token)) { + bpf_log(log, "Invalid map_token_fd.\n"); return PTR_ERR(token); + } =20 /* if current token doesn't grant map creation permissions, * then we can't use this token, so ignore it and rely on @@ -1518,8 +1534,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t= uattr) =20 err =3D bpf_obj_name_cpy(map->name, attr->map_name, sizeof(attr->map_name)); - if (err < 0) + if (err < 0) { + bpf_log(log, "Invalid map_name.\n"); goto free_map; + } =20 preempt_disable(); map->cookie =3D gen_cookie_next(&bpf_map_cookie); @@ -1542,6 +1560,7 @@ static int map_create(union bpf_attr *attr, bpfptr_t = uattr) =20 btf =3D btf_get_by_fd(attr->btf_fd); if (IS_ERR(btf)) { + bpf_log(log, "Invalid btf_fd.\n"); err =3D PTR_ERR(btf); goto free_map; } @@ -1569,6 +1588,7 @@ static int map_create(union bpf_attr *attr, bpfptr_t = uattr) bpfptr_t uprog_hash =3D make_bpfptr(attr->excl_prog_hash, uattr.is_kerne= l); =20 if (attr->excl_prog_hash_size !=3D SHA256_DIGEST_SIZE) { + bpf_log(log, "Invalid excl_prog_hash_size.\n"); err =3D -EINVAL; goto free_map; } @@ -1584,6 +1604,7 @@ static int map_create(union bpf_attr *attr, bpfptr_t = uattr) goto free_map; } } else if (attr->excl_prog_hash_size) { + bpf_log(log, "Invalid excl_prog_hash_size.\n"); err =3D -EINVAL; goto free_map; } @@ -1622,6 +1643,29 @@ static int map_create(union bpf_attr *attr, bpfptr_t= uattr) return err; } =20 +static int map_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_att= rs *attrs_common) +{ + struct bpf_verifier_log *log; + struct bpf_log_attr log_attr; + int err, ret; + + log =3D bpf_log_attr_create_vlog(&log_attr, attrs_common); + if (IS_ERR(log)) + return PTR_ERR(log); + + err =3D __map_create(attr, uattr, log); + if (err >=3D 0) + goto free; + + ret =3D bpf_log_attr_finalize(&log_attr, log); + if (ret) + err =3D ret; + +free: + kfree(log); + return err; +} + void bpf_map_inc(struct bpf_map *map) { atomic64_inc(&map->refcnt); @@ -6234,7 +6278,8 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr= , unsigned int size, =20 switch (cmd) { case BPF_MAP_CREATE: - err =3D map_create(&attr, uattr); + bpf_attrs_init(&attrs_common, &attr_common, uattr_common, size_common); + err =3D map_create(&attr, uattr, &attrs_common); break; case BPF_MAP_LOOKUP_ELEM: err =3D map_lookup_elem(&attr); --=20 2.52.0