* [PATCH bpf-next v9 2/9] libbpf: Add support for extended bpf syscall
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
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.
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
* [PATCH bpf-next v9 3/9] bpf: Refactor reporting log_true_size for prog_load
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
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_prog_load_log_attr_init(): initialize the 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 | 10 ++++++++++
kernel/bpf/log.c | 35 +++++++++++++++++++++++++++++++++++
kernel/bpf/syscall.c | 8 +++++---
kernel/bpf/verifier.c | 13 +++----------
5 files changed, 56 insertions(+), 14 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 8355b585cd18..c805b85b6f7a 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -631,6 +631,16 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
return log && log->level;
}
+struct bpf_log_attr {
+ u32 offsetof_true_size;
+ u32 uattr_size;
+ bpfptr_t uattr;
+};
+
+int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
+ 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
struct bpf_subprog_arg_info {
diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
index a0c3b35de2ce..ff579fcba36f 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -863,3 +863,38 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
}
print_verifier_state(env, vstate, frameno, false);
}
+
+static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_size, bpfptr_t uattr,
+ u32 uattr_size)
+{
+ memset(attr_log, 0, sizeof(*attr_log));
+ attr_log->offsetof_true_size = offsetof_true_size;
+ attr_log->uattr_size = uattr_size;
+ attr_log->uattr = uattr;
+}
+
+int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
+ bpfptr_t uattr, u32 size)
+{
+ bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
+ return 0;
+}
+
+int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
+{
+ u32 log_true_size;
+ size_t size;
+ int err;
+
+ if (!log)
+ return 0;
+
+ err = bpf_vlog_finalize(log, &log_true_size);
+
+ size = sizeof(log_true_size);
+ if (attr->uattr_size >= attr->offsetof_true_size + size &&
+ copy_to_bpfptr_offset(attr->uattr, attr->offsetof_true_size, &log_true_size, size))
+ err = -EFAULT;
+
+ return err;
+}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index a58b16735e86..e81199361241 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2860,7 +2860,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;
@@ -3078,7 +3078,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;
@@ -6180,6 +6180,7 @@ 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;
+ struct bpf_log_attr attr_log;
union bpf_attr attr;
int err;
@@ -6231,7 +6232,8 @@ 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);
+ err = bpf_prog_load_log_attr_init(&attr_log, &attr, uattr, 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 6b62b6d57175..1489867671e0 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -25604,12 +25604,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);
@@ -25808,17 +25808,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
* [PATCH bpf-next v9 4/9] bpf: Add syscall common attributes support for prog_load
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
BPF_PROG_LOAD can now provide log parameters through both union bpf_attr
and struct bpf_common_attr. Define clear conflict and precedence rules:
- if both are provided and log_buf/log_size/log_level match, use them;
- if only one side provides a log buffer, use that one;
- if both provide log buffers but differ, return -EINVAL.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf_verifier.h | 3 ++-
kernel/bpf/log.c | 24 ++++++++++++++++++++++--
kernel/bpf/syscall.c | 3 ++-
3 files changed, 26 insertions(+), 4 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index c805b85b6f7a..0d106fddbbc5 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -638,7 +638,8 @@ struct bpf_log_attr {
};
int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
- bpfptr_t uattr, u32 size);
+ bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
+ bpfptr_t uattr_common, u32 size_common);
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 ff579fcba36f..345005ba98dd 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -873,10 +873,30 @@ static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_s
attr_log->uattr = uattr;
}
+static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
+ u32 log_level)
+{
+ return log_buf && common->log_buf && (log_buf != common->log_buf ||
+ log_size != common->log_size ||
+ log_level != common->log_level);
+}
+
int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
- bpfptr_t uattr, u32 size)
+ bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
+ bpfptr_t uattr_common, u32 size_common)
{
- bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
+ if (bpf_log_attrs_diff(attr_common, attr->log_buf, attr->log_size, attr->log_level))
+ return -EINVAL;
+
+ if (!attr->log_buf && attr_common->log_buf) {
+ attr->log_buf = attr_common->log_buf;
+ attr->log_size = attr_common->log_size;
+ attr->log_level = attr_common->log_level;
+ bpf_log_attr_init(attr_log, offsetof(struct bpf_common_attr, log_true_size),
+ uattr_common, size_common);
+ } else {
+ bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
+ }
return 0;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index e81199361241..7125ea445c6c 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6232,7 +6232,8 @@ 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_log_attr_init(&attr_log, &attr, uattr, size);
+ err = bpf_prog_load_log_attr_init(&attr_log, &attr, uattr, 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
* [PATCH bpf-next v9 5/9] bpf: Refactor reporting btf_log_true_size for btf_load
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
In the next commit, it will be able to report logs via extended common
attributes, which will report 'log_true_size' via the extended common
attributes meanwhile.
Therefore, refactor the way of 'btf_log_true_size' reporting in order to
report 'log_true_size' via the extended common attributes easily.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf_verifier.h | 2 ++
include/linux/btf.h | 3 ++-
kernel/bpf/btf.c | 26 ++++++--------------------
kernel/bpf/log.c | 7 +++++++
kernel/bpf/syscall.c | 7 ++++---
5 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 0d106fddbbc5..b6e33ee82f63 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -640,6 +640,8 @@ struct bpf_log_attr {
int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
bpfptr_t uattr_common, u32 size_common);
+int bpf_btf_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
+ 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/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 8959f3bc1e92..753db6408c71 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -5856,22 +5856,8 @@ 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);
@@ -5953,7 +5939,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;
@@ -5965,7 +5951,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:
@@ -8136,12 +8122,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/log.c b/kernel/bpf/log.c
index 345005ba98dd..8ad88e4aa12c 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -900,6 +900,13 @@ int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *a
return 0;
}
+int bpf_btf_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
+ bpfptr_t uattr, u32 size)
+{
+ bpf_log_attr_init(attr_log, offsetof(union bpf_attr, btf_log_true_size), uattr, size);
+ return 0;
+}
+
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 7125ea445c6c..b6e4ec641dc1 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5438,7 +5438,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;
@@ -5465,7 +5465,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
@@ -6279,7 +6279,8 @@ 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);
+ err = bpf_btf_load_log_attr_init(&attr_log, &attr, uattr, size);
+ 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
* [PATCH bpf-next v9 6/9] bpf: Add syscall common attributes support for btf_load
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
BPF_BTF_LOAD can now provide log parameters through both union bpf_attr
and bpf_common_attr. Apply the same conflict and precedence rules as
prog_load:
- if both are provided and btf_log_buf/btf_log_size/btf_log_level match,
use them;
- if only one side provides a log buffer, use that one;
- if both provide log buffers but differ, return -EINVAL.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf_verifier.h | 3 ++-
kernel/bpf/log.c | 18 ++++++++++++++++--
kernel/bpf/syscall.c | 3 ++-
3 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index b6e33ee82f63..1144657bbc2f 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -641,7 +641,8 @@ int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *a
bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
bpfptr_t uattr_common, u32 size_common);
int bpf_btf_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
- bpfptr_t uattr, u32 size);
+ bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
+ bpfptr_t uattr_common, u32 size_common);
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 8ad88e4aa12c..db2716586f85 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -901,9 +901,23 @@ int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *a
}
int bpf_btf_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
- bpfptr_t uattr, u32 size)
+ bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
+ bpfptr_t uattr_common, u32 size_common)
{
- bpf_log_attr_init(attr_log, offsetof(union bpf_attr, btf_log_true_size), uattr, size);
+ if (bpf_log_attrs_diff(attr_common, attr->btf_log_buf, attr->btf_log_size,
+ attr->btf_log_level))
+ return -EINVAL;
+
+ if (!attr->btf_log_buf && attr_common->log_buf) {
+ attr->btf_log_buf = attr_common->log_buf;
+ attr->btf_log_size = attr_common->log_size;
+ attr->btf_log_level = attr_common->log_level;
+ bpf_log_attr_init(attr_log, offsetof(struct bpf_common_attr, log_true_size),
+ uattr_common, size_common);
+ } else {
+ bpf_log_attr_init(attr_log, offsetof(union bpf_attr, btf_log_true_size), uattr,
+ size);
+ }
return 0;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index b6e4ec641dc1..4a8933c1dd38 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -6279,7 +6279,8 @@ 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_log_attr_init(&attr_log, &attr, uattr, size);
+ err = bpf_btf_load_log_attr_init(&attr_log, &attr, uattr, size, &attr_common,
+ uattr_common, size_common);
err = err ?: bpf_btf_load(&attr, uattr, &attr_log);
break;
case BPF_BTF_GET_FD_BY_ID:
--
2.52.0
^ permalink raw reply related
* [PATCH bpf-next v9 7/9] bpf: Add syscall common attributes support for map_create
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
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 | 25 ++++++++++++++
kernel/bpf/syscall.c | 65 ++++++++++++++++++++++++++++++------
3 files changed, 83 insertions(+), 10 deletions(-)
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 1144657bbc2f..eb7e6e0458f5 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -643,6 +643,9 @@ int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *a
int bpf_btf_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
bpfptr_t uattr_common, u32 size_common);
+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 db2716586f85..e5a46ad4eb23 100644
--- a/kernel/bpf/log.c
+++ b/kernel/bpf/log.c
@@ -921,6 +921,31 @@ int bpf_btf_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *at
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;
+
+ if (!common->log_buf)
+ return NULL;
+
+ log = kzalloc(sizeof(*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);
+ }
+
+ bpf_log_attr_init(attr_log, offsetof(struct bpf_common_attr, log_true_size), uattr, size);
+ 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 4a8933c1dd38..d26f63bd460e 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);
@@ -6214,7 +6259,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
* [PATCH bpf-next v9 8/9] libbpf: Add syscall common attributes support for map_create
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
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.
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..59673f094f86 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;
+
+ 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
* [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
From: Leon Hwang @ 2026-02-02 14:40 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
In-Reply-To: <20260202144046.30651-1-leon.hwang@linux.dev>
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 | 168 ++++++++++++++++++
1 file changed, 168 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..89e6daf2fcfd 100644
--- a/tools/testing/selftests/bpf/prog_tests/map_init.c
+++ b/tools/testing/selftests/bpf/prog_tests/map_init.c
@@ -212,3 +212,171 @@ void test_map_init(void)
if (test__start_subtest("pcpu_lru_map_init"))
test_pcpu_lru_map_init();
}
+
+#define BPF_LOG_FIXED 8
+
+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 = BPF_LOG_FIXED;
+ 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
* Re: [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Thomas Weißschuh @ 2026-02-03 11:42 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Simon Horman, Shuah Khan, Matthieu Baerts,
Mat Martineau, Geliang Tang, Mickaël Salaün,
Günther Noack, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, netdev, linux-kernel,
linux-api, Arnd Bergmann, linux-kselftest, mptcp,
linux-security-module, bpf, libc-alpha, Carlos O'Donell,
Adhemerval Zanella, Rich Felker, klibc, Florian Weimer
In-Reply-To: <20260131092517.6639d84c@kernel.org>
On Sat, Jan 31, 2026 at 09:25:17AM -0800, Jakub Kicinski wrote:
> On Sat, 31 Jan 2026 11:26:32 +0100 Thomas Weißschuh wrote:
> > Jan 30, 2026 17:17:46 Jakub Kicinski <kuba@kernel.org>:
> >
> > > On Fri, 30 Jan 2026 11:34:15 +0100 Thomas Weißschuh wrote:
> > >> Some of them get broken by the new 'struct sockaddr', but some others are
> > >> already broken just by the new transitive inclusion of libc-compat.h.
> > >> So any header starting to use the compatibility machinery may trigger breakage
> > >> in code including UAPI headers before libc header, even for completely new type
> > >> definitions which themselves would not conflict with libc.
> > >
> > > Let's split the uAPI header changes from any selftest changes.
> > > If you're saying the the selftests no longer build after the uAPI
> > > header changes then of course we can't apply the patches.
> >
> > Yes, the selftests don't build anymore after the uAPI changes.
> >
> > "can't apply" as in
> > * "can't apply separately"
> > * "are unacceptable in general"
>
> this one
>
> > * "are too late for this cycle"
> > ?
> >
> > None of this is urgent.
> > We can do the selftests in one cycle and the uAPI in another one.
> > Feel free to pick up the patches as you see fit.
> > (The mptcp changes already go through their tree, so need to be dropped here)
> > I can also resubmit the patches differently if preferred.
>
> The selftests are just a canary in the coalmine. If we break a bunch of
> selftests chances are we'll also break compilation of real applications
> for people. Subjective, but I don't see a sufficient upside here to do
> that.
Okay. We'll have around this inconsistency then.
> FWIW the typelimits change broke compilation of ethtool, we'll see if
> anyone "outside kernel community itself" complains.
Can you point me to that breakage? I was unable to find it.
Thomas
^ permalink raw reply
* Re: [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Jakub Kicinski @ 2026-02-03 22:40 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Simon Horman, Shuah Khan, Matthieu Baerts,
Mat Martineau, Geliang Tang, Mickaël Salaün,
Günther Noack, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, netdev, linux-kernel,
linux-api, Arnd Bergmann, linux-kselftest, mptcp,
linux-security-module, bpf, libc-alpha, Carlos O'Donell,
Adhemerval Zanella, Rich Felker, klibc, Florian Weimer
In-Reply-To: <20260203122715-eeb304f9-4b42-4fc6-a527-658182a92ba5@linutronix.de>
On Tue, 3 Feb 2026 12:42:22 +0100 Thomas Weißschuh wrote:
> > FWIW the typelimits change broke compilation of ethtool, we'll see if
> > anyone "outside kernel community itself" complains.
>
> Can you point me to that breakage? I was unable to find it.
Not reported on the ML, and it's kinda annoying to repro because
the uAPI header sync script isn't committed :/ You have to check
this out
https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/
and run a script like this to sync headers from the kernel (then build):
#!/bin/bash -e
sn="${0##*/}"
export ARCH="x86_64"
if [ ! -d "$LINUX_GIT" ]; then
echo "${sn}: LINUX_GIT not set" >&2
exit 1
fi
pushd "$LINUX_GIT"
if [ -n "$1" ]; then
git checkout "$1"
fi
desc=$(git describe --exact-match 2>/dev/null \
|| git show -s --abbrev=12 --pretty='commit %h')
kobj=$(mktemp -d)
make -j16 O="$kobj" allmodconfig
make -j16 O="$kobj" prepare
make -j16 O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
popd
pushd uapi
find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;
popd
rm -rf "$kobj"
git add uapi
git commit -s -F - <<EOT
update UAPI header copies
Update to kernel ${desc}.
EOT
^ permalink raw reply
* Re: [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Thomas Weißschuh @ 2026-02-04 5:51 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Simon Horman, Shuah Khan, Matthieu Baerts,
Mat Martineau, Geliang Tang, Mickaël Salaün,
Günther Noack, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, netdev, linux-kernel,
linux-api, Arnd Bergmann, linux-kselftest, mptcp,
linux-security-module, bpf, libc-alpha, Carlos O'Donell,
Adhemerval Zanella, Rich Felker, klibc, Florian Weimer
In-Reply-To: <20260203144011.32d5b223@kernel.org>
On Tue, Feb 03, 2026 at 02:40:11PM -0800, Jakub Kicinski wrote:
> On Tue, 3 Feb 2026 12:42:22 +0100 Thomas Weißschuh wrote:
> > > FWIW the typelimits change broke compilation of ethtool, we'll see if
> > > anyone "outside kernel community itself" complains.
> >
> > Can you point me to that breakage? I was unable to find it.
>
> Not reported on the ML, and it's kinda annoying to repro because
> the uAPI header sync script isn't committed :/ You have to check
> this out
>
> https://git.kernel.org/pub/scm/network/ethtool/ethtool.git/
>
> and run a script like this to sync headers from the kernel (then build):
>
> #!/bin/bash -e
>
> sn="${0##*/}"
> export ARCH="x86_64"
>
> if [ ! -d "$LINUX_GIT" ]; then
> echo "${sn}: LINUX_GIT not set" >&2
> exit 1
> fi
>
> pushd "$LINUX_GIT"
> if [ -n "$1" ]; then
> git checkout "$1"
> fi
> desc=$(git describe --exact-match 2>/dev/null \
> || git show -s --abbrev=12 --pretty='commit %h')
> kobj=$(mktemp -d)
> make -j16 O="$kobj" allmodconfig
> make -j16 O="$kobj" prepare
These are not necessary.
The UAPI generation does not need a kernel configuration.
> make -j16 O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
> popd
>
> pushd uapi
> find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;
Here only those headers which already exist in ethtool's uapi/ directory
are copied. As linux/typelimits.h is new, it is now missing.
Honestly, if a user fiddles with the internals of the UAPI headers like
this, it is on them to update their code if the internal structure
changes. In your case a simple 'touch uapi/linux/typelimits.h'
before running the script will be enough. Also internal.h now requires
an explicit inclusion of <limits.h>, as that is not satisfied by the
UAPI anymore.
> popd
> rm -rf "$kobj"
>
> git add uapi
> git commit -s -F - <<EOT
> update UAPI header copies
>
> Update to kernel ${desc}.
>
> EOT
^ permalink raw reply
* Re: [PATCH bpf-next v9 8/9] libbpf: Add syscall common attributes support for map_create
From: Andrii Nakryiko @ 2026-02-04 19:48 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
In-Reply-To: <20260202144046.30651-9-leon.hwang@linux.dev>
On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> 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.
>
> 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(-)
>
LGTM
Acked-by: Andrii Nakryiko <andrii@kernel.org>
> 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..59673f094f86 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;
please mention in the comment here that this is an out parameter set
by the 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
* Re: [PATCH bpf-next v9 2/9] libbpf: Add support for extended bpf syscall
From: Andrii Nakryiko @ 2026-02-04 19:48 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
In-Reply-To: <20260202144046.30651-3-leon.hwang@linux.dev>
On Mon, Feb 2, 2026 at 6:41 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> 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.
>
> 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(+)
>
LGTM
Acked-by: Andrii Nakryiko <andrii@kernel.org>
[...]
^ permalink raw reply
* Re: [PATCH bpf-next v9 3/9] bpf: Refactor reporting log_true_size for prog_load
From: Andrii Nakryiko @ 2026-02-04 19:48 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
In-Reply-To: <20260202144046.30651-4-leon.hwang@linux.dev>
On Mon, Feb 2, 2026 at 6:42 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_prog_load_log_attr_init(): initialize the 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 | 10 ++++++++++
> kernel/bpf/log.c | 35 +++++++++++++++++++++++++++++++++++
> kernel/bpf/syscall.c | 8 +++++---
> kernel/bpf/verifier.c | 13 +++----------
> 5 files changed, 56 insertions(+), 14 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 8355b585cd18..c805b85b6f7a 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -631,6 +631,16 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
> return log && log->level;
> }
>
> +struct bpf_log_attr {
> + u32 offsetof_true_size;
> + u32 uattr_size;
> + bpfptr_t uattr;
> +};
> +
> +int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
> + 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
>
> struct bpf_subprog_arg_info {
> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> index a0c3b35de2ce..ff579fcba36f 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -863,3 +863,38 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
> }
> print_verifier_state(env, vstate, frameno, false);
> }
> +
> +static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_size, bpfptr_t uattr,
> + u32 uattr_size)
> +{
> + memset(attr_log, 0, sizeof(*attr_log));
> + attr_log->offsetof_true_size = offsetof_true_size;
> + attr_log->uattr_size = uattr_size;
> + attr_log->uattr = uattr;
> +}
> +
> +int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
> + bpfptr_t uattr, u32 size)
> +{
> + bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
> + return 0;
> +}
> +
> +int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
> +{
> + u32 log_true_size;
> + size_t size;
> + int err;
> +
> + if (!log)
> + return 0;
can this ever happen? why guard against this?
> +
> + err = bpf_vlog_finalize(log, &log_true_size);
> +
> + size = sizeof(log_true_size);
> + if (attr->uattr_size >= attr->offsetof_true_size + size &&
> + copy_to_bpfptr_offset(attr->uattr, attr->offsetof_true_size, &log_true_size, size))
> + err = -EFAULT;
minor nit: return -EFAULT;
> +
> + return err;
> +}
[...]
^ permalink raw reply
* Re: [PATCH bpf-next v9 4/9] bpf: Add syscall common attributes support for prog_load
From: Andrii Nakryiko @ 2026-02-04 19:48 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
In-Reply-To: <20260202144046.30651-5-leon.hwang@linux.dev>
On Mon, Feb 2, 2026 at 6:42 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> BPF_PROG_LOAD can now provide log parameters through both union bpf_attr
> and struct bpf_common_attr. Define clear conflict and precedence rules:
>
> - if both are provided and log_buf/log_size/log_level match, use them;
> - if only one side provides a log buffer, use that one;
> - if both provide log buffers but differ, return -EINVAL.
>
> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> ---
> include/linux/bpf_verifier.h | 3 ++-
> kernel/bpf/log.c | 24 ++++++++++++++++++++++--
> kernel/bpf/syscall.c | 3 ++-
> 3 files changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index c805b85b6f7a..0d106fddbbc5 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -638,7 +638,8 @@ struct bpf_log_attr {
> };
>
> int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
> - bpfptr_t uattr, u32 size);
> + bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
> + bpfptr_t uattr_common, u32 size_common);
> 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 ff579fcba36f..345005ba98dd 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -873,10 +873,30 @@ static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_s
> attr_log->uattr = uattr;
> }
>
> +static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
> + u32 log_level)
> +{
> + return log_buf && common->log_buf && (log_buf != common->log_buf ||
> + log_size != common->log_size ||
> + log_level != common->log_level);
let's validate (unless we do this somewhere else) that if log_buf is
set, then log_size and log_level (? not sure, maybe zero is fine) are
set, or all three are not set. Same for common->log* fields...
> +}
> +
> int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
> - bpfptr_t uattr, u32 size)
> + bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
> + bpfptr_t uattr_common, u32 size_common)
> {
> - bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
> + if (bpf_log_attrs_diff(attr_common, attr->log_buf, attr->log_size, attr->log_level))
> + return -EINVAL;
> +
> + if (!attr->log_buf && attr_common->log_buf) {
> + attr->log_buf = attr_common->log_buf;
> + attr->log_size = attr_common->log_size;
> + attr->log_level = attr_common->log_level;
why are we setting this? Do we still have code that can access
attr->log_buf even though we pass attr_log everywhere? If yes, should
we still have that "split brain" code?
If we don't have this assignment, then I think we don't need to have
bpf_prog_load-specific and btf_load-specific log_attr_init() helpers.
They can be unified into generic log_attr_init, where for
bpf_prog_load you'll pass offsetof(log_true_size) +
attr->log_{buf,size,level}, and for btf_load you'll pass different
offset of and btf-specific attr->btf_log*
This helper will just be making decision whether to use common_attr's
log fields or passed directly command-specific ones.
Or what am I missing?
> + bpf_log_attr_init(attr_log, offsetof(struct bpf_common_attr, log_true_size),
> + uattr_common, size_common);
> + } else {
> + bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
> + }
> return 0;
> }
>
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index e81199361241..7125ea445c6c 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -6232,7 +6232,8 @@ 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_log_attr_init(&attr_log, &attr, uattr, size);
> + err = bpf_prog_load_log_attr_init(&attr_log, &attr, uattr, 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
* Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
From: Alexei Starovoitov @ 2026-02-04 20:14 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
In-Reply-To: <20260202144046.30651-10-leon.hwang@linux.dev>
On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> +
> +#define BPF_LOG_FIXED 8
> +
> +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 = BPF_LOG_FIXED;
Why? Which part of the test needs the log with this flag?
^ permalink raw reply
* Re: [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Jakub Kicinski @ 2026-02-05 1:55 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Simon Horman, Shuah Khan, Matthieu Baerts,
Mat Martineau, Geliang Tang, Mickaël Salaün,
Günther Noack, Alexei Starovoitov, Daniel Borkmann,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Hao Luo, Jiri Olsa, netdev, linux-kernel,
linux-api, Arnd Bergmann, linux-kselftest, mptcp,
linux-security-module, bpf, libc-alpha, Carlos O'Donell,
Adhemerval Zanella, Rich Felker, klibc, Florian Weimer
In-Reply-To: <20260204064248-d9c4ab78-f6d4-4ac6-8d55-e939bc1df6d2@linutronix.de>
On Wed, 4 Feb 2026 06:51:46 +0100 Thomas Weißschuh wrote:
> > make -j16 O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
> > popd
> >
> > pushd uapi
> > find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;
>
> Here only those headers which already exist in ethtool's uapi/ directory
> are copied. As linux/typelimits.h is new, it is now missing.
> Honestly, if a user fiddles with the internals of the UAPI headers like
> this, it is on them to update their code if the internal structure
> changes. In your case a simple 'touch uapi/linux/typelimits.h'
> before running the script will be enough. Also internal.h now requires
> an explicit inclusion of <limits.h>, as that is not satisfied by the
> UAPI anymore.
Hopefully you understand that while due to uapi header copy this is not
a huge issue for ethtool itself, but it is a proof that your changes
can break normal user space applications which do not vendor in uapi.
^ permalink raw reply
* Re: [PATCH bpf-next v9 3/9] bpf: Refactor reporting log_true_size for prog_load
From: Leon Hwang @ 2026-02-05 2:20 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
In-Reply-To: <CAEf4Bza+n2-tq0cGvAit23OduWbqO6teF211iPnOfp0s_ZwEPw@mail.gmail.com>
On 5/2/26 03:48, Andrii Nakryiko wrote:
> On Mon, Feb 2, 2026 at 6:42 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_prog_load_log_attr_init(): initialize the 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 | 10 ++++++++++
>> kernel/bpf/log.c | 35 +++++++++++++++++++++++++++++++++++
>> kernel/bpf/syscall.c | 8 +++++---
>> kernel/bpf/verifier.c | 13 +++----------
>> 5 files changed, 56 insertions(+), 14 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 8355b585cd18..c805b85b6f7a 100644
>> --- a/include/linux/bpf_verifier.h
>> +++ b/include/linux/bpf_verifier.h
>> @@ -631,6 +631,16 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log)
>> return log && log->level;
>> }
>>
>> +struct bpf_log_attr {
>> + u32 offsetof_true_size;
>> + u32 uattr_size;
>> + bpfptr_t uattr;
>> +};
>> +
>> +int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
>> + 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
>>
>> struct bpf_subprog_arg_info {
>> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
>> index a0c3b35de2ce..ff579fcba36f 100644
>> --- a/kernel/bpf/log.c
>> +++ b/kernel/bpf/log.c
>> @@ -863,3 +863,38 @@ void print_insn_state(struct bpf_verifier_env *env, const struct bpf_verifier_st
>> }
>> print_verifier_state(env, vstate, frameno, false);
>> }
>> +
>> +static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_size, bpfptr_t uattr,
>> + u32 uattr_size)
>> +{
>> + memset(attr_log, 0, sizeof(*attr_log));
>> + attr_log->offsetof_true_size = offsetof_true_size;
>> + attr_log->uattr_size = uattr_size;
>> + attr_log->uattr = uattr;
>> +}
>> +
>> +int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
>> + bpfptr_t uattr, u32 size)
>> +{
>> + bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
>> + return 0;
>> +}
>> +
>> +int bpf_log_attr_finalize(struct bpf_log_attr *attr, struct bpf_verifier_log *log)
>> +{
>> + u32 log_true_size;
>> + size_t size;
>> + int err;
>> +
>> + if (!log)
>> + return 0;
>
> can this ever happen? why guard against this?
>
In patch #7, 'log' can be NULL when users do not provide 'log_buf'.
However, bpf_vlog_finalize() already guards against this case, so I'll
drop this check.
>> +
>> + err = bpf_vlog_finalize(log, &log_true_size);
>> +
>> + size = sizeof(log_true_size);
>> + if (attr->uattr_size >= attr->offsetof_true_size + size &&
>> + copy_to_bpfptr_offset(attr->uattr, attr->offsetof_true_size, &log_true_size, size))
>> + err = -EFAULT;
>
> minor nit: return -EFAULT;
>
Ack.
Thanks,
Leon
^ permalink raw reply
* Re: [PATCH bpf-next v9 4/9] bpf: Add syscall common attributes support for prog_load
From: Leon Hwang @ 2026-02-05 3:42 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
In-Reply-To: <CAEf4Bza-PM9ExqJS=Q_oj7Cqc5dvmbN_Zv9-4UnJNtsZU28FoQ@mail.gmail.com>
On 5/2/26 03:48, Andrii Nakryiko wrote:
> On Mon, Feb 2, 2026 at 6:42 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
>> BPF_PROG_LOAD can now provide log parameters through both union bpf_attr
>> and struct bpf_common_attr. Define clear conflict and precedence rules:
>>
>> - if both are provided and log_buf/log_size/log_level match, use them;
>> - if only one side provides a log buffer, use that one;
>> - if both provide log buffers but differ, return -EINVAL.
>>
>> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
>> ---
>> include/linux/bpf_verifier.h | 3 ++-
>> kernel/bpf/log.c | 24 ++++++++++++++++++++++--
>> kernel/bpf/syscall.c | 3 ++-
>> 3 files changed, 26 insertions(+), 4 deletions(-)
>>
>> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
>> index c805b85b6f7a..0d106fddbbc5 100644
>> --- a/include/linux/bpf_verifier.h
>> +++ b/include/linux/bpf_verifier.h
>> @@ -638,7 +638,8 @@ struct bpf_log_attr {
>> };
>>
>> int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
>> - bpfptr_t uattr, u32 size);
>> + bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
>> + bpfptr_t uattr_common, u32 size_common);
>> 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 ff579fcba36f..345005ba98dd 100644
>> --- a/kernel/bpf/log.c
>> +++ b/kernel/bpf/log.c
>> @@ -873,10 +873,30 @@ static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_s
>> attr_log->uattr = uattr;
>> }
>>
>> +static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
>> + u32 log_level)
>> +{
>> + return log_buf && common->log_buf && (log_buf != common->log_buf ||
>> + log_size != common->log_size ||
>> + log_level != common->log_level);
>
> let's validate (unless we do this somewhere else) that if log_buf is
> set, then log_size and log_level (? not sure, maybe zero is fine) are
> set, or all three are not set. Same for common->log* fields...
>
Ack.
Will validate 'log_buf && log_size && log_level' first.
>
>> +}
>> +
>> int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
>> - bpfptr_t uattr, u32 size)
>> + bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
>> + bpfptr_t uattr_common, u32 size_common)
>> {
>> - bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
>> + if (bpf_log_attrs_diff(attr_common, attr->log_buf, attr->log_size, attr->log_level))
>> + return -EINVAL;
>> +
>> + if (!attr->log_buf && attr_common->log_buf) {
>> + attr->log_buf = attr_common->log_buf;
>> + attr->log_size = attr_common->log_size;
>> + attr->log_level = attr_common->log_level;
>
> why are we setting this? Do we still have code that can access
> attr->log_buf even though we pass attr_log everywhere? If yes, should
> we still have that "split brain" code?
>
'attr->log_buf' is accessed only in bpf_check().
> If we don't have this assignment, then I think we don't need to have
> bpf_prog_load-specific and btf_load-specific log_attr_init() helpers.
> They can be unified into generic log_attr_init, where for
> bpf_prog_load you'll pass offsetof(log_true_size) +
> attr->log_{buf,size,level}, and for btf_load you'll pass different
> offset of and btf-specific attr->btf_log*
>
> This helper will just be making decision whether to use common_attr's
> log fields or passed directly command-specific ones.
>
> Or what am I missing?
>
If the log attributes differ, where should the effective
log_* values be stored?
Should they live in struct bpf_common_attr, or should we extend
struct bpf_log_attr to carry them?
Note that in v8, Alexei suggested struct bpf_log_attr only needs
u32 offsetof_true_size;
bpfptr_t uattr;
so I’d like to clarify the intended direction here. Once that’s clear, a
single generic log_attr_init() should be sufficient to handle this.
Thanks,
Leon
>
>> + bpf_log_attr_init(attr_log, offsetof(struct bpf_common_attr, log_true_size),
>> + uattr_common, size_common);
>> + } else {
>> + bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
>> + }
>> return 0;
>> }
>>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index e81199361241..7125ea445c6c 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
>> @@ -6232,7 +6232,8 @@ 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_log_attr_init(&attr_log, &attr, uattr, size);
>> + err = bpf_prog_load_log_attr_init(&attr_log, &attr, uattr, 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
* Re: [PATCH bpf-next v9 8/9] libbpf: Add syscall common attributes support for map_create
From: Leon Hwang @ 2026-02-05 3:45 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
In-Reply-To: <CAEf4Bzb=96Ja38VGBr9YGGSSjaWwhkfH_oWjMJULykA-a7jZxA@mail.gmail.com>
On 5/2/26 03:48, Andrii Nakryiko wrote:
> On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
>> 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.
>>
>> 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(-)
>>
>
> LGTM
>
> Acked-by: Andrii Nakryiko <andrii@kernel.org>
>
Thanks for your review.
>> 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..59673f094f86 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;
>
> please mention in the comment here that this is an out parameter set
> by the kernel
>
Ack.
I'll add a comment in the next revision.
Thanks,
Leon
>> +
>> + 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
* Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
From: Leon Hwang @ 2026-02-05 3:53 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
In-Reply-To: <CAADnVQLXWQ8Miq2WBoXRDsEVP1QPwk=a5=Rj_uPN+9qKHZZmZw@mail.gmail.com>
On 5/2/26 04:14, Alexei Starovoitov wrote:
> On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
>>
>> +
>> +#define BPF_LOG_FIXED 8
>> +
>> +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 = BPF_LOG_FIXED;
>
> Why? Which part of the test needs the log with this flag?
BPF_LOG_FIXED looks odd here.
This test sets 'log_level = BPF_LOG_FIXED' to match the behavior of
bpf_vlog_init() as initialized by bpf_log_attr_create_vlog() in
patch #7. BPF_LOG_FIXED is intended to be the default log_level
there.
Thanks,
Leon
^ permalink raw reply
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024
From: Jan Kara @ 2026-02-05 9:34 UTC (permalink / raw)
To: Zack Weinberg
Cc: Jeff Layton, Trevor Gross, Jan Kara, The 8472, Rich Felker,
Alejandro Colomar, Vincent Lefevre, Alexander Viro,
Christian Brauner, linux-fsdevel, linux-api, GNU libc development
In-Reply-To: <037a7546-cbbf-4c00-bebd-57cee38785e1@app.fastmail.com>
I've noticed we didn't reply to one question here:
On Wed 28-01-26 11:58:07, Zack Weinberg wrote:
> On Mon, Jan 26, 2026, at 7:49 PM, Jeff Layton wrote:
> > Checking the implementations e.g. FUSE and NFS *will* return delayed
> > writeback errors on *first* descriptor close even if there are other
> > still open descriptors for the description AFAICS.
> ...
> > fsync(2) must make sure data is persistently stored and return error if
> > it was not. Thus as a VFS person I'd consider it a filesystem bug if an
> > error preveting reading data later was not returned from fsync(2). OTOH
> > that doesn't necessarily mean that later close doesn't return an error -
> > e.g. FUSE does communicate with the server on close that can fail and
> > error can be returned.
> >
> > With this in mind let me now try to answer your remaining questions:
> >
> >> >> - The OFD was opened with O_RDONLY
> >
> > If the filesystem supports atime, close can in principle report that atime
> > update failed.
> >
> >> >> - The OFD was opened with O_RDWR but has never actually
> >> >> been written to
> >
> > The same as above but with inode mtime updates.
> >
> >> >> - No data has been written to the OFD since the last call to
> >> >> fsync() for that OFD
> >
> > No writeback errors should happen in this case. As I wrote above I'd
> > consider this a filesystem bug.
> >
> >> >>
> >> >> - No data has been written to the OFD since the last call to
> >> >> fdatasync() for that OFD
> >
> > Errors can happen because some inode metadata (in practice probably only
> > inode time stamps) may still need to be written out.
> >
> > So in the cases described above (except for fsync()) you may get delayed
> > errors on close. But since in all those cases no data is lost, I don't
> > think 99.9% of applications care at all...
>
> ... regrettably I think this does mean the close(3) manpage still needs
> to tell people to watch out for errors, and should probably say that
> errors _can_ happen even if the file wasn’t written to, but are much
> less likely to be important in that case.
>
> And my “how to close stdout in a thread-safe manner” sample code is
> wrong, because I was wrong to think that the error reporting only
> happened on the _final_ close, when the OFD is destroyed.
>
> ... What happens if the close is implicit in a dup2() operation? Here’s
> that erroneous “how to close stdout” fragment, with comments
> indicating what I thought could and could not fail at the time I wrote
> it:
>
> // These allocate new fds, which can always fail, e.g. because
> // the program already has too many files open.
> int new_stdout = open("/dev/null", O_WRONLY);
> if (new_stdout == -1) perror_exit("/dev/null");
> int old_stdout = dup(1);
> if (old_stdout == -1) perror_exit("dup(1)");
>
> flockfile(stdout);
> if (fflush(stdout)) perror_exit("stdout: write error");
> dup2(new_stdout, 1); // cannot fail, atomically replaces fd 1
> funlockfile(stdout);
>
> // this close may receive delayed write errors from previous writes
> // to stdout
> if (close(old_stdout)) perror_exit("stdout: write error");
>
> // this close cannot fail, because it only drops an alternative
> // reference to the open file description now installed as fd 1
> close(new_stdout);
>
> Note in particular that the first close _operation_ on fd 1 is in
> consequence of dup2(new_stdout, 1). The dup2() manpage specifically
> says “the close is performed silently (i.e. any errors during the
> close are not reported by dup()” but, if stdout points to a file on
> an NFS mount, are those errors _lost_, or will they actually be
> reported by the subsequent close(old_stdout)?
It is simply lost (the error is propagated from the filesystem to VFS which
just ignores it).
> Incidentally, the dup2() manpage has a very similar example in its
> NOTES section, also presuming that close only reports errors on the
> _final_ close, not when it “merely” drops reference >=2 to an OFD.
>
> (I’m starting to think we need dup3(old, new, O_SWAP_FDS). Or is that
> already a thing somehow?)
I don't think a functionality like this currently exists.
Honza
--
Jan Kara <jack@suse.com>
SUSE Labs, CR
^ permalink raw reply
* Re: [PATCH bpf-next v9 4/9] bpf: Add syscall common attributes support for prog_load
From: Andrii Nakryiko @ 2026-02-05 22:18 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
In-Reply-To: <a31b7f19-a22a-44ab-8ecd-9df9dead9c3d@linux.dev>
On Wed, Feb 4, 2026 at 7:42 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>
>
>
> On 5/2/26 03:48, Andrii Nakryiko wrote:
> > On Mon, Feb 2, 2026 at 6:42 AM Leon Hwang <leon.hwang@linux.dev> wrote:
> >>
> >> BPF_PROG_LOAD can now provide log parameters through both union bpf_attr
> >> and struct bpf_common_attr. Define clear conflict and precedence rules:
> >>
> >> - if both are provided and log_buf/log_size/log_level match, use them;
> >> - if only one side provides a log buffer, use that one;
> >> - if both provide log buffers but differ, return -EINVAL.
> >>
> >> Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
> >> ---
> >> include/linux/bpf_verifier.h | 3 ++-
> >> kernel/bpf/log.c | 24 ++++++++++++++++++++++--
> >> kernel/bpf/syscall.c | 3 ++-
> >> 3 files changed, 26 insertions(+), 4 deletions(-)
> >>
> >> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> >> index c805b85b6f7a..0d106fddbbc5 100644
> >> --- a/include/linux/bpf_verifier.h
> >> +++ b/include/linux/bpf_verifier.h
> >> @@ -638,7 +638,8 @@ struct bpf_log_attr {
> >> };
> >>
> >> int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
> >> - bpfptr_t uattr, u32 size);
> >> + bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
> >> + bpfptr_t uattr_common, u32 size_common);
> >> 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 ff579fcba36f..345005ba98dd 100644
> >> --- a/kernel/bpf/log.c
> >> +++ b/kernel/bpf/log.c
> >> @@ -873,10 +873,30 @@ static void bpf_log_attr_init(struct bpf_log_attr *attr_log, int offsetof_true_s
> >> attr_log->uattr = uattr;
> >> }
> >>
> >> +static bool bpf_log_attrs_diff(struct bpf_common_attr *common, u64 log_buf, u32 log_size,
> >> + u32 log_level)
> >> +{
> >> + return log_buf && common->log_buf && (log_buf != common->log_buf ||
> >> + log_size != common->log_size ||
> >> + log_level != common->log_level);
> >
> > let's validate (unless we do this somewhere else) that if log_buf is
> > set, then log_size and log_level (? not sure, maybe zero is fine) are
> > set, or all three are not set. Same for common->log* fields...
> >
>
> Ack.
>
> Will validate 'log_buf && log_size && log_level' first.
>
> >
> >> +}
> >> +
> >> int bpf_prog_load_log_attr_init(struct bpf_log_attr *attr_log, union bpf_attr *attr,
> >> - bpfptr_t uattr, u32 size)
> >> + bpfptr_t uattr, u32 size, struct bpf_common_attr *attr_common,
> >> + bpfptr_t uattr_common, u32 size_common)
> >> {
> >> - bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
> >> + if (bpf_log_attrs_diff(attr_common, attr->log_buf, attr->log_size, attr->log_level))
> >> + return -EINVAL;
> >> +
> >> + if (!attr->log_buf && attr_common->log_buf) {
> >> + attr->log_buf = attr_common->log_buf;
> >> + attr->log_size = attr_common->log_size;
> >> + attr->log_level = attr_common->log_level;
> >
> > why are we setting this? Do we still have code that can access
> > attr->log_buf even though we pass attr_log everywhere? If yes, should
> > we still have that "split brain" code?
> >
>
> 'attr->log_buf' is accessed only in bpf_check().
bpf_check should be changed then, see below
>
> > If we don't have this assignment, then I think we don't need to have
> > bpf_prog_load-specific and btf_load-specific log_attr_init() helpers.
> > They can be unified into generic log_attr_init, where for
> > bpf_prog_load you'll pass offsetof(log_true_size) +
> > attr->log_{buf,size,level}, and for btf_load you'll pass different
> > offset of and btf-specific attr->btf_log*
> >
> > This helper will just be making decision whether to use common_attr's
> > log fields or passed directly command-specific ones.
> >
> > Or what am I missing?
> >
>
> If the log attributes differ, where should the effective
> log_* values be stored?
>
> Should they live in struct bpf_common_attr, or should we extend
> struct bpf_log_attr to carry them?
>
> Note that in v8, Alexei suggested struct bpf_log_attr only needs
> u32 offsetof_true_size;
> bpfptr_t uattr;
>
> so I’d like to clarify the intended direction here. Once that’s clear, a
> single generic log_attr_init() should be sufficient to handle this.
>
The intended direction is to have log buf/size/level in one place
(after attr and common_attr validations), so we keep internal logic
simple. Let's put all of that and log_true_size **pointer** (we don't
have to much with offsetof, just calculate user addr for
log_true_size, which just might be NULL) into bpf_log_attrs and teach
all code to look and work *only* with that struct, ignoring anything
log related from attr.
> Thanks,
> Leon
>
> >
> >> + bpf_log_attr_init(attr_log, offsetof(struct bpf_common_attr, log_true_size),
> >> + uattr_common, size_common);
> >> + } else {
> >> + bpf_log_attr_init(attr_log, offsetof(union bpf_attr, log_true_size), uattr, size);
> >> + }
> >> return 0;
> >> }
> >>
> >> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> >> index e81199361241..7125ea445c6c 100644
> >> --- a/kernel/bpf/syscall.c
> >> +++ b/kernel/bpf/syscall.c
> >> @@ -6232,7 +6232,8 @@ 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_log_attr_init(&attr_log, &attr, uattr, size);
> >> + err = bpf_prog_load_log_attr_init(&attr_log, &attr, uattr, 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
* Re: [PATCH bpf-next v9 9/9] selftests/bpf: Add tests to verify map create failure log
From: Alexei Starovoitov @ 2026-02-05 23:18 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
In-Reply-To: <11bb515b-35fd-44f3-9647-9c39580ce6a1@linux.dev>
On Wed, Feb 4, 2026 at 7:54 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>
>
>
> On 5/2/26 04:14, Alexei Starovoitov wrote:
> > On Mon, Feb 2, 2026 at 6:43 AM Leon Hwang <leon.hwang@linux.dev> wrote:
> >>
> >> +
> >> +#define BPF_LOG_FIXED 8
> >> +
> >> +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 = BPF_LOG_FIXED;
> >
> > Why? Which part of the test needs the log with this flag?
>
> BPF_LOG_FIXED looks odd here.
>
> This test sets 'log_level = BPF_LOG_FIXED' to match the behavior of
> bpf_vlog_init() as initialized by bpf_log_attr_create_vlog() in
> patch #7. BPF_LOG_FIXED is intended to be the default log_level
> there.
I don't think you answered my question.
bpf_vlog_init() is using whatever log_level user space provided.
Why do you pass BPF_LOG_FIXED ?
^ permalink raw reply
* Re: [PATCH bpf-next v9 4/9] bpf: Add syscall common attributes support for prog_load
From: Leon Hwang @ 2026-02-06 2:45 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
In-Reply-To: <CAEf4BzZWawrE+mXaPNPAT8zcz0Qy+5QYA6r4JzEVw7UAcUH-uA@mail.gmail.com>
On 6/2/26 06:18, Andrii Nakryiko wrote:
> On Wed, Feb 4, 2026 at 7:42 PM Leon Hwang <leon.hwang@linux.dev> wrote:
[...]
>>>> +
>>>> + if (!attr->log_buf && attr_common->log_buf) {
>>>> + attr->log_buf = attr_common->log_buf;
>>>> + attr->log_size = attr_common->log_size;
>>>> + attr->log_level = attr_common->log_level;
>>>
>>> why are we setting this? Do we still have code that can access
>>> attr->log_buf even though we pass attr_log everywhere? If yes, should
>>> we still have that "split brain" code?
>>>
>>
>> 'attr->log_buf' is accessed only in bpf_check().
>
> bpf_check should be changed then, see below
>
>>
>>> If we don't have this assignment, then I think we don't need to have
>>> bpf_prog_load-specific and btf_load-specific log_attr_init() helpers.
>>> They can be unified into generic log_attr_init, where for
>>> bpf_prog_load you'll pass offsetof(log_true_size) +
>>> attr->log_{buf,size,level}, and for btf_load you'll pass different
>>> offset of and btf-specific attr->btf_log*
>>>
>>> This helper will just be making decision whether to use common_attr's
>>> log fields or passed directly command-specific ones.
>>>
>>> Or what am I missing?
>>>
>>
>> If the log attributes differ, where should the effective
>> log_* values be stored?
>>
>> Should they live in struct bpf_common_attr, or should we extend
>> struct bpf_log_attr to carry them?
>>
>> Note that in v8, Alexei suggested struct bpf_log_attr only needs
>> u32 offsetof_true_size;
>> bpfptr_t uattr;
>>
>> so I’d like to clarify the intended direction here. Once that’s clear, a
>> single generic log_attr_init() should be sufficient to handle this.
>>
>
> The intended direction is to have log buf/size/level in one place
> (after attr and common_attr validations), so we keep internal logic
> simple. Let's put all of that and log_true_size **pointer** (we don't
> have to much with offsetof, just calculate user addr for
> log_true_size, which just might be NULL) into bpf_log_attrs and teach
> all code to look and work *only* with that struct, ignoring anything
> log related from attr.
>
It’s clear now.
I’ll follow this direction in the next revision and consolidate all
log-related fields (including the log_true_size pointer) into
bpf_log_attr, so that internal code relies solely on that struct.
Thanks,
Leon
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox