* [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support
@ 2026-02-11 15:11 Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 1/8] " Leon Hwang
` (7 more replies)
0 siblings, 8 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
This patch series builds upon the discussion in
"[PATCH bpf-next v4 0/4] bpf: Improve error reporting for freplace attachment failure" [1].
This patch series introduces support for *common attributes* in the BPF
syscall, providing a unified mechanism for passing shared metadata across
all BPF commands, and uses it for BPF_PROG_LOAD, BPF_BTF_LOAD, and
BPF_MAP_CREATE.
The initial set of common attributes includes:
1. 'log_buf': User-provided buffer for storing log output.
2. 'log_size': Size of the provided log buffer.
3. 'log_level': Verbosity level for logging.
4. 'log_true_size': Actual log size reported by kernel.
With this extension, the BPF syscall will be able to return meaningful
error messages (e.g., failures of creating map), improving debuggability
and user experience.
Links:
[1] https://lore.kernel.org/bpf/20250224153352.64689-1-leon.hwang@linux.dev/
Changes:
v9 -> v10:
* Collect Acked-by from Andrii, thanks.
* Address comments from Andrii:
* Drop log NULL check in bpf_log_attr_finalize().
* Return -EFAULT early in bpf_log_attr_finalize().
* Validate whether log_buf, log_size, and log_level are set.
* Keep log_buf, log_size, log_level, and user-pointer log_true_size in struct
bpf_log_attr.
* Make prog_load and btf_load work with the new struct bpf_log_attr.
* Add comment to log_true_size of struct bpf_log_opts in libbpf.
* Address comment from Alexei:
* Avoid using BPF_LOG_FIXED as log_level in tests.
* v9: https://lore.kernel.org/bpf/20260202144046.30651-1-leon.hwang@linux.dev/
v8 -> v9:
* Rework reporting 'log_true_size' for prog_load, btf_load, and map_create to
simplify struct bpf_log_attr (per Alexei).
* v8: https://lore.kernel.org/bpf/20260126151409.52072-1-leon.hwang@linux.dev/
v7 -> v8:
* Return 0 when fd < 0 and errno != EFAULT in probe_sys_bpf_ext(), then simplify
probe_bpf_syscall_common_attrs() (per Alexei and Andrii).
* v7: https://lore.kernel.org/bpf/20260123032445.125259-1-leon.hwang@linux.dev/
v6 -> v7:
* Return -errno when fd < 0 and errno != EFAULT in probe_sys_bpf_ext().
* Convert return value of probe_sys_bpf_ext() to bool in
probe_bpf_syscall_common_attrs().
* Address comments from Andrii:
* Drop the comment, and handle fd >= 0 case explicitly in
probe_sys_bpf_ext().
* Return an error when fd >= 0 in probe_sys_bpf_ext().
* v6: https://lore.kernel.org/bpf/20260120152424.40766-1-leon.hwang@linux.dev/
v5 -> v6:
* Address comments from Andrii:
* Update some variables' name.
* Drop unnecessary 'close(fd)' in libbpf.
* Rename FEAT_EXTENDED_SYSCALL to FEAT_BPF_SYSCALL_COMMON_ATTRS with
updated description in libbpf.
* Use EINVAL instead of EUSERS, as EUSERS is not used in bpf yet.
* Rename struct bpf_syscall_common_attr_opts to bpf_log_opts in libbpf.
* Add 'OPTS_SET(log_opts, log_true_size, 0);' in libbpf's 'bpf_map_create()'.
* v5: https://lore.kernel.org/bpf/20260112145616.44195-1-leon.hwang@linux.dev/
v4 -> v5:
* Rework reporting 'log_true_size' for prog_load, btf_load, and map_create
(per Alexei).
* v4: https://lore.kernel.org/bpf/20260106172018.57757-1-leon.hwang@linux.dev/
RFC v3 -> v4:
* Drop RFC.
* Address comments from Andrii:
* Add parentheses in 'sys_bpf_ext()'.
* Avoid creating new fd in 'probe_sys_bpf_ext()'.
* Add a new struct to wrap log fields in libbpf.
* Address comments from Alexei:
* Do not skip writing to user space when log_true_size is zero.
* Do not use 'bool' arguments.
* Drop the adding WARN_ON_ONCE()'s.
* v3: https://lore.kernel.org/bpf/20251002154841.99348-1-leon.hwang@linux.dev/
RFC v2 -> RFC v3:
* Rename probe_sys_bpf_extended to probe_sys_bpf_ext.
* Refactor reporting 'log_true_size' for prog_load.
* Refactor reporting 'btf_log_true_size' for btf_load.
* Add warnings for internal bugs in map_create.
* Check log_true_size in test cases.
* Address comment from Alexei:
* Change kvzalloc/kvfree to kzalloc/kfree.
* Address comments from Andrii:
* Move BPF_COMMON_ATTRS to 'enum bpf_cmd' alongside brief comment.
* Add bpf_check_uarg_tail_zero() for extra checks.
* Rename sys_bpf_extended to sys_bpf_ext.
* Rename sys_bpf_fd_extended to sys_bpf_ext_fd.
* Probe the new feature using NULL and -EFAULT.
* Move probe_sys_bpf_ext to libbpf_internal.h and drop LIBBPF_API.
* Return -EUSERS when log attrs are conflict between bpf_attr and
bpf_common_attr.
* Avoid touching bpf_vlog_init().
* Update the reason messages in map_create.
* Finalize the log using __cleanup().
* Report log size to users.
* Change type of log_buf from '__u64' to 'const char *' and cast type
using ptr_to_u64() in bpf_map_create().
* Do not return -EOPNOTSUPP when kernel doesn't support this feature
in bpf_map_create().
* Add log_level support for map creation for consistency.
* Address comment from Eduard:
* Use common_attrs->log_level instead of BPF_LOG_FIXED.
* v2: https://lore.kernel.org/bpf/20250911163328.93490-1-leon.hwang@linux.dev/
RFC v1 -> RFC v2:
* Fix build error reported by test bot.
* Address comments from Alexei:
* Drop new uapi for freplace.
* Add common attributes support for prog_load and btf_load.
* Add common attributes support for map_create.
* v1: https://lore.kernel.org/bpf/20250728142346.95681-1-leon.hwang@linux.dev/
Leon Hwang (8):
bpf: Extend BPF syscall with common attributes support
libbpf: Add support for extended bpf syscall
bpf: Refactor reporting log_true_size for prog_load
bpf: Add syscall common attributes support for prog_load
bpf: Add syscall common attributes support for btf_load
bpf: Add syscall common attributes support for map_create
libbpf: Add syscall common attributes support for map_create
selftests/bpf: Add tests to verify map create failure log
include/linux/bpf.h | 4 +-
include/linux/bpf_verifier.h | 15 ++
include/linux/btf.h | 3 +-
include/linux/syscalls.h | 3 +-
include/uapi/linux/bpf.h | 8 +
kernel/bpf/btf.c | 30 +---
kernel/bpf/log.c | 84 +++++++++
kernel/bpf/syscall.c | 114 +++++++++---
kernel/bpf/verifier.c | 17 +-
tools/include/uapi/linux/bpf.h | 8 +
tools/lib/bpf/bpf.c | 52 +++++-
tools/lib/bpf/bpf.h | 17 +-
tools/lib/bpf/features.c | 8 +
tools/lib/bpf/libbpf_internal.h | 3 +
.../selftests/bpf/prog_tests/map_init.c | 166 ++++++++++++++++++
15 files changed, 471 insertions(+), 61 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 1/8] bpf: Extend BPF syscall with common attributes support
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 2/8] libbpf: Add support for extended bpf syscall Leon Hwang
` (6 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
Add generic BPF syscall support for passing common attributes.
The initial set of common attributes includes:
1. 'log_buf': User-provided buffer for storing logs.
2. 'log_size': Size of the log buffer.
3. 'log_level': Log verbosity level.
4. 'log_true_size': Actual log size reported by kernel.
The common-attribute pointer and its size are passed as the 4th and 5th
syscall arguments. A new command bit, 'BPF_COMMON_ATTRS' ('1 << 16'),
indicates that common attributes are supplied.
This commit adds syscall and uapi plumbing. Command-specific handling is
added in follow-up patches.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/syscalls.h | 3 ++-
include/uapi/linux/bpf.h | 8 ++++++++
kernel/bpf/syscall.c | 25 +++++++++++++++++++++----
tools/include/uapi/linux/bpf.h | 8 ++++++++
4 files changed, 39 insertions(+), 5 deletions(-)
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 6c8a570cf44a..aadbb7164ea5 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -937,7 +937,8 @@ asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
asmlinkage long sys_getrandom(char __user *buf, size_t count,
unsigned int flags);
asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags);
-asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size);
+asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size,
+ struct bpf_common_attr __user *attr_common, unsigned int size_common);
asmlinkage long sys_execveat(int dfd, const char __user *filename,
const char __user *const __user *argv,
const char __user *const __user *envp, int flags);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index c8d400b7680a..b2126c9641ec 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -994,6 +994,7 @@ enum bpf_cmd {
BPF_PROG_STREAM_READ_BY_FD,
BPF_PROG_ASSOC_STRUCT_OPS,
__MAX_BPF_CMD,
+ BPF_COMMON_ATTRS = 1 << 16, /* Indicate carrying syscall common attrs. */
};
enum bpf_map_type {
@@ -1500,6 +1501,13 @@ struct bpf_stack_build_id {
};
};
+struct bpf_common_attr {
+ __u64 log_buf;
+ __u32 log_size;
+ __u32 log_level;
+ __u32 log_true_size;
+};
+
#define BPF_OBJ_NAME_LEN 16U
enum {
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 683c332dbafb..0e231c0b1d04 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6186,8 +6186,10 @@ static int prog_assoc_struct_ops(union bpf_attr *attr)
return ret;
}
-static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
+static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
+ bpfptr_t uattr_common, unsigned int size_common)
{
+ struct bpf_common_attr attr_common;
union bpf_attr attr;
int err;
@@ -6201,6 +6203,20 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
if (copy_from_bpfptr(&attr, uattr, size) != 0)
return -EFAULT;
+ memset(&attr_common, 0, sizeof(attr_common));
+ if (cmd & BPF_COMMON_ATTRS) {
+ err = bpf_check_uarg_tail_zero(uattr_common, sizeof(attr_common), size_common);
+ if (err)
+ return err;
+
+ cmd &= ~BPF_COMMON_ATTRS;
+ size_common = min_t(u32, size_common, sizeof(attr_common));
+ if (copy_from_bpfptr(&attr_common, uattr_common, size_common) != 0)
+ return -EFAULT;
+ } else {
+ size_common = 0;
+ }
+
err = security_bpf(cmd, &attr, size, uattr.is_kernel);
if (err < 0)
return err;
@@ -6336,9 +6352,10 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size)
return err;
}
-SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size)
+SYSCALL_DEFINE5(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, size,
+ struct bpf_common_attr __user *, uattr_common, unsigned int, size_common)
{
- return __sys_bpf(cmd, USER_BPFPTR(uattr), size);
+ return __sys_bpf(cmd, USER_BPFPTR(uattr), size, USER_BPFPTR(uattr_common), size_common);
}
static bool syscall_prog_is_valid_access(int off, int size,
@@ -6369,7 +6386,7 @@ BPF_CALL_3(bpf_sys_bpf, int, cmd, union bpf_attr *, attr, u32, attr_size)
default:
return -EINVAL;
}
- return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size);
+ return __sys_bpf(cmd, KERNEL_BPFPTR(attr), attr_size, KERNEL_BPFPTR(NULL), 0);
}
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 5e38b4887de6..c4934c2370fd 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -994,6 +994,7 @@ enum bpf_cmd {
BPF_PROG_STREAM_READ_BY_FD,
BPF_PROG_ASSOC_STRUCT_OPS,
__MAX_BPF_CMD,
+ BPF_COMMON_ATTRS = 1 << 16, /* Indicate carrying syscall common attrs. */
};
enum bpf_map_type {
@@ -1500,6 +1501,13 @@ struct bpf_stack_build_id {
};
};
+struct bpf_common_attr {
+ __u64 log_buf;
+ __u32 log_size;
+ __u32 log_level;
+ __u32 log_true_size;
+};
+
#define BPF_OBJ_NAME_LEN 16U
enum {
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 2/8] libbpf: Add support for extended bpf syscall
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 1/8] " Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load Leon Hwang
` (5 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
To support the extended BPF syscall introduced in the previous commit,
introduce the following internal APIs:
* 'sys_bpf_ext()'
* 'sys_bpf_ext_fd()'
They wrap the raw 'syscall()' interface to support passing extended
attributes.
* 'probe_sys_bpf_ext()'
Check whether current kernel supports the BPF syscall common attributes.
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
tools/lib/bpf/bpf.c | 36 +++++++++++++++++++++++++++++++++
tools/lib/bpf/features.c | 8 ++++++++
tools/lib/bpf/libbpf_internal.h | 3 +++
3 files changed, 47 insertions(+)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 5846de364209..9d8740761b7a 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -69,6 +69,42 @@ static inline __u64 ptr_to_u64(const void *ptr)
return (__u64) (unsigned long) ptr;
}
+static inline int sys_bpf_ext(enum bpf_cmd cmd, union bpf_attr *attr,
+ unsigned int size,
+ struct bpf_common_attr *attr_common,
+ unsigned int size_common)
+{
+ cmd = attr_common ? (cmd | BPF_COMMON_ATTRS) : (cmd & ~BPF_COMMON_ATTRS);
+ return syscall(__NR_bpf, cmd, attr, size, attr_common, size_common);
+}
+
+static inline int sys_bpf_ext_fd(enum bpf_cmd cmd, union bpf_attr *attr,
+ unsigned int size,
+ struct bpf_common_attr *attr_common,
+ unsigned int size_common)
+{
+ int fd;
+
+ fd = sys_bpf_ext(cmd, attr, size, attr_common, size_common);
+ return ensure_good_fd(fd);
+}
+
+int probe_sys_bpf_ext(void)
+{
+ const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
+ union bpf_attr attr;
+ int fd;
+
+ memset(&attr, 0, attr_sz);
+ fd = syscall(__NR_bpf, BPF_PROG_LOAD | BPF_COMMON_ATTRS, &attr, attr_sz, NULL,
+ sizeof(struct bpf_common_attr));
+ if (fd >= 0) {
+ close(fd);
+ return -EINVAL;
+ }
+ return errno == EFAULT ? 1 : 0;
+}
+
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size)
{
diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
index b842b83e2480..e0d646a9e233 100644
--- a/tools/lib/bpf/features.c
+++ b/tools/lib/bpf/features.c
@@ -506,6 +506,11 @@ static int probe_kern_arg_ctx_tag(int token_fd)
return probe_fd(prog_fd);
}
+static int probe_bpf_syscall_common_attrs(int token_fd)
+{
+ return probe_sys_bpf_ext();
+}
+
typedef int (*feature_probe_fn)(int /* token_fd */);
static struct kern_feature_cache feature_cache;
@@ -581,6 +586,9 @@ static struct kern_feature_desc {
[FEAT_BTF_QMARK_DATASEC] = {
"BTF DATASEC names starting from '?'", probe_kern_btf_qmark_datasec,
},
+ [FEAT_BPF_SYSCALL_COMMON_ATTRS] = {
+ "BPF syscall common attributes support", probe_bpf_syscall_common_attrs,
+ },
};
bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_id)
diff --git a/tools/lib/bpf/libbpf_internal.h b/tools/lib/bpf/libbpf_internal.h
index fc59b21b51b5..aa16be869c4f 100644
--- a/tools/lib/bpf/libbpf_internal.h
+++ b/tools/lib/bpf/libbpf_internal.h
@@ -392,6 +392,8 @@ enum kern_feature_id {
FEAT_ARG_CTX_TAG,
/* Kernel supports '?' at the front of datasec names */
FEAT_BTF_QMARK_DATASEC,
+ /* Kernel supports BPF syscall common attributes */
+ FEAT_BPF_SYSCALL_COMMON_ATTRS,
__FEAT_CNT,
};
@@ -757,4 +759,5 @@ int probe_fd(int fd);
#define SHA256_DWORD_SIZE SHA256_DIGEST_LENGTH / sizeof(__u64)
void libbpf_sha256(const void *data, size_t len, __u8 out[SHA256_DIGEST_LENGTH]);
+int probe_sys_bpf_ext(void);
#endif /* __LIBBPF_LIBBPF_INTERNAL_H */
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 1/8] " Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 2/8] libbpf: Add support for extended bpf syscall Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 22:10 ` Andrii Nakryiko
2026-03-03 16:32 ` Alexei Starovoitov
2026-02-11 15:11 ` [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support " Leon Hwang
` (4 subsequent siblings)
7 siblings, 2 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
The next commit will add support for reporting logs via extended common
attributes, including 'log_true_size'.
To prepare for that, refactor the 'log_true_size' reporting logic by
introducing a new struct bpf_log_attr to encapsulate log-related behavior:
* bpf_log_attr_init(): initialize log fields, which will support
extended common attributes in the next commit.
* bpf_log_attr_finalize(): handle log finalization and write back
'log_true_size' to userspace.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf.h | 4 +++-
include/linux/bpf_verifier.h | 11 +++++++++++
kernel/bpf/log.c | 25 +++++++++++++++++++++++++
kernel/bpf/syscall.c | 13 ++++++++++---
kernel/bpf/verifier.c | 17 ++++-------------
5 files changed, 53 insertions(+), 17 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index cd9b96434904..d4dbcc7ad156 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -2913,7 +2913,9 @@ int bpf_check_uarg_tail_zero(bpfptr_t uaddr, size_t expected_size,
size_t actual_size);
/* verify correctness of eBPF program */
-int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size);
+struct bpf_log_attr;
+int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr,
+ struct bpf_log_attr *attr_log);
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index ef8e45a362d9..dbd9bdb955b3 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -635,6 +635,17 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
return log && log->level;
}
+struct bpf_log_attr {
+ char __user *log_buf;
+ u32 log_size;
+ u32 log_level;
+ u32 __user *log_true_size;
+};
+
+int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
+ u32 __user *log_true_size);
+int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log);
+
#define BPF_MAX_SUBPROGS 256
struct bpf_subprog_arg_info {
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index a0c3b35de2ce..e31747b84fe2 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -863,3 +863,28 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
}
print_verifier_state(env, vstate, frameno, false);
}
+
+int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
+ u32 __user *log_true_size)
+{
+ memset(log, 0, sizeof(*log));
+ log->log_buf = u64_to_user_ptr(log_buf);
+ log->log_size = log_size;
+ log->log_level = log_level;
+ log->log_true_size = log_true_size;
+ return 0;
+}
+
+int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
+{
+ u32 log_true_size;
+ int err;
+
+ err = bpf_vlog_finalize(log, &log_true_size);
+
+ if (attr->log_true_size && copy_to_user(attr->log_true_size, &log_true_size,
+ sizeof(log_true_size)))
+ return -EFAULT;
+
+ return err;
+}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 0e231c0b1d04..e86674811996 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2867,7 +2867,7 @@ static int bpf_prog_mark_insn_arrays_ready(struct bpf_prog *prog)
/* last field in 'union bpf_attr' used by this command */
#define BPF_PROG_LOAD_LAST_FIELD keyring_id
-static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
+static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_attr *attr_log)
{
enum bpf_prog_type type = attr->prog_type;
struct bpf_prog *prog, *dst_prog = NULL;
@@ -3085,7 +3085,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
goto free_prog_sec;
/* run eBPF verifier */
- err = bpf_check(&prog, attr, uattr, uattr_size);
+ err = bpf_check(&prog, attr, uattr, attr_log);
if (err < 0)
goto free_used_maps;
@@ -6189,7 +6189,10 @@ static int prog_assoc_struct_ops(union bpf_attr *attr)
static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
bpfptr_t uattr_common, unsigned int size_common)
{
+ bool from_user = !bpfptr_is_kernel(uattr);
struct bpf_common_attr attr_common;
+ u32 __user *log_true_size = NULL;
+ struct bpf_log_attr attr_log;
union bpf_attr attr;
int err;
@@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
err = map_freeze(&attr);
break;
case BPF_PROG_LOAD:
- err = bpf_prog_load(&attr, uattr, size);
+ if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
+ log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
+ err = bpf_log_attr_init(&attr_log, attr.log_buf, attr.log_size, attr.log_level,
+ log_true_size);
+ err = err ?: bpf_prog_load(&attr, uattr, &attr_log);
break;
case BPF_OBJ_PIN:
err = bpf_obj_pin(&attr);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index edf5342b982f..f1447b1878fd 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -25840,12 +25840,12 @@ static int compute_scc(struct bpf_verifier_env *env)
return err;
}
-int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u32 uattr_size)
+int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
+ struct bpf_log_attr *attr_log)
{
u64 start_time = ktime_get_ns();
struct bpf_verifier_env *env;
int i, len, ret = -EINVAL, err;
- u32 log_true_size;
bool is_priv;
BTF_TYPE_EMIT(enum bpf_features);
@@ -25892,9 +25892,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
/* user could have requested verbose verifier output
* and supplied buffer to store the verification trace
*/
- ret = bpf_vlog_init(&env->log, attr->log_level,
- (char __user *) (unsigned long) attr->log_buf,
- attr->log_size);
+ ret = bpf_vlog_init(&env->log, attr_log->log_level, attr_log->log_buf, attr_log->log_size);
if (ret)
goto err_unlock;
@@ -26044,17 +26042,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
env->prog->aux->verified_insns = env->insn_processed;
/* preserve original error even if log finalization is successful */
- err = bpf_vlog_finalize(&env->log, &log_true_size);
+ err = bpf_log_attr_finalize(attr_log, &env->log);
if (err)
ret = err;
- if (uattr_size >= offsetofend(union bpf_attr, log_true_size) &&
- copy_to_bpfptr_offset(uattr, offsetof(union bpf_attr, log_true_size),
- &log_true_size, sizeof(log_true_size))) {
- ret = -EFAULT;
- goto err_release_maps;
- }
-
if (ret)
goto err_release_maps;
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support for prog_load
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
` (2 preceding siblings ...)
2026-02-11 15:11 ` [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 22:08 ` Andrii Nakryiko
2026-02-11 15:11 ` [PATCH bpf-next v10 5/8] bpf: Add syscall common attributes support for btf_load Leon Hwang
` (3 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
BPF_PROG_LOAD can now take log parameters from both union bpf_attr and
struct bpf_common_attr. The merge rules are:
- if both sides provide a complete log tuple (buf/size/level) and they
match, use it;
- if only one side provides log parameters, use that one;
- if both sides provide complete tuples but they differ, return -EINVAL.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf_verifier.h | 3 ++-
kernel/bpf/log.c | 31 ++++++++++++++++++++++++++++++-
kernel/bpf/syscall.c | 2 +-
3 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index dbd9bdb955b3..34f28d40022a 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -643,7 +643,8 @@ struct bpf_log_attr {
};
int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
- u32 __user *log_true_size);
+ u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
+ u32 size);
int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log);
#define BPF_MAX_SUBPROGS 256
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index e31747b84fe2..a2b41bf5e9cb 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -864,14 +864,43 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
print_verifier_state(env, vstate, frameno, false);
}
+static bool bpf_log_attrs_set(u64 log_buf, u32 log_size, u32 log_level)
+{
+ return log_buf && log_size && log_level;
+}
+
+static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
+ u32 log_level)
+{
+ return bpf_log_attrs_set(log_buf, log_size, log_level) &&
+ bpf_log_attrs_set(common->log_buf, common->log_size, common->log_level) &&
+ (log_buf != common->log_buf || log_size != common->log_size ||
+ log_level != common->log_level);
+}
+
int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
- u32 __user *log_true_size)
+ u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
+ u32 size)
{
+ if (bpf_log_attrs_diff(common, log_buf, log_size, log_level))
+ return -EINVAL;
+
memset(log, 0, sizeof(*log));
log->log_buf = u64_to_user_ptr(log_buf);
log->log_size = log_size;
log->log_level = log_level;
log->log_true_size = log_true_size;
+
+ if (!log_buf && common->log_buf) {
+ log->log_buf = u64_to_user_ptr(common->log_buf);
+ log->log_size = common->log_size;
+ log->log_level = common->log_level;
+ if (size >= offsetofend(struct bpf_common_attr, log_true_size))
+ log->log_true_size = uattr.user +
+ offsetof(struct bpf_common_attr, log_true_size);
+ else
+ log->log_true_size = NULL;
+ }
return 0;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e86674811996..17116603ff51 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6247,7 +6247,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
err = bpf_log_attr_init(&attr_log, attr.log_buf, attr.log_size, attr.log_level,
- log_true_size);
+ log_true_size, &attr_common, uattr_common, size_common);
err = err ?: bpf_prog_load(&attr, uattr, &attr_log);
break;
case BPF_OBJ_PIN:
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 5/8] bpf: Add syscall common attributes support for btf_load
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
` (3 preceding siblings ...)
2026-02-11 15:11 ` [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support " Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 22:11 ` Andrii Nakryiko
2026-02-11 15:11 ` [PATCH bpf-next v10 6/8] bpf: Add syscall common attributes support for map_create Leon Hwang
` (2 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
BPF_BTF_LOAD can now take log parameters from both union bpf_attr and
struct bpf_common_attr, with the same merge rules as BPF_PROG_LOAD:
- if both sides provide a complete log tuple (buf/size/level) and they
match, use it;
- if only one side provides log parameters, use that one;
- if both sides provide complete tuples but they differ, return -EINVAL.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/btf.h | 3 ++-
kernel/bpf/btf.c | 30 +++++++-----------------------
kernel/bpf/syscall.c | 11 ++++++++---
3 files changed, 17 insertions(+), 27 deletions(-)
diff --git a/include/linux/btf.h b/include/linux/btf.h
index 48108471c5b1..f64d87315c5f 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -145,7 +145,8 @@ const char *btf_get_name(const struct btf *btf);
void btf_get(struct btf *btf);
void btf_put(struct btf *btf);
const struct btf_header *btf_header(const struct btf *btf);
-int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_sz);
+struct bpf_log_attr;
+int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_attr *attr_log);
struct btf *btf_get_by_fd(int fd);
int btf_get_info_by_fd(const struct btf *btf,
const union bpf_attr *attr,
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index 7708958e3fb8..810007028b72 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5857,25 +5857,10 @@ static int btf_check_type_tags(struct btf_verifier_env *env,
return 0;
}
-static int finalize_log(struct bpf_verifier_log *log, bpfptr_t uattr, u32 uattr_size)
-{
- u32 log_true_size;
- int err;
-
- err = bpf_vlog_finalize(log, &log_true_size);
-
- if (uattr_size >= offsetofend(union bpf_attr, btf_log_true_size) &&
- copy_to_bpfptr_offset(uattr, offsetof(union bpf_attr, btf_log_true_size),
- &log_true_size, sizeof(log_true_size)))
- err = -EFAULT;
-
- return err;
-}
-
-static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
+static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr,
+ struct bpf_log_attr *attr_log)
{
bpfptr_t btf_data = make_bpfptr(attr->btf, uattr.is_kernel);
- char __user *log_ubuf = u64_to_user_ptr(attr->btf_log_buf);
struct btf_struct_metas *struct_meta_tab;
struct btf_verifier_env *env = NULL;
struct btf *btf = NULL;
@@ -5892,8 +5877,7 @@ static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr, u32 uat
/* user could have requested verbose verifier output
* and supplied buffer to store the verification trace
*/
- err = bpf_vlog_init(&env->log, attr->btf_log_level,
- log_ubuf, attr->btf_log_size);
+ err = bpf_vlog_init(&env->log, attr_log->log_level, attr_log->log_buf, attr_log->log_size);
if (err)
goto errout_free;
@@ -5954,7 +5938,7 @@ static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr, u32 uat
}
}
- err = finalize_log(&env->log, uattr, uattr_size);
+ err = bpf_log_attr_finalize(attr_log, &env->log);
if (err)
goto errout_free;
@@ -5966,7 +5950,7 @@ static struct btf *btf_parse(const union bpf_attr *attr, bpfptr_t uattr, u32 uat
btf_free_struct_meta_tab(btf);
errout:
/* overwrite err with -ENOSPC or -EFAULT */
- ret = finalize_log(&env->log, uattr, uattr_size);
+ ret = bpf_log_attr_finalize(attr_log, &env->log);
if (ret)
err = ret;
errout_free:
@@ -8137,12 +8121,12 @@ static int __btf_new_fd(struct btf *btf)
return anon_inode_getfd("btf", &btf_fops, btf, O_RDONLY | O_CLOEXEC);
}
-int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
+int btf_new_fd(const union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_attr *attr_log)
{
struct btf *btf;
int ret;
- btf = btf_parse(attr, uattr, uattr_size);
+ btf = btf_parse(attr, uattr, attr_log);
if (IS_ERR(btf))
return PTR_ERR(btf);
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 17116603ff51..6d727a4b5121 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5448,7 +5448,7 @@ static int bpf_obj_get_info_by_fd(const union bpf_attr *attr,
#define BPF_BTF_LOAD_LAST_FIELD btf_token_fd
-static int bpf_btf_load(const union bpf_attr *attr, bpfptr_t uattr, __u32 uattr_size)
+static int bpf_btf_load(const union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_attr *attr_log)
{
struct bpf_token *token = NULL;
@@ -5475,7 +5475,7 @@ static int bpf_btf_load(const union bpf_attr *attr, bpfptr_t uattr, __u32 uattr_
bpf_token_put(token);
- return btf_new_fd(attr, uattr, uattr_size);
+ return btf_new_fd(attr, uattr, attr_log);
}
#define BPF_BTF_GET_FD_BY_ID_LAST_FIELD fd_by_id_token_fd
@@ -6293,7 +6293,12 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
err = bpf_raw_tracepoint_open(&attr);
break;
case BPF_BTF_LOAD:
- err = bpf_btf_load(&attr, uattr, size);
+ if (from_user && size >= offsetofend(union bpf_attr, btf_log_true_size))
+ log_true_size = uattr.user + offsetof(union bpf_attr, btf_log_true_size);
+ err = bpf_log_attr_init(&attr_log, attr.btf_log_buf, attr.btf_log_size,
+ attr.btf_log_level, log_true_size, &attr_common,
+ uattr_common, size_common);
+ err = err ?: bpf_btf_load(&attr, uattr, &attr_log);
break;
case BPF_BTF_GET_FD_BY_ID:
err = bpf_btf_get_fd_by_id(&attr);
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 6/8] bpf: Add syscall common attributes support for map_create
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
` (4 preceding siblings ...)
2026-02-11 15:11 ` [PATCH bpf-next v10 5/8] bpf: Add syscall common attributes support for btf_load Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 7/8] libbpf: " Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 8/8] selftests/bpf: Add tests to verify map create failure log Leon Hwang
7 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
Many BPF_MAP_CREATE validation failures currently return -EINVAL without
any explanation to userspace.
Plumb common syscall log attributes into map_create(), create a verifier
log from bpf_common_attr::log_buf/log_size/log_level, and report
map-creation failure reasons through that buffer.
This improves debuggability by allowing userspace to inspect why map
creation failed and read back log_true_size from common attributes.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf_verifier.h | 3 ++
kernel/bpf/log.c | 30 +++++++++++++++++
kernel/bpf/syscall.c | 65 ++++++++++++++++++++++++++++++------
3 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 34f28d40022a..52627a93338f 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -645,6 +645,9 @@ struct bpf_log_attr {
int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
u32 size);
+struct bpf_verifier_log *bpf_log_attr_create_vlog(struct bpf_log_attr *attr_log,
+ struct bpf_common_attr *common, bpfptr_t uattr,
+ u32 size);
int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log);
#define BPF_MAX_SUBPROGS 256
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index a2b41bf5e9cb..f7251217452e 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -904,6 +904,36 @@ int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 l
return 0;
}
+
+struct bpf_verifier_log *bpf_log_attr_create_vlog(struct bpf_log_attr *attr_log,
+ struct bpf_common_attr *common, bpfptr_t uattr,
+ u32 size)
+{
+ struct bpf_verifier_log *log;
+ int err;
+
+ memset(attr_log, 0, sizeof(*attr_log));
+ if (size >= offsetofend(struct bpf_common_attr, log_true_size))
+ attr_log->log_true_size = uattr.user + offsetof(struct bpf_common_attr,
+ log_true_size);
+
+ if (!common->log_buf)
+ return NULL;
+
+ log = kzalloc_obj(*log, GFP_KERNEL);
+ if (!log)
+ return ERR_PTR(-ENOMEM);
+
+ err = bpf_vlog_init(log, common->log_level, u64_to_user_ptr(common->log_buf),
+ common->log_size);
+ if (err) {
+ kfree(log);
+ return ERR_PTR(err);
+ }
+
+ return log;
+}
+
int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
{
u32 log_true_size;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6d727a4b5121..04bb4a905559 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -1365,7 +1365,7 @@ static int map_check_btf(struct bpf_map *map, struct bpf_token *token,
#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_verifier_log *log)
{
const struct bpf_map_ops *ops;
struct bpf_token *token = NULL;
@@ -1377,8 +1377,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
int err;
err = CHECK_ATTR(BPF_MAP_CREATE);
- if (err)
+ if (err) {
+ bpf_log(log, "Invalid attr.\n");
return -EINVAL;
+ }
/* 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
@@ -1387,17 +1389,25 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
attr->map_flags &= ~BPF_F_TOKEN_FD;
if (attr->btf_vmlinux_value_type_id) {
- if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS ||
- attr->btf_key_type_id || attr->btf_value_type_id)
+ if (attr->map_type != BPF_MAP_TYPE_STRUCT_OPS) {
+ bpf_log(log, "btf_vmlinux_value_type_id can only be used with struct_ops 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;
}
if (attr->map_type != BPF_MAP_TYPE_BLOOM_FILTER &&
attr->map_type != BPF_MAP_TYPE_ARENA &&
- attr->map_extra != 0)
+ attr->map_extra != 0) {
+ bpf_log(log, "Invalid map_extra.\n");
return -EINVAL;
+ }
f_flags = bpf_get_file_flag(attr->map_flags);
if (f_flags < 0)
@@ -1405,13 +1415,17 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
if (numa_node != NUMA_NO_NODE &&
((unsigned int)numa_node >= nr_node_ids ||
- !node_online(numa_node)))
+ !node_online(numa_node))) {
+ bpf_log(log, "Invalid numa_node.\n");
return -EINVAL;
+ }
/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
map_type = attr->map_type;
- if (map_type >= ARRAY_SIZE(bpf_map_types))
+ if (map_type >= ARRAY_SIZE(bpf_map_types)) {
+ bpf_log(log, "Invalid map_type.\n");
return -EINVAL;
+ }
map_type = array_index_nospec(map_type, ARRAY_SIZE(bpf_map_types));
ops = bpf_map_types[map_type];
if (!ops)
@@ -1429,8 +1443,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
if (token_flag) {
token = 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);
+ }
/* if current token doesn't grant map creation permissions,
* then we can't use this token, so ignore it and rely on
@@ -1513,8 +1529,10 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
err = 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;
+ }
preempt_disable();
map->cookie = gen_cookie_next(&bpf_map_cookie);
@@ -1537,6 +1555,7 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
btf = btf_get_by_fd(attr->btf_fd);
if (IS_ERR(btf)) {
+ bpf_log(log, "Invalid btf_fd.\n");
err = PTR_ERR(btf);
goto free_map;
}
@@ -1564,6 +1583,7 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
bpfptr_t uprog_hash = make_bpfptr(attr->excl_prog_hash, uattr.is_kernel);
if (attr->excl_prog_hash_size != SHA256_DIGEST_SIZE) {
+ bpf_log(log, "Invalid excl_prog_hash_size.\n");
err = -EINVAL;
goto free_map;
}
@@ -1579,6 +1599,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 = -EINVAL;
goto free_map;
}
@@ -1617,6 +1638,30 @@ static int map_create(union bpf_attr *attr, bpfptr_t uattr)
return err;
}
+static int map_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_attr *attr_common,
+ bpfptr_t uattr_common, u32 size_common)
+{
+ struct bpf_verifier_log *log;
+ struct bpf_log_attr attr_log;
+ int err, ret;
+
+ log = bpf_log_attr_create_vlog(&attr_log, attr_common, uattr_common, size_common);
+ if (IS_ERR(log))
+ return PTR_ERR(log);
+
+ err = __map_create(attr, uattr, log);
+ if (err >= 0)
+ goto free;
+
+ ret = bpf_log_attr_finalize(&attr_log, log);
+ if (ret)
+ err = ret;
+
+free:
+ kfree(log);
+ return err;
+}
+
void bpf_map_inc(struct bpf_map *map)
{
atomic64_inc(&map->refcnt);
@@ -6226,7 +6271,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
switch (cmd) {
case BPF_MAP_CREATE:
- err = map_create(&attr, uattr);
+ err = map_create(&attr, uattr, &attr_common, uattr_common, size_common);
break;
case BPF_MAP_LOOKUP_ELEM:
err = map_lookup_elem(&attr);
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 7/8] libbpf: Add syscall common attributes support for map_create
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
` (5 preceding siblings ...)
2026-02-11 15:11 ` [PATCH bpf-next v10 6/8] bpf: Add syscall common attributes support for map_create Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 8/8] selftests/bpf: Add tests to verify map create failure log Leon Hwang
7 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
With the previous commit adding common attribute support for
BPF_MAP_CREATE, users can now retrieve detailed error messages when map
creation fails via the log_buf field.
Introduce struct bpf_log_opts with the following fields:
log_buf, log_size, log_level, and log_true_size.
Extend bpf_map_create_opts with a new field log_opts, allowing users to
capture and inspect log messages on map creation failures.
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
tools/lib/bpf/bpf.c | 16 +++++++++++++++-
tools/lib/bpf/bpf.h | 17 ++++++++++++++++-
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 9d8740761b7a..0c3e40844d80 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -209,6 +209,9 @@ int bpf_map_create(enum bpf_map_type map_type,
const struct bpf_map_create_opts *opts)
{
const size_t attr_sz = offsetofend(union bpf_attr, excl_prog_hash_size);
+ const size_t attr_common_sz = sizeof(struct bpf_common_attr);
+ struct bpf_common_attr attr_common;
+ struct bpf_log_opts *log_opts;
union bpf_attr attr;
int fd;
@@ -242,7 +245,18 @@ int bpf_map_create(enum bpf_map_type map_type,
attr.excl_prog_hash = ptr_to_u64(OPTS_GET(opts, excl_prog_hash, NULL));
attr.excl_prog_hash_size = OPTS_GET(opts, excl_prog_hash_size, 0);
- fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
+ log_opts = OPTS_GET(opts, log_opts, NULL);
+ if (log_opts && feat_supported(NULL, FEAT_BPF_SYSCALL_COMMON_ATTRS)) {
+ memset(&attr_common, 0, attr_common_sz);
+ attr_common.log_buf = ptr_to_u64(OPTS_GET(log_opts, log_buf, NULL));
+ attr_common.log_size = OPTS_GET(log_opts, log_size, 0);
+ attr_common.log_level = OPTS_GET(log_opts, log_level, 0);
+ fd = sys_bpf_ext_fd(BPF_MAP_CREATE, &attr, attr_sz, &attr_common, attr_common_sz);
+ OPTS_SET(log_opts, log_true_size, attr_common.log_true_size);
+ } else {
+ fd = sys_bpf_fd(BPF_MAP_CREATE, &attr, attr_sz);
+ OPTS_SET(log_opts, log_true_size, 0);
+ }
return libbpf_err_errno(fd);
}
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index 2c8e88ddb674..db834f09799e 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -37,6 +37,18 @@ extern "C" {
LIBBPF_API int libbpf_set_memlock_rlim(size_t memlock_bytes);
+struct bpf_log_opts {
+ size_t sz; /* size of this struct for forward/backward compatibility */
+
+ char *log_buf;
+ __u32 log_size;
+ __u32 log_level;
+ __u32 log_true_size; /* out parameter set by kernel */
+
+ size_t :0;
+};
+#define bpf_log_opts__last_field log_true_size
+
struct bpf_map_create_opts {
size_t sz; /* size of this struct for forward/backward compatibility */
@@ -57,9 +69,12 @@ struct bpf_map_create_opts {
const void *excl_prog_hash;
__u32 excl_prog_hash_size;
+
+ struct bpf_log_opts *log_opts;
+
size_t :0;
};
-#define bpf_map_create_opts__last_field excl_prog_hash_size
+#define bpf_map_create_opts__last_field log_opts
LIBBPF_API int bpf_map_create(enum bpf_map_type map_type,
const char *map_name,
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf-next v10 8/8] selftests/bpf: Add tests to verify map create failure log
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
` (6 preceding siblings ...)
2026-02-11 15:11 ` [PATCH bpf-next v10 7/8] libbpf: " Leon Hwang
@ 2026-02-11 15:11 ` Leon Hwang
7 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-11 15:11 UTC (permalink / raw)
To: bpf
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, linux-api,
linux-kselftest, kernel-patches-bot
Add tests to verify that the kernel reports the expected error messages
when map creation fails.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
.../selftests/bpf/prog_tests/map_init.c | 166 ++++++++++++++++++
1 file changed, 166 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/map_init.c b/tools/testing/selftests/bpf/prog_tests/map_init.c
index 14a31109dd0e..b8b727e24b5e 100644
--- a/tools/testing/selftests/bpf/prog_tests/map_init.c
+++ b/tools/testing/selftests/bpf/prog_tests/map_init.c
@@ -212,3 +212,169 @@ void test_map_init(void)
if (test__start_subtest("pcpu_lru_map_init"))
test_pcpu_lru_map_init();
}
+
+static void test_map_create(enum bpf_map_type map_type, const char *map_name,
+ struct bpf_map_create_opts *opts, const char *exp_msg)
+{
+ const int key_size = 4, value_size = 4, max_entries = 1;
+ char log_buf[128];
+ int fd;
+ LIBBPF_OPTS(bpf_log_opts, log_opts);
+
+ log_buf[0] = '\0';
+ log_opts.log_buf = log_buf;
+ log_opts.log_size = sizeof(log_buf);
+ log_opts.log_level = 1;
+ opts->log_opts = &log_opts;
+ fd = bpf_map_create(map_type, map_name, key_size, value_size, max_entries, opts);
+ if (!ASSERT_LT(fd, 0, "bpf_map_create")) {
+ close(fd);
+ return;
+ }
+
+ ASSERT_STREQ(log_buf, exp_msg, "log_buf");
+ ASSERT_EQ(log_opts.log_true_size, strlen(exp_msg) + 1, "log_true_size");
+}
+
+static void test_map_create_array(struct bpf_map_create_opts *opts, const char *exp_msg)
+{
+ test_map_create(BPF_MAP_TYPE_ARRAY, "test_map_create", opts, exp_msg);
+}
+
+static void test_invalid_vmlinux_value_type_id_struct_ops(void)
+{
+ const char *msg = "btf_vmlinux_value_type_id can only be used with struct_ops maps.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .btf_vmlinux_value_type_id = 1,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_vmlinux_value_type_id_kv_type_id(void)
+{
+ const char *msg = "btf_vmlinux_value_type_id is mutually exclusive with btf_key_type_id and btf_value_type_id.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .btf_vmlinux_value_type_id = 1,
+ .btf_key_type_id = 1,
+ );
+
+ test_map_create(BPF_MAP_TYPE_STRUCT_OPS, "test_map_create", &opts, msg);
+}
+
+static void test_invalid_value_type_id(void)
+{
+ const char *msg = "Invalid btf_value_type_id.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .btf_key_type_id = 1,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_map_extra(void)
+{
+ const char *msg = "Invalid map_extra.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .map_extra = 1,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_numa_node(void)
+{
+ const char *msg = "Invalid numa_node.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .map_flags = BPF_F_NUMA_NODE,
+ .numa_node = 0xFF,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_map_type(void)
+{
+ const char *msg = "Invalid map_type.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts);
+
+ test_map_create(__MAX_BPF_MAP_TYPE, "test_map_create", &opts, msg);
+}
+
+static void test_invalid_token_fd(void)
+{
+ const char *msg = "Invalid map_token_fd.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .map_flags = BPF_F_TOKEN_FD,
+ .token_fd = 0xFF,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_invalid_map_name(void)
+{
+ const char *msg = "Invalid map_name.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts);
+
+ test_map_create(BPF_MAP_TYPE_ARRAY, "test-!@#", &opts, msg);
+}
+
+static void test_invalid_btf_fd(void)
+{
+ const char *msg = "Invalid btf_fd.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .btf_fd = -1,
+ .btf_key_type_id = 1,
+ .btf_value_type_id = 1,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_excl_prog_hash_size_1(void)
+{
+ const char *msg = "Invalid excl_prog_hash_size.\n";
+ const char *hash = "DEADCODE";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .excl_prog_hash = hash,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+static void test_excl_prog_hash_size_2(void)
+{
+ const char *msg = "Invalid excl_prog_hash_size.\n";
+ LIBBPF_OPTS(bpf_map_create_opts, opts,
+ .excl_prog_hash_size = 1,
+ );
+
+ test_map_create_array(&opts, msg);
+}
+
+void test_map_create_failure(void)
+{
+ if (test__start_subtest("invalid_vmlinux_value_type_id_struct_ops"))
+ test_invalid_vmlinux_value_type_id_struct_ops();
+ if (test__start_subtest("invalid_vmlinux_value_type_id_kv_type_id"))
+ test_invalid_vmlinux_value_type_id_kv_type_id();
+ if (test__start_subtest("invalid_value_type_id"))
+ test_invalid_value_type_id();
+ if (test__start_subtest("invalid_map_extra"))
+ test_invalid_map_extra();
+ if (test__start_subtest("invalid_numa_node"))
+ test_invalid_numa_node();
+ if (test__start_subtest("invalid_map_type"))
+ test_invalid_map_type();
+ if (test__start_subtest("invalid_token_fd"))
+ test_invalid_token_fd();
+ if (test__start_subtest("invalid_map_name"))
+ test_invalid_map_name();
+ if (test__start_subtest("invalid_btf_fd"))
+ test_invalid_btf_fd();
+ if (test__start_subtest("invalid_excl_prog_hash_size_1"))
+ test_excl_prog_hash_size_1();
+ if (test__start_subtest("invalid_excl_prog_hash_size_2"))
+ test_excl_prog_hash_size_2();
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support for prog_load
2026-02-11 15:11 ` [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support " Leon Hwang
@ 2026-02-11 22:08 ` Andrii Nakryiko
2026-02-12 5:50 ` Leon Hwang
0 siblings, 1 reply; 19+ messages in thread
From: Andrii Nakryiko @ 2026-02-11 22:08 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, linux-kernel, linux-api, linux-kselftest,
kernel-patches-bot
On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> BPF_PROG_LOAD can now take log parameters from both union bpf_attr and
> struct bpf_common_attr. The merge rules are:
>
> - if both sides provide a complete log tuple (buf/size/level) and they
> match, use it;
> - if only one side provides log parameters, use that one;
> - if both sides provide complete tuples but they differ, return -EINVAL.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/bpf_verifier.h | 3 ++-
> kernel/bpf/log.c | 31 ++++++++++++++++++++++++++++++-
> kernel/bpf/syscall.c | 2 +-
> 3 files changed, 33 insertions(+), 3 deletions(-)
>
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index dbd9bdb955b3..34f28d40022a 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -643,7 +643,8 @@ struct bpf_log_attr {
> };
>
> int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> - u32 __user *log_true_size);
> + u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
> + u32 size);
> int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log);
>
> #define BPF_MAX_SUBPROGS 256
> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> index e31747b84fe2..a2b41bf5e9cb 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -864,14 +864,43 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
> print_verifier_state(env, vstate, frameno, false);
> }
>
> +static bool bpf_log_attrs_set(u64 log_buf, u32 log_size, u32 log_level)
> +{
> + return log_buf && log_size && log_level;
> +}
> +
> +static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
> + u32 log_level)
> +{
> + return bpf_log_attrs_set(log_buf, log_size, log_level) &&
> + bpf_log_attrs_set(common->log_buf, common->log_size, common->log_level) &&
> + (log_buf != common->log_buf || log_size != common->log_size ||
> + log_level != common->log_level);
> +}
> +
I'm not sure this check is doing what we discussed previously?... If
log_buf is set, but log_size or log_level is zero, you'll just ignore
log_buf here...
Maybe let's keep it super simple:
if (log_buf && common->log_buf && log_buf != common->log_buf)
return -EINVAL;
/* same for log_size, log_level, log_true_size */
and then below just
log->log_buf = u64_to_user_ptr(log_buf ?: common->log_buf);
log->log_size = log_size ?: common->log_size;
and so on
We can be stricter than that, of course (as in, all triplets have to
be completely set in either/both common_attr and attr, and they should
completely match), but it's just more code for little benefit.
> int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> - u32 __user *log_true_size)
> + u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
> + u32 size)
> {
> + if (bpf_log_attrs_diff(common, log_buf, log_size, log_level))
> + return -EINVAL;
> +
> memset(log, 0, sizeof(*log));
> log->log_buf = u64_to_user_ptr(log_buf);
> log->log_size = log_size;
> log->log_level = log_level;
> log->log_true_size = log_true_size;
> +
> + if (!log_buf && common->log_buf) {
> + log->log_buf = u64_to_user_ptr(common->log_buf);
> + log->log_size = common->log_size;
> + log->log_level = common->log_level;
> + if (size >= offsetofend(struct bpf_common_attr, log_true_size))
> + log->log_true_size = uattr.user +
> + offsetof(struct bpf_common_attr, log_true_size);
> + else
> + log->log_true_size = NULL;
why not treat log_true_size same as log_buf/log_level/log_size? If
both are provided, they should match, and then we don't have a
possibility of inconsistency?
> + }
> return 0;
> }
>
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index e86674811996..17116603ff51 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -6247,7 +6247,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
> if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
> log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
> err = bpf_log_attr_init(&attr_log, attr.log_buf, attr.log_size, attr.log_level,
> - log_true_size);
> + log_true_size, &attr_common, uattr_common, size_common);
> err = err ?: bpf_prog_load(&attr, uattr, &attr_log);
> break;
> case BPF_OBJ_PIN:
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-02-11 15:11 ` [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load Leon Hwang
@ 2026-02-11 22:10 ` Andrii Nakryiko
2026-02-12 5:50 ` Leon Hwang
2026-03-03 16:32 ` Alexei Starovoitov
1 sibling, 1 reply; 19+ messages in thread
From: Andrii Nakryiko @ 2026-02-11 22:10 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, linux-kernel, linux-api, linux-kselftest,
kernel-patches-bot
On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> The next commit will add support for reporting logs via extended common
> attributes, including 'log_true_size'.
>
> To prepare for that, refactor the 'log_true_size' reporting logic by
> introducing a new struct bpf_log_attr to encapsulate log-related behavior:
>
> * bpf_log_attr_init(): initialize log fields, which will support
> extended common attributes in the next commit.
> * bpf_log_attr_finalize(): handle log finalization and write back
> 'log_true_size' to userspace.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/bpf.h | 4 +++-
> include/linux/bpf_verifier.h | 11 +++++++++++
> kernel/bpf/log.c | 25 +++++++++++++++++++++++++
> kernel/bpf/syscall.c | 13 ++++++++++---
> kernel/bpf/verifier.c | 17 ++++-------------
> 5 files changed, 53 insertions(+), 17 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index cd9b96434904..d4dbcc7ad156 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -2913,7 +2913,9 @@ int bpf_check_uarg_tail_zero(bpfptr_t uaddr, size_t expected_size,
> size_t actual_size);
>
> /* verify correctness of eBPF program */
> -int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size);
> +struct bpf_log_attr;
> +int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr,
> + struct bpf_log_attr *attr_log);
>
> #ifndef CONFIG_BPF_JIT_ALWAYS_ON
> void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index ef8e45a362d9..dbd9bdb955b3 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -635,6 +635,17 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
> return log && log->level;
> }
>
> +struct bpf_log_attr {
> + char __user *log_buf;
> + u32 log_size;
> + u32 log_level;
> + u32 __user *log_true_size;
> +};
> +
> +int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> + u32 __user *log_true_size);
> +int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log);
> +
> #define BPF_MAX_SUBPROGS 256
>
> struct bpf_subprog_arg_info {
> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> index a0c3b35de2ce..e31747b84fe2 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -863,3 +863,28 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
> }
> print_verifier_state(env, vstate, frameno, false);
> }
> +
> +int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> + u32 __user *log_true_size)
> +{
> + memset(log, 0, sizeof(*log));
> + log->log_buf = u64_to_user_ptr(log_buf);
> + log->log_size = log_size;
> + log->log_level = log_level;
> + log->log_true_size = log_true_size;
> + return 0;
> +}
> +
> +int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
> +{
> + u32 log_true_size;
> + int err;
> +
> + err = bpf_vlog_finalize(log, &log_true_size);
> +
> + if (attr->log_true_size && copy_to_user(attr->log_true_size, &log_true_size,
> + sizeof(log_true_size)))
> + return -EFAULT;
> +
> + return err;
> +}
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 0e231c0b1d04..e86674811996 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -2867,7 +2867,7 @@ static int bpf_prog_mark_insn_arrays_ready(struct bpf_prog *prog)
> /* last field in 'union bpf_attr' used by this command */
> #define BPF_PROG_LOAD_LAST_FIELD keyring_id
>
> -static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
> +static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_attr *attr_log)
> {
> enum bpf_prog_type type = attr->prog_type;
> struct bpf_prog *prog, *dst_prog = NULL;
> @@ -3085,7 +3085,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
> goto free_prog_sec;
>
> /* run eBPF verifier */
> - err = bpf_check(&prog, attr, uattr, uattr_size);
> + err = bpf_check(&prog, attr, uattr, attr_log);
> if (err < 0)
> goto free_used_maps;
>
> @@ -6189,7 +6189,10 @@ static int prog_assoc_struct_ops(union bpf_attr *attr)
> static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
> bpfptr_t uattr_common, unsigned int size_common)
> {
> + bool from_user = !bpfptr_is_kernel(uattr);
> struct bpf_common_attr attr_common;
> + u32 __user *log_true_size = NULL;
> + struct bpf_log_attr attr_log;
> union bpf_attr attr;
> int err;
>
> @@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
> err = map_freeze(&attr);
> break;
> case BPF_PROG_LOAD:
> - err = bpf_prog_load(&attr, uattr, size);
> + if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
> + log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
LGTM, so
Acked-by: Andrii Nakryiko <andrii@kernel.org>
but it caught my eye that we will never return log_true_size if
SYSCALL program tried to load another BPF program (light skeleton
case), which seems limiting, but we can perhaps address that
separately as a follow up
> + err = bpf_log_attr_init(&attr_log, attr.log_buf, attr.log_size, attr.log_level,
> + log_true_size);
> + err = err ?: bpf_prog_load(&attr, uattr, &attr_log);
> break;
> case BPF_OBJ_PIN:
> err = bpf_obj_pin(&attr);
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index edf5342b982f..f1447b1878fd 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -25840,12 +25840,12 @@ static int compute_scc(struct bpf_verifier_env *env)
> return err;
> }
>
> -int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u32 uattr_size)
> +int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr,
> + struct bpf_log_attr *attr_log)
> {
> u64 start_time = ktime_get_ns();
> struct bpf_verifier_env *env;
> int i, len, ret = -EINVAL, err;
> - u32 log_true_size;
> bool is_priv;
>
> BTF_TYPE_EMIT(enum bpf_features);
> @@ -25892,9 +25892,7 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
> /* user could have requested verbose verifier output
> * and supplied buffer to store the verification trace
> */
> - ret = bpf_vlog_init(&env->log, attr->log_level,
> - (char __user *) (unsigned long) attr->log_buf,
> - attr->log_size);
> + ret = bpf_vlog_init(&env->log, attr_log->log_level, attr_log->log_buf, attr_log->log_size);
> if (ret)
> goto err_unlock;
>
> @@ -26044,17 +26042,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
> env->prog->aux->verified_insns = env->insn_processed;
>
> /* preserve original error even if log finalization is successful */
> - err = bpf_vlog_finalize(&env->log, &log_true_size);
> + err = bpf_log_attr_finalize(attr_log, &env->log);
> if (err)
> ret = err;
>
> - if (uattr_size >= offsetofend(union bpf_attr, log_true_size) &&
> - copy_to_bpfptr_offset(uattr, offsetof(union bpf_attr, log_true_size),
> - &log_true_size, sizeof(log_true_size))) {
> - ret = -EFAULT;
> - goto err_release_maps;
> - }
> -
> if (ret)
> goto err_release_maps;
>
> --
> 2.52.0
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 5/8] bpf: Add syscall common attributes support for btf_load
2026-02-11 15:11 ` [PATCH bpf-next v10 5/8] bpf: Add syscall common attributes support for btf_load Leon Hwang
@ 2026-02-11 22:11 ` Andrii Nakryiko
0 siblings, 0 replies; 19+ messages in thread
From: Andrii Nakryiko @ 2026-02-11 22:11 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, linux-kernel, linux-api, linux-kselftest,
kernel-patches-bot
On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> BPF_BTF_LOAD can now take log parameters from both union bpf_attr and
> struct bpf_common_attr, with the same merge rules as BPF_PROG_LOAD:
>
> - if both sides provide a complete log tuple (buf/size/level) and they
> match, use it;
> - if only one side provides log parameters, use that one;
> - if both sides provide complete tuples but they differ, return -EINVAL.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/btf.h | 3 ++-
> kernel/bpf/btf.c | 30 +++++++-----------------------
> kernel/bpf/syscall.c | 11 ++++++++---
> 3 files changed, 17 insertions(+), 27 deletions(-)
>
same remark about user space only log_true_size, but overall LGTM
Acked-by: Andrii Nakryiko <andrii@kernel.org>
[...]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support for prog_load
2026-02-11 22:08 ` Andrii Nakryiko
@ 2026-02-12 5:50 ` Leon Hwang
2026-02-18 18:44 ` Andrii Nakryiko
0 siblings, 1 reply; 19+ messages in thread
From: Leon Hwang @ 2026-02-12 5:50 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, linux-kernel, linux-api, linux-kselftest,
kernel-patches-bot
On 12/2/26 06:08, Andrii Nakryiko wrote:
> On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
[...]
>> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
>> index e31747b84fe2..a2b41bf5e9cb 100644
>> --- a/kernel/bpf/log.c
>> +++ b/kernel/bpf/log.c
>> @@ -864,14 +864,43 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
>> print_verifier_state(env, vstate, frameno, false);
>> }
>>
>> +static bool bpf_log_attrs_set(u64 log_buf, u32 log_size, u32 log_level)
>> +{
>> + return log_buf && log_size && log_level;
>> +}
>> +
>> +static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
>> + u32 log_level)
>> +{
>> + return bpf_log_attrs_set(log_buf, log_size, log_level) &&
>> + bpf_log_attrs_set(common->log_buf, common->log_size, common->log_level) &&
>> + (log_buf != common->log_buf || log_size != common->log_size ||
>> + log_level != common->log_level);
>> +}
>> +
>
> I'm not sure this check is doing what we discussed previously?... If
> log_buf is set, but log_size or log_level is zero, you'll just ignore
> log_buf here...
>
> Maybe let's keep it super simple:
>
> if (log_buf && common->log_buf && log_buf != common->log_buf)
> return -EINVAL;
> /* same for log_size, log_level, log_true_size */
>
> and then below just
>
> log->log_buf = u64_to_user_ptr(log_buf ?: common->log_buf);
> log->log_size = log_size ?: common->log_size;
>
> and so on
>
>
> We can be stricter than that, of course (as in, all triplets have to
> be completely set in either/both common_attr and attr, and they should
> completely match), but it's just more code for little benefit.
>
We cannot mix fields across the two sources. For example, using log_buf
from attr together with common->log_size when log_size is zero would mix
the configuration and make the effective log setup ambiguous.
The intent is to align strictly with the semantics enforced by
bpf_verifier_log_attr_valid():
* log_buf and log_size must be specified together.
* A non-NULL log_buf requires log_level != 0.
* All values must pass basic sanity checks.
Given that contract, we should:
1. Validate the log attributes from attr and common independently using
the same helper.
2. if both sides provide log buffers, require the tuples to match
exactly.
3. select either the attr tuple or the common tuple as a whole — never
mix fields across the two.
The patch below implements this by reusing bpf_verifier_log_attr_valid()
for both sources and resolving conflicts before selecting the effective
log configuration.
>
>> int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
>> - u32 __user *log_true_size)
>> + u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
>> + u32 size)
>> {
>> + if (bpf_log_attrs_diff(common, log_buf, log_size, log_level))
>> + return -EINVAL;
>> +
>> memset(log, 0, sizeof(*log));
>> log->log_buf = u64_to_user_ptr(log_buf);
>> log->log_size = log_size;
>> log->log_level = log_level;
>> log->log_true_size = log_true_size;
>> +
>> + if (!log_buf && common->log_buf) {
>> + log->log_buf = u64_to_user_ptr(common->log_buf);
>> + log->log_size = common->log_size;
>> + log->log_level = common->log_level;
>> + if (size >= offsetofend(struct bpf_common_attr, log_true_size))
>> + log->log_true_size = uattr.user +
>> + offsetof(struct bpf_common_attr, log_true_size);
>> + else
>> + log->log_true_size = NULL;
>
> why not treat log_true_size same as log_buf/log_level/log_size? If
> both are provided, they should match, and then we don't have a
> possibility of inconsistency?
>
log_true_size is different from log_buf/log_size/log_level.
It is not a regular attribute stored in either union bpf_attr or
struct bpf_common_attr. Instead, it is a user pointer derived from
uattr.user + offset.
As a result, the computed log_true_size pointer for union bpf_attr
and for struct bpf_common_attr will always differ, because they are
based on different base user pointers (uattr.user vs
uattr_common.user).
So unlike the other log attributes, pointer equality is not a
meaningful consistency check for log_true_size. The only sensible
rule is that whichever side provides the effective log triplet also
determines the write-back destination.
Thanks,
Leon
---
Based-on commit 19de32d4cb58 ("selftests/bpf: Migrate align.c tests to
test_loader framework").
From 32ec02c06d2abacbde17a45edbda46ef8a16fa2d Mon Sep 17 00:00:00 2001
From: Leon Hwang <leon.hwang@linux.dev>
Date: Wed, 11 Feb 2026 23:11:11 +0800
Subject: [PATCH bpf-next v11 4/8] bpf: Add syscall common attributes support
for prog_load
BPF_PROG_LOAD can now take log parameters from both union bpf_attr and
struct bpf_common_attr. The merge rules are:
- if both sides provide a complete log tuple (buf/size/level) and they
match, use it;
- if only one side provides log parameters, use that one;
- if both sides provide complete tuples but they differ, return -EINVAL.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf_verifier.h | 3 ++-
kernel/bpf/log.c | 38 ++++++++++++++++++++++++++++--------
kernel/bpf/syscall.c | 2 +-
3 files changed, 33 insertions(+), 10 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index dbd9bdb955b3..34f28d40022a 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -643,7 +643,8 @@ struct bpf_log_attr {
};
int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32
log_size, u32 log_level,
- u32 __user *log_true_size);
+ u32 __user *log_true_size, struct bpf_common_attr *common,
bpfptr_t uattr,
+ u32 size);
int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct
bpf_verifier_log *log);
#define BPF_MAX_SUBPROGS 256
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index e31747b84fe2..47bf496b673e 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -13,17 +13,17 @@
#define verbose(env, fmt, args...) bpf_verifier_log_write(env, fmt, ##args)
-static bool bpf_verifier_log_attr_valid(const struct bpf_verifier_log *log)
+static bool bpf_verifier_log_attr_valid(u32 log_level, char __user
*log_buf, u32 log_size)
{
/* ubuf and len_total should both be specified (or not) together */
- if (!!log->ubuf != !!log->len_total)
+ if (!!log_buf != !!log_size)
return false;
/* log buf without log_level is meaningless */
- if (log->ubuf && log->level == 0)
+ if (log_buf && log_level == 0)
return false;
- if (log->level & ~BPF_LOG_MASK)
+ if (log_level & ~BPF_LOG_MASK)
return false;
- if (log->len_total > UINT_MAX >> 2)
+ if (log_size > UINT_MAX >> 2)
return false;
return true;
}
@@ -36,7 +36,7 @@ int bpf_vlog_init(struct bpf_verifier_log *log, u32
log_level,
log->len_total = log_size;
/* log attributes have to be sane */
- if (!bpf_verifier_log_attr_valid(log))
+ if (!bpf_verifier_log_attr_valid(log_level, log_buf, log_size))
return -EINVAL;
return 0;
@@ -865,13 +865,35 @@ void print_insn_state(struct bpf_verifier_env
*env, const struct bpf_verifier_st
}
int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32
log_size, u32 log_level,
- u32 __user *log_true_size)
+ u32 __user *log_true_size, struct bpf_common_attr *common,
bpfptr_t uattr,
+ u32 size)
{
+ char __user *ubuf_common = u64_to_user_ptr(common->log_buf);
+ char __user *ubuf = u64_to_user_ptr(log_buf);
+
+ if (!bpf_verifier_log_attr_valid(common->log_level, ubuf_common,
common->log_size) ||
+ !bpf_verifier_log_attr_valid(log_level, ubuf, log_size))
+ return -EINVAL;
+
+ if (ubuf && ubuf_common && (ubuf != ubuf_common || log_size !=
common->log_size ||
+ log_level != common->log_level))
+ return -EINVAL;
+
memset(log, 0, sizeof(*log));
- log->log_buf = u64_to_user_ptr(log_buf);
+ log->log_buf = ubuf;
log->log_size = log_size;
log->log_level = log_level;
log->log_true_size = log_true_size;
+
+ if (!ubuf && ubuf_common) {
+ log->log_buf = ubuf_common;
+ log->log_size = common->log_size;
+ log->log_level = common->log_level;
+ log->log_true_size = NULL;
+ if (size >= offsetofend(struct bpf_common_attr, log_true_size))
+ log->log_true_size = uattr.user +
+ offsetof(struct bpf_common_attr, log_true_size);
+ }
return 0;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e86674811996..17116603ff51 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6247,7 +6247,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t
uattr, unsigned int size,
if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
err = bpf_log_attr_init(&attr_log, attr.log_buf, attr.log_size,
attr.log_level,
- log_true_size);
+ log_true_size, &attr_common, uattr_common, size_common);
err = err ?: bpf_prog_load(&attr, uattr, &attr_log);
break;
case BPF_OBJ_PIN:
--
2.52.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-02-11 22:10 ` Andrii Nakryiko
@ 2026-02-12 5:50 ` Leon Hwang
0 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-02-12 5:50 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, linux-kernel, linux-api, linux-kselftest,
kernel-patches-bot
On 12/2/26 06:10, Andrii Nakryiko wrote:
> On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
[...]
>> @@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
>> err = map_freeze(&attr);
>> break;
>> case BPF_PROG_LOAD:
>> - err = bpf_prog_load(&attr, uattr, size);
>> + if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
>> + log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
>
> LGTM, so
>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
>
Thanks for the review and the Ack!
> but it caught my eye that we will never return log_true_size if
> SYSCALL program tried to load another BPF program (light skeleton
> case), which seems limiting, but we can perhaps address that
> separately as a follow up
>
Correct.
Currently, struct bpf_verifier_log and the log_true_size
back-propagation mechanism are designed specifically for user space and
are not compatible with in-kernel callers.
I’ll look into whether this can be improved in a follow-up.
Thanks,
Leon
[...]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support for prog_load
2026-02-12 5:50 ` Leon Hwang
@ 2026-02-18 18:44 ` Andrii Nakryiko
0 siblings, 0 replies; 19+ messages in thread
From: Andrii Nakryiko @ 2026-02-18 18:44 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, linux-kernel, linux-api, linux-kselftest,
kernel-patches-bot
On Wed, Feb 11, 2026 at 9:50 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>
>
>
> On 12/2/26 06:08, Andrii Nakryiko wrote:
> > On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
> >>
>
> [...]
>
> >> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> >> index e31747b84fe2..a2b41bf5e9cb 100644
> >> --- a/kernel/bpf/log.c
> >> +++ b/kernel/bpf/log.c
> >> @@ -864,14 +864,43 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
> >> print_verifier_state(env, vstate, frameno, false);
> >> }
> >>
> >> +static bool bpf_log_attrs_set(u64 log_buf, u32 log_size, u32 log_level)
> >> +{
> >> + return log_buf && log_size && log_level;
> >> +}
> >> +
> >> +static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
> >> + u32 log_level)
> >> +{
> >> + return bpf_log_attrs_set(log_buf, log_size, log_level) &&
> >> + bpf_log_attrs_set(common->log_buf, common->log_size, common->log_level) &&
> >> + (log_buf != common->log_buf || log_size != common->log_size ||
> >> + log_level != common->log_level);
> >> +}
> >> +
> >
> > I'm not sure this check is doing what we discussed previously?... If
> > log_buf is set, but log_size or log_level is zero, you'll just ignore
> > log_buf here...
> >
> > Maybe let's keep it super simple:
> >
> > if (log_buf && common->log_buf && log_buf != common->log_buf)
> > return -EINVAL;
> > /* same for log_size, log_level, log_true_size */
> >
> > and then below just
> >
> > log->log_buf = u64_to_user_ptr(log_buf ?: common->log_buf);
> > log->log_size = log_size ?: common->log_size;
> >
> > and so on
> >
> >
> > We can be stricter than that, of course (as in, all triplets have to
> > be completely set in either/both common_attr and attr, and they should
> > completely match), but it's just more code for little benefit.
> >
>
> We cannot mix fields across the two sources. For example, using log_buf
> from attr together with common->log_size when log_size is zero would mix
> the configuration and make the effective log setup ambiguous.
>
> The intent is to align strictly with the semantics enforced by
> bpf_verifier_log_attr_valid():
>
> * log_buf and log_size must be specified together.
> * A non-NULL log_buf requires log_level != 0.
> * All values must pass basic sanity checks.
>
> Given that contract, we should:
>
> 1. Validate the log attributes from attr and common independently using
> the same helper.
> 2. if both sides provide log buffers, require the tuples to match
> exactly.
> 3. select either the attr tuple or the common tuple as a whole — never
> mix fields across the two.
>
> The patch below implements this by reusing bpf_verifier_log_attr_valid()
> for both sources and resolving conflicts before selecting the effective
> log configuration.
> >
> >> int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> >> - u32 __user *log_true_size)
> >> + u32 __user *log_true_size, struct bpf_common_attr *common, bpfptr_t uattr,
> >> + u32 size)
> >> {
> >> + if (bpf_log_attrs_diff(common, log_buf, log_size, log_level))
> >> + return -EINVAL;
> >> +
> >> memset(log, 0, sizeof(*log));
> >> log->log_buf = u64_to_user_ptr(log_buf);
> >> log->log_size = log_size;
> >> log->log_level = log_level;
> >> log->log_true_size = log_true_size;
> >> +
> >> + if (!log_buf && common->log_buf) {
> >> + log->log_buf = u64_to_user_ptr(common->log_buf);
> >> + log->log_size = common->log_size;
> >> + log->log_level = common->log_level;
> >> + if (size >= offsetofend(struct bpf_common_attr, log_true_size))
> >> + log->log_true_size = uattr.user +
> >> + offsetof(struct bpf_common_attr, log_true_size);
> >> + else
> >> + log->log_true_size = NULL;
> >
> > why not treat log_true_size same as log_buf/log_level/log_size? If
> > both are provided, they should match, and then we don't have a
> > possibility of inconsistency?
> >
> log_true_size is different from log_buf/log_size/log_level.
>
> It is not a regular attribute stored in either union bpf_attr or
> struct bpf_common_attr. Instead, it is a user pointer derived from
> uattr.user + offset.
>
> As a result, the computed log_true_size pointer for union bpf_attr
> and for struct bpf_common_attr will always differ, because they are
> based on different base user pointers (uattr.user vs
> uattr_common.user).
>
> So unlike the other log attributes, pointer equality is not a
> meaningful consistency check for log_true_size. The only sensible
> rule is that whichever side provides the effective log triplet also
> determines the write-back destination.
yeah, you are right, I forgot that log_true_size is not a pointer
itself, it's just a field in user-provided attrs. I'll check what you
did in v11, let's continue there.
>
> Thanks,
> Leon
>
> ---
>
> Based-on commit 19de32d4cb58 ("selftests/bpf: Migrate align.c tests to
> test_loader framework").
>
> From 32ec02c06d2abacbde17a45edbda46ef8a16fa2d Mon Sep 17 00:00:00 2001
> From: Leon Hwang <leon.hwang@linux.dev>
> Date: Wed, 11 Feb 2026 23:11:11 +0800
> Subject: [PATCH bpf-next v11 4/8] bpf: Add syscall common attributes support
> for prog_load
>
> BPF_PROG_LOAD can now take log parameters from both union bpf_attr and
> struct bpf_common_attr. The merge rules are:
>
> - if both sides provide a complete log tuple (buf/size/level) and they
> match, use it;
> - if only one side provides log parameters, use that one;
> - if both sides provide complete tuples but they differ, return -EINVAL.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/bpf_verifier.h | 3 ++-
> kernel/bpf/log.c | 38 ++++++++++++++++++++++++++++--------
> kernel/bpf/syscall.c | 2 +-
> 3 files changed, 33 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index dbd9bdb955b3..34f28d40022a 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -643,7 +643,8 @@ struct bpf_log_attr {
> };
>
> int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32
> log_size, u32 log_level,
> - u32 __user *log_true_size);
> + u32 __user *log_true_size, struct bpf_common_attr *common,
> bpfptr_t uattr,
> + u32 size);
> int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct
> bpf_verifier_log *log);
>
> #define BPF_MAX_SUBPROGS 256
> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> index e31747b84fe2..47bf496b673e 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -13,17 +13,17 @@
>
> #define verbose(env, fmt, args...) bpf_verifier_log_write(env, fmt, ##args)
>
> -static bool bpf_verifier_log_attr_valid(const struct bpf_verifier_log *log)
> +static bool bpf_verifier_log_attr_valid(u32 log_level, char __user
> *log_buf, u32 log_size)
> {
> /* ubuf and len_total should both be specified (or not) together */
> - if (!!log->ubuf != !!log->len_total)
> + if (!!log_buf != !!log_size)
> return false;
> /* log buf without log_level is meaningless */
> - if (log->ubuf && log->level == 0)
> + if (log_buf && log_level == 0)
> return false;
> - if (log->level & ~BPF_LOG_MASK)
> + if (log_level & ~BPF_LOG_MASK)
> return false;
> - if (log->len_total > UINT_MAX >> 2)
> + if (log_size > UINT_MAX >> 2)
> return false;
> return true;
> }
> @@ -36,7 +36,7 @@ int bpf_vlog_init(struct bpf_verifier_log *log, u32
> log_level,
> log->len_total = log_size;
>
> /* log attributes have to be sane */
> - if (!bpf_verifier_log_attr_valid(log))
> + if (!bpf_verifier_log_attr_valid(log_level, log_buf, log_size))
> return -EINVAL;
>
> return 0;
> @@ -865,13 +865,35 @@ void print_insn_state(struct bpf_verifier_env
> *env, const struct bpf_verifier_st
> }
>
> int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32
> log_size, u32 log_level,
> - u32 __user *log_true_size)
> + u32 __user *log_true_size, struct bpf_common_attr *common,
> bpfptr_t uattr,
> + u32 size)
> {
> + char __user *ubuf_common = u64_to_user_ptr(common->log_buf);
> + char __user *ubuf = u64_to_user_ptr(log_buf);
> +
> + if (!bpf_verifier_log_attr_valid(common->log_level, ubuf_common,
> common->log_size) ||
> + !bpf_verifier_log_attr_valid(log_level, ubuf, log_size))
> + return -EINVAL;
> +
> + if (ubuf && ubuf_common && (ubuf != ubuf_common || log_size !=
> common->log_size ||
> + log_level != common->log_level))
> + return -EINVAL;
> +
> memset(log, 0, sizeof(*log));
> - log->log_buf = u64_to_user_ptr(log_buf);
> + log->log_buf = ubuf;
> log->log_size = log_size;
> log->log_level = log_level;
> log->log_true_size = log_true_size;
> +
> + if (!ubuf && ubuf_common) {
> + log->log_buf = ubuf_common;
> + log->log_size = common->log_size;
> + log->log_level = common->log_level;
> + log->log_true_size = NULL;
> + if (size >= offsetofend(struct bpf_common_attr, log_true_size))
> + log->log_true_size = uattr.user +
> + offsetof(struct bpf_common_attr, log_true_size);
> + }
> return 0;
> }
>
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index e86674811996..17116603ff51 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -6247,7 +6247,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t
> uattr, unsigned int size,
> if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
> log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
> err = bpf_log_attr_init(&attr_log, attr.log_buf, attr.log_size,
> attr.log_level,
> - log_true_size);
> + log_true_size, &attr_common, uattr_common, size_common);
> err = err ?: bpf_prog_load(&attr, uattr, &attr_log);
> break;
> case BPF_OBJ_PIN:
> --
> 2.52.0
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-02-11 15:11 ` [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load Leon Hwang
2026-02-11 22:10 ` Andrii Nakryiko
@ 2026-03-03 16:32 ` Alexei Starovoitov
2026-03-04 5:47 ` Leon Hwang
1 sibling, 1 reply; 19+ messages in thread
From: Alexei Starovoitov @ 2026-03-03 16:32 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, LKML, Linux API,
open list:KERNEL SELFTEST FRAMEWORK, kernel-patches-bot
On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> The next commit will add support for reporting logs via extended common
> attributes, including 'log_true_size'.
>
> To prepare for that, refactor the 'log_true_size' reporting logic by
> introducing a new struct bpf_log_attr to encapsulate log-related behavior:
>
> * bpf_log_attr_init(): initialize log fields, which will support
> extended common attributes in the next commit.
> * bpf_log_attr_finalize(): handle log finalization and write back
> 'log_true_size' to userspace.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/bpf.h | 4 +++-
> include/linux/bpf_verifier.h | 11 +++++++++++
> kernel/bpf/log.c | 25 +++++++++++++++++++++++++
> kernel/bpf/syscall.c | 13 ++++++++++---
> kernel/bpf/verifier.c | 17 ++++-------------
> 5 files changed, 53 insertions(+), 17 deletions(-)
>
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index cd9b96434904..d4dbcc7ad156 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -2913,7 +2913,9 @@ int bpf_check_uarg_tail_zero(bpfptr_t uaddr, size_t expected_size,
> size_t actual_size);
>
> /* verify correctness of eBPF program */
> -int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size);
> +struct bpf_log_attr;
> +int bpf_check(struct bpf_prog **fp, union bpf_attr *attr, bpfptr_t uattr,
> + struct bpf_log_attr *attr_log);
>
> #ifndef CONFIG_BPF_JIT_ALWAYS_ON
> void bpf_patch_call_args(struct bpf_insn *insn, u32 stack_depth);
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index ef8e45a362d9..dbd9bdb955b3 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -635,6 +635,17 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
> return log && log->level;
> }
>
> +struct bpf_log_attr {
> + char __user *log_buf;
> + u32 log_size;
> + u32 log_level;
> + u32 __user *log_true_size;
> +};
> +
> +int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> + u32 __user *log_true_size);
> +int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log);
> +
> #define BPF_MAX_SUBPROGS 256
>
> struct bpf_subprog_arg_info {
> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> index a0c3b35de2ce..e31747b84fe2 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -863,3 +863,28 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
> }
> print_verifier_state(env, vstate, frameno, false);
> }
> +
> +int bpf_log_attr_init(struct bpf_log_attr *log, u64 log_buf, u32 log_size, u32 log_level,
> + u32 __user *log_true_size)
> +{
> + memset(log, 0, sizeof(*log));
> + log->log_buf = u64_to_user_ptr(log_buf);
> + log->log_size = log_size;
> + log->log_level = log_level;
> + log->log_true_size = log_true_size;
> + return 0;
> +}
> +
> +int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
> +{
> + u32 log_true_size;
> + int err;
> +
> + err = bpf_vlog_finalize(log, &log_true_size);
> +
> + if (attr->log_true_size && copy_to_user(attr->log_true_size, &log_true_size,
> + sizeof(log_true_size)))
> + return -EFAULT;
> +
> + return err;
> +}
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 0e231c0b1d04..e86674811996 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -2867,7 +2867,7 @@ static int bpf_prog_mark_insn_arrays_ready(struct bpf_prog *prog)
> /* last field in 'union bpf_attr' used by this command */
> #define BPF_PROG_LOAD_LAST_FIELD keyring_id
>
> -static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
> +static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, struct bpf_log_attr *attr_log)
> {
> enum bpf_prog_type type = attr->prog_type;
> struct bpf_prog *prog, *dst_prog = NULL;
> @@ -3085,7 +3085,7 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
> goto free_prog_sec;
>
> /* run eBPF verifier */
> - err = bpf_check(&prog, attr, uattr, uattr_size);
> + err = bpf_check(&prog, attr, uattr, attr_log);
> if (err < 0)
> goto free_used_maps;
>
> @@ -6189,7 +6189,10 @@ static int prog_assoc_struct_ops(union bpf_attr *attr)
> static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
> bpfptr_t uattr_common, unsigned int size_common)
> {
> + bool from_user = !bpfptr_is_kernel(uattr);
> struct bpf_common_attr attr_common;
> + u32 __user *log_true_size = NULL;
> + struct bpf_log_attr attr_log;
> union bpf_attr attr;
> int err;
>
> @@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
> err = map_freeze(&attr);
> break;
> case BPF_PROG_LOAD:
> - err = bpf_prog_load(&attr, uattr, size);
> + if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
> + log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
So you added 'from_user' gating because
you replaced copy_to_bpfptr_offset() with copy_to_user()?
This is a drastic change in behavior and you don't even talk about
it in the commit log.
You said "refactor". This is not a refactoring!
This is v10. The common_attr feature is useful, but
you really need to think harder about what your patches
are doing.
pw-bot: cr
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-03-03 16:32 ` Alexei Starovoitov
@ 2026-03-04 5:47 ` Leon Hwang
2026-03-04 5:58 ` Alexei Starovoitov
0 siblings, 1 reply; 19+ messages in thread
From: Leon Hwang @ 2026-03-04 5:47 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, LKML, Linux API,
open list:KERNEL SELFTEST FRAMEWORK, kernel-patches-bot
On 4/3/26 00:32, Alexei Starovoitov wrote:
> On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
[...]
>> @@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
>> err = map_freeze(&attr);
>> break;
>> case BPF_PROG_LOAD:
>> - err = bpf_prog_load(&attr, uattr, size);
>> + if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
>> + log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
>
> So you added 'from_user' gating because
> you replaced copy_to_bpfptr_offset() with copy_to_user()?
> This is a drastic change in behavior and you don't even talk about
> it in the commit log.
> You said "refactor". This is not a refactoring!
>
> This is v10. The common_attr feature is useful, but
> you really need to think harder about what your patches
> are doing.
>
Refactoring should not introduce any functional changes. If a functional
change is involved, it should be factored out of the refactoring commit
into a separate commit with an explanation in the commit log.
I'll add this to my self-review checklist.
The intention of 'from_user' was to replace copy_to_bpfptr_offset() with
copy_to_user(), since the log is always copied to the user-space buffer
when the log level is not BPF_LOG_KERNEL in
kernel/bpf/log.c::bpf_verifier_vlog().
The 'from_user' gating will be dropped in v12 to keep this patch as pure
refactoring.
Thanks,
Leon
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-03-04 5:47 ` Leon Hwang
@ 2026-03-04 5:58 ` Alexei Starovoitov
2026-03-04 6:17 ` Leon Hwang
0 siblings, 1 reply; 19+ messages in thread
From: Alexei Starovoitov @ 2026-03-04 5:58 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, LKML, Linux API,
open list:KERNEL SELFTEST FRAMEWORK, kernel-patches-bot
On Tue, Mar 3, 2026 at 9:47 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> On 4/3/26 00:32, Alexei Starovoitov wrote:
> > On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
> >>
>
> [...]
>
> >> @@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
> >> err = map_freeze(&attr);
> >> break;
> >> case BPF_PROG_LOAD:
> >> - err = bpf_prog_load(&attr, uattr, size);
> >> + if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
> >> + log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
> >
> > So you added 'from_user' gating because
> > you replaced copy_to_bpfptr_offset() with copy_to_user()?
> > This is a drastic change in behavior and you don't even talk about
> > it in the commit log.
> > You said "refactor". This is not a refactoring!
> >
> > This is v10. The common_attr feature is useful, but
> > you really need to think harder about what your patches
> > are doing.
> >
>
> Refactoring should not introduce any functional changes. If a functional
> change is involved, it should be factored out of the refactoring commit
> into a separate commit with an explanation in the commit log.
>
> I'll add this to my self-review checklist.
>
> The intention of 'from_user' was to replace copy_to_bpfptr_offset() with
> copy_to_user(), since the log is always copied to the user-space buffer
> when the log level is not BPF_LOG_KERNEL in
> kernel/bpf/log.c::bpf_verifier_vlog().
>
> The 'from_user' gating will be dropped in v12 to keep this patch as pure
> refactoring.
You were told multiple times to avoid copy pasting AI into your emails.
Sorry, but this crosses the line for me.
Your patches will be ignored for 2 weeks.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load
2026-03-04 5:58 ` Alexei Starovoitov
@ 2026-03-04 6:17 ` Leon Hwang
0 siblings, 0 replies; 19+ messages in thread
From: Leon Hwang @ 2026-03-04 6:17 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: bpf, 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, Willem de Bruijn, Jason Xing, Tao Chen,
Mykyta Yatsenko, Kumar Kartikeya Dwivedi, Anton Protopopov,
Amery Hung, Rong Tao, LKML, Linux API,
open list:KERNEL SELFTEST FRAMEWORK, kernel-patches-bot
On 4/3/26 13:58, Alexei Starovoitov wrote:
> On Tue, Mar 3, 2026 at 9:47 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
>> On 4/3/26 00:32, Alexei Starovoitov wrote:
>>> On Wed, Feb 11, 2026 at 7:13 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>>>
>>
>> [...]
>>
>>>> @@ -6241,7 +6244,11 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size,
>>>> err = map_freeze(&attr);
>>>> break;
>>>> case BPF_PROG_LOAD:
>>>> - err = bpf_prog_load(&attr, uattr, size);
>>>> + if (from_user && size >= offsetofend(union bpf_attr, log_true_size))
>>>> + log_true_size = uattr.user + offsetof(union bpf_attr, log_true_size);
>>>
>>> So you added 'from_user' gating because
>>> you replaced copy_to_bpfptr_offset() with copy_to_user()?
>>> This is a drastic change in behavior and you don't even talk about
>>> it in the commit log.
>>> You said "refactor". This is not a refactoring!
>>>
>>> This is v10. The common_attr feature is useful, but
>>> you really need to think harder about what your patches
>>> are doing.
>>>
>>
>> Refactoring should not introduce any functional changes. If a functional
>> change is involved, it should be factored out of the refactoring commit
>> into a separate commit with an explanation in the commit log.
>>
>> I'll add this to my self-review checklist.
>>
>> The intention of 'from_user' was to replace copy_to_bpfptr_offset() with
>> copy_to_user(), since the log is always copied to the user-space buffer
>> when the log level is not BPF_LOG_KERNEL in
>> kernel/bpf/log.c::bpf_verifier_vlog().
>>
>> The 'from_user' gating will be dropped in v12 to keep this patch as pure
>> refactoring.
>
> You were told multiple times to avoid copy pasting AI into your emails.
> Sorry, but this crosses the line for me.
> Your patches will be ignored for 2 weeks.
Oops. The above reply was written by my hand. Possibly, the reply
carried LLM smell because I learnt LLM tongue recently.
As you said, I won't send patches for 2 weeks. :-(
Thanks,
Leon
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-03-04 6:17 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-11 15:11 [PATCH bpf-next v10 0/8] bpf: Extend BPF syscall with common attributes support Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 1/8] " Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 2/8] libbpf: Add support for extended bpf syscall Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 3/8] bpf: Refactor reporting log_true_size for prog_load Leon Hwang
2026-02-11 22:10 ` Andrii Nakryiko
2026-02-12 5:50 ` Leon Hwang
2026-03-03 16:32 ` Alexei Starovoitov
2026-03-04 5:47 ` Leon Hwang
2026-03-04 5:58 ` Alexei Starovoitov
2026-03-04 6:17 ` Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 4/8] bpf: Add syscall common attributes support " Leon Hwang
2026-02-11 22:08 ` Andrii Nakryiko
2026-02-12 5:50 ` Leon Hwang
2026-02-18 18:44 ` Andrii Nakryiko
2026-02-11 15:11 ` [PATCH bpf-next v10 5/8] bpf: Add syscall common attributes support for btf_load Leon Hwang
2026-02-11 22:11 ` Andrii Nakryiko
2026-02-11 15:11 ` [PATCH bpf-next v10 6/8] bpf: Add syscall common attributes support for map_create Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 7/8] libbpf: " Leon Hwang
2026-02-11 15:11 ` [PATCH bpf-next v10 8/8] selftests/bpf: Add tests to verify map create failure log Leon Hwang
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox