From nobody Sat Feb 7 15:09:59 2026 Received: from out-185.mta0.migadu.com (out-185.mta0.migadu.com [91.218.175.185]) (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 4792E2DE70C for ; Mon, 12 Jan 2026 14:59:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.185 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768229972; cv=none; b=IkPGAhJy0BfQsJPtOfZWCTCsjtUuD7Tgoq2ao8lKhd0zp3+MvIBLaKgic5t9k/zEUYGaL0cNJ780NN/Tcf1/6a5BUeA7iwnGBE73cyPT2/loGJmp4xWrhm9YHtXJRIyNKTuie1CE+3vzCp0VGPUlesxPpyXJsZGn7dwawWqQBr0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768229972; c=relaxed/simple; bh=xdEKcnIuRvnkKprV7MZfKu9TFcwFGvDSVPZUZlgi+iI=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sve6CsycV822y7GT0KkVs3RIZ3eCECoIkMf08b0NBAx/ads1CEAuKE2DWY/TPPC912F/pfUYhsaGg99jXsrEY+ydT2kuTXEcpQNd89co8e1A043Jf8Wxg4X3eVJqJb1eUCa62Y9yStEWeQ65mGLBkZXdVJmRs2j9UJyFdxBtxcU= 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=H9PjDDfa; arc=none smtp.client-ip=91.218.175.185 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="H9PjDDfa" 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=1768229968; 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=6rIjtBtg4j5ppg7ai8t6gRwAk9XLgVvAUqy+c8sSBgU=; b=H9PjDDfaXBMQ3YazqTGBTfaTx4YSC2FQwKw/30z0UWzq+ed3zzXYSlfkIT8ETIdnWLrU41 JCprAhJs5gm4g8eKyrL4or249HqoXOcNtkyRDOzRqquvUGX5T4zHfOPvY4vM4pLQ531lZe V2SW/RDmrjWbJJL4sd8t7Cm5hDCz8B0= 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 v5 7/9] bpf: Add syscall common attributes support for map_create Date: Mon, 12 Jan 2026 22:56:14 +0800 Message-ID: <20260112145616.44195-8-leon.hwang@linux.dev> In-Reply-To: <20260112145616.44195-1-leon.hwang@linux.dev> References: <20260112145616.44195-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 9022e4f515f9..280beca480ea 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 0dba014ca055..6586d752970f 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_attr =3D attrs_common->attr; + struct bpf_verifier_log *log; + int err; + + memset(log_attr, 0, sizeof(*log_attr)); + log_attr->log_buf =3D common_attr->log_buf; + log_attr->log_size =3D common_attr->log_size; + log_attr->log_level =3D common_attr->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 d0440e640e40..52e1ab142da9 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 *common_attrs) +{ + struct bpf_verifier_log *log; + struct bpf_log_attr log_attr; + int err, ret; + + log =3D bpf_log_attr_create_vlog(&log_attr, common_attrs); + 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); @@ -6218,7 +6262,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(&common_attrs, &common_attr, uattr_common, size_common); + err =3D map_create(&attr, uattr, &common_attrs); break; case BPF_MAP_LOOKUP_ELEM: err =3D map_lookup_elem(&attr); --=20 2.52.0