From nobody Sat Feb 7 20:58:02 2026 Received: from out-173.mta0.migadu.com (out-173.mta0.migadu.com [91.218.175.173]) (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 0943634F485 for ; Tue, 6 Jan 2026 17:21:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767720118; cv=none; b=QNHi/m82x7LvOfqcRUfrKKy1BpJLeD5osv5QULo2LYzYs7ySKCteKEVALxcnPyLMLBI7k63zij81gjwd1c9L59qxeXrnqFyzuLapvzcBXZbXMUUIykMb1igNZqfOZpiRZRYNHuzspVJhX/PMlEguR9FObLqXScHH4k6B2UhKVGY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1767720118; c=relaxed/simple; bh=AETHN+3kFlVaYquHWZbaQLeMcf8iQflBHGOXp5wQCqo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dd3iRL7nnIFEuRLsF00N50/PqNHBMBjytrUlhw1q6Az9wHq+/hI8xuR1EJmLEvlI3yjzU9GhDqY1J0k11j0qnRWUqGeXiRlVvWwLRTKRlmbYJ7HZLnolLfwGxhdDv5MbMlRGMGC7Al6mk0VqA/3GE4P/kBiynJxDNwgT/sio5Ek= 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=QdaEnI2+; arc=none smtp.client-ip=91.218.175.173 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="QdaEnI2+" 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=1767720113; 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=5mauyZYzayXq6OYND+1vFeaYe2URO7AKanu1AXWjwEU=; b=QdaEnI2+xAQi2FlSNHjuDzvhP21UVE0kcsOG6LIZgJtB0NyFGGIwfu/wlGmgEob5pxER7X Qwvf0K+jr/zXhghujm1c76640gyvD0EbejUYLp4HMGUQEa9qvhsXBl+b2jIsuX10bZ/LfM VSTZcUnOOcJTQ/eaxqp4aEEWLsao3n4= From: Leon Hwang To: bpf@vger.kernel.org Cc: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , John Fastabend , KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa , Shuah Khan , Christian Brauner , Oleg Nesterov , Leon Hwang , Seth Forshee , Yuichiro Tsuji , Andrey Albershteyn , Willem de Bruijn , Jason Xing , Paul Chaignon , 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: [RESEND PATCH bpf-next v4 7/9] bpf: Add common attr support for map_create Date: Wed, 7 Jan 2026 01:20:16 +0800 Message-ID: <20260106172018.57757-8-leon.hwang@linux.dev> In-Reply-To: <20260106172018.57757-1-leon.hwang@linux.dev> References: <20260106172018.57757-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 user space. With the extended BPF syscall support, detailed error messages can now be reported. This allows users to understand the specific reason for a failed map creation, rather than just receiving a generic '-EINVAL'. Signed-off-by: Leon Hwang --- kernel/bpf/syscall.c | 88 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 14fc5738f2b9..e64cc7504731 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1366,23 +1366,72 @@ static bool bpf_net_capable(void) return capable(CAP_NET_ADMIN) || capable(CAP_SYS_ADMIN); } =20 +struct bpf_vlog_wrapper { + struct bpf_common_attr *attr; + struct bpf_verifier_log *log; +}; + +static void bpf_vlog_wrapper_destructor(struct bpf_vlog_wrapper *w) +{ + if (!w->log) + return; + + (void) bpf_vlog_finalize(w->log, &w->attr->log_true_size); + kfree(w->log); +} + +#define DEFINE_BPF_VLOG_WRAPPER(name, common_attrs) \ + struct bpf_vlog_wrapper name __cleanup(bpf_vlog_wrapper_destructor) =3D {= \ + .attr =3D common_attrs, \ + } + +static int bpf_vlog_wrapper_init(struct bpf_vlog_wrapper *w) +{ + struct bpf_common_attr *attr =3D w->attr; + struct bpf_verifier_log *log; + int err; + + if (!attr->log_buf) + return 0; + + log =3D kzalloc(sizeof(*log), GFP_KERNEL); + if (!log) + return -ENOMEM; + + err =3D bpf_vlog_init(log, attr->log_level, u64_to_user_ptr(attr->log_buf= ), attr->log_size); + if (err) { + kfree(log); + return err; + } + + w->log =3D log; + return 0; +} + #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_com= mon_attr *common_attrs) { const struct bpf_map_ops *ops; struct bpf_token *token =3D NULL; int numa_node =3D bpf_map_attr_numa_node(attr); u32 map_type =3D attr->map_type; + struct bpf_verifier_log *log; struct bpf_map *map; bool token_flag; int f_flags; int err; + DEFINE_BPF_VLOG_WRAPPER(log_wrapper, common_attrs); =20 err =3D CHECK_ATTR(BPF_MAP_CREATE); if (err) return -EINVAL; =20 + err =3D bpf_vlog_wrapper_init(&log_wrapper); + if (err) + return err; + log =3D log_wrapper.log; + /* 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 */ @@ -1390,17 +1439,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) @@ -1408,13 +1465,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) @@ -1432,8 +1493,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 @@ -1516,8 +1579,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); @@ -1540,6 +1605,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; } @@ -6279,7 +6345,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uatt= r, unsigned int size, =20 switch (cmd) { case BPF_MAP_CREATE: - err =3D map_create(&attr, uattr); + common_attrs.log_true_size =3D 0; + err =3D map_create(&attr, uattr, &common_attrs); + ret =3D copy_common_attr_log_true_size(uattr_common, size_common, + &common_attrs.log_true_size); + err =3D ret ? ret : err; break; case BPF_MAP_LOOKUP_ELEM: err =3D map_lookup_elem(&attr); --=20 2.52.0