* [PATCH bpf-next v11 01/12] bpf: add fsession support
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline Menglong Dong
` (10 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
The fsession is something that similar to kprobe session. It allow to
attach a single BPF program to both the entry and the exit of the target
functions.
Introduce the struct bpf_fsession_link, which allows to add the link to
both the fentry and fexit progs_hlist of the trampoline.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
Co-developed-by: Leon Hwang <leon.hwang@linux.dev>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
v10:
- use switch in bpf_prog_has_trampoline()
- some nits adjustment
v5:
- unify the name to "fsession"
- use more explicit way in __bpf_trampoline_link_prog()
v4:
- instead of adding a new hlist to progs_hlist in trampoline, add the bpf
program to both the fentry hlist and the fexit hlist.
---
include/linux/bpf.h | 19 +++++++
include/uapi/linux/bpf.h | 1 +
kernel/bpf/btf.c | 2 +
kernel/bpf/syscall.c | 18 ++++++-
kernel/bpf/trampoline.c | 53 ++++++++++++++++---
kernel/bpf/verifier.c | 12 +++--
net/bpf/test_run.c | 1 +
net/core/bpf_sk_storage.c | 1 +
tools/include/uapi/linux/bpf.h | 1 +
.../bpf/prog_tests/tracing_failure.c | 2 +-
10 files changed, 97 insertions(+), 13 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 5936f8e2996f..41228b0add52 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1309,6 +1309,7 @@ enum bpf_tramp_prog_type {
BPF_TRAMP_MODIFY_RETURN,
BPF_TRAMP_MAX,
BPF_TRAMP_REPLACE, /* more than MAX */
+ BPF_TRAMP_FSESSION,
};
struct bpf_tramp_image {
@@ -1875,6 +1876,11 @@ struct bpf_tracing_link {
struct bpf_prog *tgt_prog;
};
+struct bpf_fsession_link {
+ struct bpf_tracing_link link;
+ struct bpf_tramp_link fexit;
+};
+
struct bpf_raw_tp_link {
struct bpf_link link;
struct bpf_raw_event_map *btp;
@@ -2169,6 +2175,19 @@ static inline void bpf_struct_ops_desc_release(struct bpf_struct_ops_desc *st_op
#endif
+static inline int bpf_fsession_cnt(struct bpf_tramp_links *links)
+{
+ struct bpf_tramp_links fentries = links[BPF_TRAMP_FENTRY];
+ int cnt = 0;
+
+ for (int i = 0; i < links[BPF_TRAMP_FENTRY].nr_links; i++) {
+ if (fentries.links[i]->link.prog->expected_attach_type == BPF_TRACE_FSESSION)
+ cnt++;
+ }
+
+ return cnt;
+}
+
int bpf_prog_ctx_arg_info_init(struct bpf_prog *prog,
const struct bpf_ctx_arg_aux *info, u32 cnt);
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 2a2ade4be60f..44e7dbc278e3 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1145,6 +1145,7 @@ enum bpf_attach_type {
BPF_NETKIT_PEER,
BPF_TRACE_KPROBE_SESSION,
BPF_TRACE_UPROBE_SESSION,
+ BPF_TRACE_FSESSION,
__MAX_BPF_ATTACH_TYPE
};
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index d10b3404260f..8959f3bc1e92 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6219,6 +6219,7 @@ static int btf_validate_prog_ctx_type(struct bpf_verifier_log *log, const struct
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
case BPF_MODIFY_RETURN:
+ case BPF_TRACE_FSESSION:
/* allow u64* as ctx */
if (btf_is_int(t) && t->size == 8)
return 0;
@@ -6820,6 +6821,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
fallthrough;
case BPF_LSM_CGROUP:
case BPF_TRACE_FEXIT:
+ case BPF_TRACE_FSESSION:
/* When LSM programs are attached to void LSM hooks
* they use FEXIT trampolines and when attached to
* int LSM hooks, they use MODIFY_RETURN trampolines.
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 3c5c03d43f5f..b9184545c3fd 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -3577,6 +3577,7 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog,
case BPF_PROG_TYPE_TRACING:
if (prog->expected_attach_type != BPF_TRACE_FENTRY &&
prog->expected_attach_type != BPF_TRACE_FEXIT &&
+ prog->expected_attach_type != BPF_TRACE_FSESSION &&
prog->expected_attach_type != BPF_MODIFY_RETURN) {
err = -EINVAL;
goto out_put_prog;
@@ -3626,7 +3627,21 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog,
key = bpf_trampoline_compute_key(tgt_prog, NULL, btf_id);
}
- link = kzalloc(sizeof(*link), GFP_USER);
+ if (prog->expected_attach_type == BPF_TRACE_FSESSION) {
+ struct bpf_fsession_link *fslink;
+
+ fslink = kzalloc(sizeof(*fslink), GFP_USER);
+ if (fslink) {
+ bpf_link_init(&fslink->fexit.link, BPF_LINK_TYPE_TRACING,
+ &bpf_tracing_link_lops, prog, attach_type);
+ fslink->fexit.cookie = bpf_cookie;
+ link = &fslink->link;
+ } else {
+ link = NULL;
+ }
+ } else {
+ link = kzalloc(sizeof(*link), GFP_USER);
+ }
if (!link) {
err = -ENOMEM;
goto out_put_prog;
@@ -4350,6 +4365,7 @@ attach_type_to_prog_type(enum bpf_attach_type attach_type)
case BPF_TRACE_RAW_TP:
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
+ case BPF_TRACE_FSESSION:
case BPF_MODIFY_RETURN:
return BPF_PROG_TYPE_TRACING;
case BPF_LSM_MAC:
diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index 2a125d063e62..edf9da43762d 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -109,10 +109,17 @@ bool bpf_prog_has_trampoline(const struct bpf_prog *prog)
enum bpf_attach_type eatype = prog->expected_attach_type;
enum bpf_prog_type ptype = prog->type;
- return (ptype == BPF_PROG_TYPE_TRACING &&
- (eatype == BPF_TRACE_FENTRY || eatype == BPF_TRACE_FEXIT ||
- eatype == BPF_MODIFY_RETURN)) ||
- (ptype == BPF_PROG_TYPE_LSM && eatype == BPF_LSM_MAC);
+ switch (ptype) {
+ case BPF_PROG_TYPE_TRACING:
+ if (eatype == BPF_TRACE_FENTRY || eatype == BPF_TRACE_FEXIT ||
+ eatype == BPF_MODIFY_RETURN || eatype == BPF_TRACE_FSESSION)
+ return true;
+ return false;
+ case BPF_PROG_TYPE_LSM:
+ return eatype == BPF_LSM_MAC;
+ default:
+ return false;
+ }
}
void bpf_image_ksym_init(void *data, unsigned int size, struct bpf_ksym *ksym)
@@ -559,6 +566,8 @@ static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
return BPF_TRAMP_MODIFY_RETURN;
case BPF_TRACE_FEXIT:
return BPF_TRAMP_FEXIT;
+ case BPF_TRACE_FSESSION:
+ return BPF_TRAMP_FSESSION;
case BPF_LSM_MAC:
if (!prog->aux->attach_func_proto->type)
/* The function returns void, we cannot modify its
@@ -594,8 +603,10 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link,
struct bpf_trampoline *tr,
struct bpf_prog *tgt_prog)
{
+ struct bpf_fsession_link *fslink = NULL;
enum bpf_tramp_prog_type kind;
struct bpf_tramp_link *link_exiting;
+ struct hlist_head *prog_list;
int err = 0;
int cnt = 0, i;
@@ -621,24 +632,43 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_link *link,
BPF_MOD_JUMP, NULL,
link->link.prog->bpf_func);
}
+ if (kind == BPF_TRAMP_FSESSION) {
+ prog_list = &tr->progs_hlist[BPF_TRAMP_FENTRY];
+ cnt++;
+ } else {
+ prog_list = &tr->progs_hlist[kind];
+ }
if (cnt >= BPF_MAX_TRAMP_LINKS)
return -E2BIG;
if (!hlist_unhashed(&link->tramp_hlist))
/* prog already linked */
return -EBUSY;
- hlist_for_each_entry(link_exiting, &tr->progs_hlist[kind], tramp_hlist) {
+ hlist_for_each_entry(link_exiting, prog_list, tramp_hlist) {
if (link_exiting->link.prog != link->link.prog)
continue;
/* prog already linked */
return -EBUSY;
}
- hlist_add_head(&link->tramp_hlist, &tr->progs_hlist[kind]);
- tr->progs_cnt[kind]++;
+ hlist_add_head(&link->tramp_hlist, prog_list);
+ if (kind == BPF_TRAMP_FSESSION) {
+ tr->progs_cnt[BPF_TRAMP_FENTRY]++;
+ fslink = container_of(link, struct bpf_fsession_link, link.link);
+ hlist_add_head(&fslink->fexit.tramp_hlist, &tr->progs_hlist[BPF_TRAMP_FEXIT]);
+ tr->progs_cnt[BPF_TRAMP_FEXIT]++;
+ } else {
+ tr->progs_cnt[kind]++;
+ }
err = bpf_trampoline_update(tr, true /* lock_direct_mutex */);
if (err) {
hlist_del_init(&link->tramp_hlist);
- tr->progs_cnt[kind]--;
+ if (kind == BPF_TRAMP_FSESSION) {
+ tr->progs_cnt[BPF_TRAMP_FENTRY]--;
+ hlist_del_init(&fslink->fexit.tramp_hlist);
+ tr->progs_cnt[BPF_TRAMP_FEXIT]--;
+ } else {
+ tr->progs_cnt[kind]--;
+ }
}
return err;
}
@@ -672,6 +702,13 @@ static int __bpf_trampoline_unlink_prog(struct bpf_tramp_link *link,
guard(mutex)(&tgt_prog->aux->ext_mutex);
tgt_prog->aux->is_extended = false;
return err;
+ } else if (kind == BPF_TRAMP_FSESSION) {
+ struct bpf_fsession_link *fslink =
+ container_of(link, struct bpf_fsession_link, link.link);
+
+ hlist_del_init(&fslink->fexit.tramp_hlist);
+ tr->progs_cnt[BPF_TRAMP_FEXIT]--;
+ kind = BPF_TRAMP_FENTRY;
}
hlist_del_init(&link->tramp_hlist);
tr->progs_cnt[kind]--;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index c7f5234d5fd2..41bbed6418b5 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -17848,6 +17848,7 @@ static int check_return_code(struct bpf_verifier_env *env, int regno, const char
switch (env->prog->expected_attach_type) {
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
+ case BPF_TRACE_FSESSION:
range = retval_range(0, 0);
break;
case BPF_TRACE_RAW_TP:
@@ -23774,6 +23775,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
if (prog_type == BPF_PROG_TYPE_TRACING &&
insn->imm == BPF_FUNC_get_func_ret) {
if (eatype == BPF_TRACE_FEXIT ||
+ eatype == BPF_TRACE_FSESSION ||
eatype == BPF_MODIFY_RETURN) {
/* Load nr_args from ctx - 8 */
insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
@@ -24725,7 +24727,8 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
if (tgt_prog->type == BPF_PROG_TYPE_TRACING &&
prog_extension &&
(tgt_prog->expected_attach_type == BPF_TRACE_FENTRY ||
- tgt_prog->expected_attach_type == BPF_TRACE_FEXIT)) {
+ tgt_prog->expected_attach_type == BPF_TRACE_FEXIT ||
+ tgt_prog->expected_attach_type == BPF_TRACE_FSESSION)) {
/* Program extensions can extend all program types
* except fentry/fexit. The reason is the following.
* The fentry/fexit programs are used for performance
@@ -24740,7 +24743,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
* beyond reasonable stack size. Hence extending fentry
* is not allowed.
*/
- bpf_log(log, "Cannot extend fentry/fexit\n");
+ bpf_log(log, "Cannot extend fentry/fexit/fsession\n");
return -EINVAL;
}
} else {
@@ -24824,6 +24827,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
case BPF_LSM_CGROUP:
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
+ case BPF_TRACE_FSESSION:
if (!btf_type_is_func(t)) {
bpf_log(log, "attach_btf_id %u is not a function\n",
btf_id);
@@ -24990,6 +24994,7 @@ static bool can_be_sleepable(struct bpf_prog *prog)
case BPF_TRACE_FEXIT:
case BPF_MODIFY_RETURN:
case BPF_TRACE_ITER:
+ case BPF_TRACE_FSESSION:
return true;
default:
return false;
@@ -25071,9 +25076,10 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
tgt_info.tgt_name);
return -EINVAL;
} else if ((prog->expected_attach_type == BPF_TRACE_FEXIT ||
+ prog->expected_attach_type == BPF_TRACE_FSESSION ||
prog->expected_attach_type == BPF_MODIFY_RETURN) &&
btf_id_set_contains(&noreturn_deny, btf_id)) {
- verbose(env, "Attaching fexit/fmod_ret to __noreturn function '%s' is rejected.\n",
+ verbose(env, "Attaching fexit/fsession/fmod_ret to __noreturn function '%s' is rejected.\n",
tgt_info.tgt_name);
return -EINVAL;
}
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 26cfcfdc45eb..178c4738e63b 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -685,6 +685,7 @@ int bpf_prog_test_run_tracing(struct bpf_prog *prog,
switch (prog->expected_attach_type) {
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
+ case BPF_TRACE_FSESSION:
if (bpf_fentry_test1(1) != 2 ||
bpf_fentry_test2(2, 3) != 5 ||
bpf_fentry_test3(4, 5, 6) != 15 ||
diff --git a/net/core/bpf_sk_storage.c b/net/core/bpf_sk_storage.c
index 850dd736ccd1..de111818f3a0 100644
--- a/net/core/bpf_sk_storage.c
+++ b/net/core/bpf_sk_storage.c
@@ -365,6 +365,7 @@ static bool bpf_sk_storage_tracing_allowed(const struct bpf_prog *prog)
return true;
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
+ case BPF_TRACE_FSESSION:
return !!strncmp(prog->aux->attach_func_name, "bpf_sk_storage",
strlen("bpf_sk_storage"));
default:
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index b816bc53d2e1..3ca7d76e05f0 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1145,6 +1145,7 @@ enum bpf_attach_type {
BPF_NETKIT_PEER,
BPF_TRACE_KPROBE_SESSION,
BPF_TRACE_UPROBE_SESSION,
+ BPF_TRACE_FSESSION,
__MAX_BPF_ATTACH_TYPE
};
diff --git a/tools/testing/selftests/bpf/prog_tests/tracing_failure.c b/tools/testing/selftests/bpf/prog_tests/tracing_failure.c
index 10e231965589..f9f9e1cb87bf 100644
--- a/tools/testing/selftests/bpf/prog_tests/tracing_failure.c
+++ b/tools/testing/selftests/bpf/prog_tests/tracing_failure.c
@@ -73,7 +73,7 @@ static void test_tracing_deny(void)
static void test_fexit_noreturns(void)
{
test_tracing_fail_prog("fexit_noreturns",
- "Attaching fexit/fmod_ret to __noreturn function 'do_exit' is rejected.");
+ "Attaching fexit/fsession/fmod_ret to __noreturn function 'do_exit' is rejected.");
}
void test_tracing_failure(void)
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 01/12] bpf: add " Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 8:07 ` bot+bpf-ci
2026-01-23 7:35 ` [PATCH bpf-next v11 03/12] bpf: change prototype of bpf_session_{cookie,is_return} Menglong Dong
` (9 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
For now, ((u64 *)ctx)[-1] is used to store the nr_args in the trampoline.
However, 1 byte is enough to store such information. Therefore, we use
only the least significant byte of ((u64 *)ctx)[-1] to store the nr_args,
and reserve the rest for other usages.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
v11:
- fix the rebase conflict
v10:
- some adjustment to the subject and commit log to make the description
more precise.
v8:
- fix the missed get_func_arg_cnt
---
kernel/bpf/verifier.c | 38 ++++++++++++++++++++++----------------
kernel/trace/bpf_trace.c | 6 +++---
2 files changed, 25 insertions(+), 19 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 41bbed6418b5..b3f912ad18ba 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -23747,19 +23747,21 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
/* skip 'void *__data' in btf_trace_##name() and save to reg0 */
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
+ cnt = 1;
} else {
/* Load nr_args from ctx - 8 */
insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
+ insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
+ cnt = 2;
}
- insn_buf[1] = BPF_JMP32_REG(BPF_JGE, BPF_REG_2, BPF_REG_0, 6);
- insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 3);
- insn_buf[3] = BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1);
- insn_buf[4] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 0);
- insn_buf[5] = BPF_STX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0);
- insn_buf[6] = BPF_MOV64_IMM(BPF_REG_0, 0);
- insn_buf[7] = BPF_JMP_A(1);
- insn_buf[8] = BPF_MOV64_IMM(BPF_REG_0, -EINVAL);
- cnt = 9;
+ insn_buf[cnt++] = BPF_JMP32_REG(BPF_JGE, BPF_REG_2, BPF_REG_0, 6);
+ insn_buf[cnt++] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_2, 3);
+ insn_buf[cnt++] = BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_1);
+ insn_buf[cnt++] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_2, 0);
+ insn_buf[cnt++] = BPF_STX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0);
+ insn_buf[cnt++] = BPF_MOV64_IMM(BPF_REG_0, 0);
+ insn_buf[cnt++] = BPF_JMP_A(1);
+ insn_buf[cnt++] = BPF_MOV64_IMM(BPF_REG_0, -EINVAL);
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
if (!new_prog)
@@ -23779,12 +23781,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
eatype == BPF_MODIFY_RETURN) {
/* Load nr_args from ctx - 8 */
insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
- insn_buf[1] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
- insn_buf[2] = BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1);
- insn_buf[3] = BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0);
- insn_buf[4] = BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0);
- insn_buf[5] = BPF_MOV64_IMM(BPF_REG_0, 0);
- cnt = 6;
+ insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
+ insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
+ insn_buf[3] = BPF_ALU64_REG(BPF_ADD, BPF_REG_0, BPF_REG_1);
+ insn_buf[4] = BPF_LDX_MEM(BPF_DW, BPF_REG_3, BPF_REG_0, 0);
+ insn_buf[5] = BPF_STX_MEM(BPF_DW, BPF_REG_2, BPF_REG_3, 0);
+ insn_buf[6] = BPF_MOV64_IMM(BPF_REG_0, 0);
+ cnt = 7;
} else {
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, -EOPNOTSUPP);
cnt = 1;
@@ -23808,12 +23811,15 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
/* skip 'void *__data' in btf_trace_##name() and save to reg0 */
insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
+ cnt = 1;
} else {
/* Load nr_args from ctx - 8 */
insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
+ insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
+ cnt = 2;
}
- new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
+ new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
if (!new_prog)
return -ENOMEM;
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 0e9635bcd783..d466a1503da3 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1194,7 +1194,7 @@ const struct bpf_func_proto bpf_get_branch_snapshot_proto = {
BPF_CALL_3(get_func_arg, void *, ctx, u32, n, u64 *, value)
{
/* This helper call is inlined by verifier. */
- u64 nr_args = ((u64 *)ctx)[-1];
+ u64 nr_args = ((u64 *)ctx)[-1] & 0xFF;
if ((u64) n >= nr_args)
return -EINVAL;
@@ -1214,7 +1214,7 @@ static const struct bpf_func_proto bpf_get_func_arg_proto = {
BPF_CALL_2(get_func_ret, void *, ctx, u64 *, value)
{
/* This helper call is inlined by verifier. */
- u64 nr_args = ((u64 *)ctx)[-1];
+ u64 nr_args = ((u64 *)ctx)[-1] & 0xFF;
*value = ((u64 *)ctx)[nr_args];
return 0;
@@ -1231,7 +1231,7 @@ static const struct bpf_func_proto bpf_get_func_ret_proto = {
BPF_CALL_1(get_func_arg_cnt, void *, ctx)
{
/* This helper call is inlined by verifier. */
- return ((u64 *)ctx)[-1];
+ return ((u64 *)ctx)[-1] & 0xFF;
}
static const struct bpf_func_proto bpf_get_func_arg_cnt_proto = {
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline
2026-01-23 7:35 ` [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline Menglong Dong
@ 2026-01-23 8:07 ` bot+bpf-ci
2026-01-23 8:29 ` Menglong Dong
0 siblings, 1 reply; 22+ messages in thread
From: bot+bpf-ci @ 2026-01-23 8:07 UTC (permalink / raw)
To: menglong8.dong, andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2461 bytes --]
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 41bbed6418b5..b3f912ad18ba 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
[ ... ]
> @@ -23779,12 +23781,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> eatype == BPF_MODIFY_RETURN) {
> /* Load nr_args from ctx - 8 */
> insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> - insn_buf[1] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> + insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
[ ... ]
> - cnt = 6;
> + cnt = 7;
> } else {
> insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, -EOPNOTSUPP);
> cnt = 1;
> }
>
> new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
[ ... ]
> delta += cnt - 1;
Note that the bpf_get_func_ret block above correctly updates delta after
patching.
> @@ -23808,12 +23811,15 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
>
> /* skip 'void *__data' in btf_trace_##name() and save to reg0 */
> insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
> + cnt = 1;
> } else {
> /* Load nr_args from ctx - 8 */
> insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> + cnt = 2;
> }
>
> - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
> + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> if (!new_prog)
> return -ENOMEM;
>
> env->prog = prog = new_prog;
> insn = new_prog->insnsi + i + delta;
> goto next_insn;
> }
Should there be a "delta += cnt - 1;" before assigning env->prog in this
bpf_get_func_arg_cnt block? When cnt is 2 (non-RAW_TP path), the program
grows by one instruction, but delta is not updated. This could cause
subsequent bpf_patch_insn_data() calls to use incorrect offsets.
The bpf_get_func_arg block at the beginning of this patch has:
delta += cnt - 1;
env->prog = prog = new_prog;
And the bpf_get_func_ret block similarly has delta updated. But this
bpf_get_func_arg_cnt block goes directly to env->prog assignment without
updating delta.
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline
2026-01-23 8:07 ` bot+bpf-ci
@ 2026-01-23 8:29 ` Menglong Dong
2026-01-23 9:21 ` Menglong Dong
0 siblings, 1 reply; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 8:29 UTC (permalink / raw)
To: menglong8.dong, andrii, bot+bpf-ci
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
On 2026/1/23 16:07 bot+bpf-ci@kernel.org write:
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 41bbed6418b5..b3f912ad18ba 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
>
> [ ... ]
>
> > @@ -23779,12 +23781,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > eatype == BPF_MODIFY_RETURN) {
> > /* Load nr_args from ctx - 8 */
> > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > - insn_buf[1] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > + insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
>
> [ ... ]
>
> > - cnt = 6;
> > + cnt = 7;
> > } else {
> > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, -EOPNOTSUPP);
> > cnt = 1;
> > }
> >
> > new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
>
> [ ... ]
>
> > delta += cnt - 1;
>
> Note that the bpf_get_func_ret block above correctly updates delta after
> patching.
>
> > @@ -23808,12 +23811,15 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> >
> > /* skip 'void *__data' in btf_trace_##name() and save to reg0 */
> > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
> > + cnt = 1;
> > } else {
> > /* Load nr_args from ctx - 8 */
> > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > + cnt = 2;
> > }
> >
> > - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
> > + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> > if (!new_prog)
> > return -ENOMEM;
> >
> > env->prog = prog = new_prog;
> > insn = new_prog->insnsi + i + delta;
> > goto next_insn;
> > }
>
> Should there be a "delta += cnt - 1;" before assigning env->prog in this
> bpf_get_func_arg_cnt block? When cnt is 2 (non-RAW_TP path), the program
> grows by one instruction, but delta is not updated. This could cause
> subsequent bpf_patch_insn_data() calls to use incorrect offsets.
>
> The bpf_get_func_arg block at the beginning of this patch has:
>
> delta += cnt - 1;
> env->prog = prog = new_prog;
>
> And the bpf_get_func_ret block similarly has delta updated. But this
> bpf_get_func_arg_cnt block goes directly to env->prog assignment without
> updating delta.
Ah, good point, I think this is a valid problem. The selftests didn't cover
this case, and I think I'd better to use bpf_get_func_arg() and bpf_get_func_ret()
in the exit path of fsession to cover it.
Will fix it in the next version.
Thanks!
Menglong Dong
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline
2026-01-23 8:29 ` Menglong Dong
@ 2026-01-23 9:21 ` Menglong Dong
2026-01-23 22:57 ` Andrii Nakryiko
0 siblings, 1 reply; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 9:21 UTC (permalink / raw)
To: menglong8.dong, andrii, bot+bpf-ci
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
On 2026/1/23 16:29 Menglong Dong <menglong.dong@linux.dev> write:
> On 2026/1/23 16:07 bot+bpf-ci@kernel.org write:
> > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > index 41bbed6418b5..b3f912ad18ba 100644
> > > --- a/kernel/bpf/verifier.c
> > > +++ b/kernel/bpf/verifier.c
> >
> > [ ... ]
> >
> > > @@ -23779,12 +23781,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > > eatype == BPF_MODIFY_RETURN) {
> > > /* Load nr_args from ctx - 8 */
> > > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > > - insn_buf[1] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> > > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > > + insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> >
> > [ ... ]
> >
> > > - cnt = 6;
> > > + cnt = 7;
> > > } else {
> > > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, -EOPNOTSUPP);
> > > cnt = 1;
> > > }
> > >
> > > new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> >
> > [ ... ]
> >
> > > delta += cnt - 1;
> >
> > Note that the bpf_get_func_ret block above correctly updates delta after
> > patching.
> >
> > > @@ -23808,12 +23811,15 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > >
> > > /* skip 'void *__data' in btf_trace_##name() and save to reg0 */
> > > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
> > > + cnt = 1;
> > > } else {
> > > /* Load nr_args from ctx - 8 */
> > > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > > + cnt = 2;
> > > }
> > >
> > > - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
> > > + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> > > if (!new_prog)
> > > return -ENOMEM;
> > >
> > > env->prog = prog = new_prog;
> > > insn = new_prog->insnsi + i + delta;
> > > goto next_insn;
> > > }
> >
> > Should there be a "delta += cnt - 1;" before assigning env->prog in this
> > bpf_get_func_arg_cnt block? When cnt is 2 (non-RAW_TP path), the program
> > grows by one instruction, but delta is not updated. This could cause
> > subsequent bpf_patch_insn_data() calls to use incorrect offsets.
> >
> > The bpf_get_func_arg block at the beginning of this patch has:
> >
> > delta += cnt - 1;
> > env->prog = prog = new_prog;
> >
> > And the bpf_get_func_ret block similarly has delta updated. But this
> > bpf_get_func_arg_cnt block goes directly to env->prog assignment without
> > updating delta.
>
> Ah, good point, I think this is a valid problem. The selftests didn't cover
> this case, and I think I'd better to use bpf_get_func_arg() and bpf_get_func_ret()
> in the exit path of fsession to cover it.
Oh, the problem doesn't have much impact. The only impact
is that the verifier will check the "r0 &= 0xFF" instruction redundantly.
I'll see if there is more comment before I send next version.
Thanks!
Menglong Dong
>
> Will fix it in the next version.
>
> Thanks!
> Menglong Dong
>
> >
> >
> > ---
> > AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> > See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> >
> > CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
> >
>
>
>
>
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline
2026-01-23 9:21 ` Menglong Dong
@ 2026-01-23 22:57 ` Andrii Nakryiko
2026-01-24 1:14 ` Menglong Dong
0 siblings, 1 reply; 22+ messages in thread
From: Andrii Nakryiko @ 2026-01-23 22:57 UTC (permalink / raw)
To: Menglong Dong
Cc: menglong8.dong, andrii, bot+bpf-ci, daniel, martin.lau, eddyz87,
song, yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa,
davem, dsahern, tglx, mingo, jiang.biao, bp, dave.hansen, x86,
hpa, bpf, netdev, linux-kernel, ast, martin.lau, clm,
ihor.solodrai
On Fri, Jan 23, 2026 at 1:21 AM Menglong Dong <menglong.dong@linux.dev> wrote:
>
> On 2026/1/23 16:29 Menglong Dong <menglong.dong@linux.dev> write:
> > On 2026/1/23 16:07 bot+bpf-ci@kernel.org write:
> > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > index 41bbed6418b5..b3f912ad18ba 100644
> > > > --- a/kernel/bpf/verifier.c
> > > > +++ b/kernel/bpf/verifier.c
> > >
> > > [ ... ]
> > >
> > > > @@ -23779,12 +23781,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > > > eatype == BPF_MODIFY_RETURN) {
> > > > /* Load nr_args from ctx - 8 */
> > > > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > > > - insn_buf[1] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> > > > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > > > + insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> > >
> > > [ ... ]
> > >
> > > > - cnt = 6;
> > > > + cnt = 7;
> > > > } else {
> > > > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, -EOPNOTSUPP);
> > > > cnt = 1;
> > > > }
> > > >
> > > > new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> > >
> > > [ ... ]
> > >
> > > > delta += cnt - 1;
> > >
> > > Note that the bpf_get_func_ret block above correctly updates delta after
> > > patching.
> > >
> > > > @@ -23808,12 +23811,15 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > > >
> > > > /* skip 'void *__data' in btf_trace_##name() and save to reg0 */
> > > > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
> > > > + cnt = 1;
> > > > } else {
> > > > /* Load nr_args from ctx - 8 */
> > > > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > > > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > > > + cnt = 2;
> > > > }
> > > >
> > > > - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
> > > > + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> > > > if (!new_prog)
> > > > return -ENOMEM;
> > > >
> > > > env->prog = prog = new_prog;
> > > > insn = new_prog->insnsi + i + delta;
> > > > goto next_insn;
> > > > }
> > >
> > > Should there be a "delta += cnt - 1;" before assigning env->prog in this
> > > bpf_get_func_arg_cnt block? When cnt is 2 (non-RAW_TP path), the program
> > > grows by one instruction, but delta is not updated. This could cause
> > > subsequent bpf_patch_insn_data() calls to use incorrect offsets.
> > >
> > > The bpf_get_func_arg block at the beginning of this patch has:
> > >
> > > delta += cnt - 1;
> > > env->prog = prog = new_prog;
> > >
> > > And the bpf_get_func_ret block similarly has delta updated. But this
> > > bpf_get_func_arg_cnt block goes directly to env->prog assignment without
> > > updating delta.
> >
> > Ah, good point, I think this is a valid problem. The selftests didn't cover
> > this case, and I think I'd better to use bpf_get_func_arg() and bpf_get_func_ret()
> > in the exit path of fsession to cover it.
>
> Oh, the problem doesn't have much impact. The only impact
> is that the verifier will check the "r0 &= 0xFF" instruction redundantly.
>
> I'll see if there is more comment before I send next version.
>
Let's still fix the problem. Just go ahead and resubmit (with the fix
and improved test).
pw-bot: cr
> Thanks!
> Menglong Dong
>
> >
> > Will fix it in the next version.
> >
> > Thanks!
> > Menglong Dong
> >
> > >
> > >
> > > ---
> > > AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> > > See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> > >
> > > CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
> > >
> >
> >
> >
> >
> >
> >
>
>
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline
2026-01-23 22:57 ` Andrii Nakryiko
@ 2026-01-24 1:14 ` Menglong Dong
0 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-24 1:14 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: menglong8.dong, andrii, bot+bpf-ci, daniel, martin.lau, eddyz87,
song, yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa,
davem, dsahern, tglx, mingo, jiang.biao, bp, dave.hansen, x86,
hpa, bpf, netdev, linux-kernel, ast, martin.lau, clm,
ihor.solodrai
On 2026/1/24 06:57, Andrii Nakryiko wrote:
> On Fri, Jan 23, 2026 at 1:21 AM Menglong Dong <menglong.dong@linux.dev> wrote:
> >
> > On 2026/1/23 16:29 Menglong Dong <menglong.dong@linux.dev> write:
> > > On 2026/1/23 16:07 bot+bpf-ci@kernel.org write:
> > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > > index 41bbed6418b5..b3f912ad18ba 100644
> > > > > --- a/kernel/bpf/verifier.c
> > > > > +++ b/kernel/bpf/verifier.c
> > > >
> > > > [ ... ]
> > > >
> > > > > @@ -23779,12 +23781,13 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > > > > eatype == BPF_MODIFY_RETURN) {
> > > > > /* Load nr_args from ctx - 8 */
> > > > > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > > > > - insn_buf[1] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> > > > > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > > > > + insn_buf[2] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
> > > >
> > > > [ ... ]
> > > >
> > > > > - cnt = 6;
> > > > > + cnt = 7;
> > > > > } else {
> > > > > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, -EOPNOTSUPP);
> > > > > cnt = 1;
> > > > > }
> > > > >
> > > > > new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> > > >
> > > > [ ... ]
> > > >
> > > > > delta += cnt - 1;
> > > >
> > > > Note that the bpf_get_func_ret block above correctly updates delta after
> > > > patching.
> > > >
> > > > > @@ -23808,12 +23811,15 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
> > > > >
> > > > > /* skip 'void *__data' in btf_trace_##name() and save to reg0 */
> > > > > insn_buf[0] = BPF_MOV64_IMM(BPF_REG_0, nr_args - 1);
> > > > > + cnt = 1;
> > > > > } else {
> > > > > /* Load nr_args from ctx - 8 */
> > > > > insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > > > > + insn_buf[1] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
> > > > > + cnt = 2;
> > > > > }
> > > > >
> > > > > - new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, 1);
> > > > > + new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
> > > > > if (!new_prog)
> > > > > return -ENOMEM;
> > > > >
> > > > > env->prog = prog = new_prog;
> > > > > insn = new_prog->insnsi + i + delta;
> > > > > goto next_insn;
> > > > > }
> > > >
> > > > Should there be a "delta += cnt - 1;" before assigning env->prog in this
> > > > bpf_get_func_arg_cnt block? When cnt is 2 (non-RAW_TP path), the program
> > > > grows by one instruction, but delta is not updated. This could cause
> > > > subsequent bpf_patch_insn_data() calls to use incorrect offsets.
> > > >
> > > > The bpf_get_func_arg block at the beginning of this patch has:
> > > >
> > > > delta += cnt - 1;
> > > > env->prog = prog = new_prog;
> > > >
> > > > And the bpf_get_func_ret block similarly has delta updated. But this
> > > > bpf_get_func_arg_cnt block goes directly to env->prog assignment without
> > > > updating delta.
> > >
> > > Ah, good point, I think this is a valid problem. The selftests didn't cover
> > > this case, and I think I'd better to use bpf_get_func_arg() and bpf_get_func_ret()
> > > in the exit path of fsession to cover it.
> >
> > Oh, the problem doesn't have much impact. The only impact
> > is that the verifier will check the "r0 &= 0xFF" instruction redundantly.
> >
> > I'll see if there is more comment before I send next version.
> >
>
> Let's still fix the problem. Just go ahead and resubmit (with the fix
> and improved test).
OK!
>
> pw-bot: cr
>
>
> > Thanks!
> > Menglong Dong
> >
> > >
> > > Will fix it in the next version.
> > >
> > > Thanks!
> > > Menglong Dong
> > >
> > > >
> > > >
> > > > ---
> > > > AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> > > > See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
> > > >
> > > > CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
> > > >
> > >
> > >
> > >
> > >
> > >
> > >
> >
> >
> >
> >
>
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH bpf-next v11 03/12] bpf: change prototype of bpf_session_{cookie,is_return}
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 01/12] bpf: add " Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 02/12] bpf: use the least significant byte for the nr_args in trampoline Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 04/12] bpf: support fsession for bpf_session_is_return Menglong Dong
` (8 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Add the function argument of "void *ctx" to bpf_session_cookie() and
bpf_session_is_return(), which is a preparation of the next patch.
The two kfunc is seldom used now, so it will not introduce much effect
to change their function prototype.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
---
v10:
- drop the declaration of bpf_session_is_return() and bpf_session_cookie()
---
kernel/bpf/verifier.c | 6 +++++-
kernel/trace/bpf_trace.c | 4 ++--
tools/testing/selftests/bpf/bpf_kfuncs.h | 3 ---
.../bpf/progs/kprobe_multi_session_cookie.c | 15 +++++++--------
.../selftests/bpf/progs/uprobe_multi_session.c | 7 +++----
.../bpf/progs/uprobe_multi_session_cookie.c | 15 +++++++--------
.../bpf/progs/uprobe_multi_session_recursive.c | 11 +++++------
7 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index b3f912ad18ba..19fd16697262 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -12484,6 +12484,7 @@ enum special_kfunc_type {
KF_bpf_arena_alloc_pages,
KF_bpf_arena_free_pages,
KF_bpf_arena_reserve_pages,
+ KF_bpf_session_is_return,
};
BTF_ID_LIST(special_kfunc_list)
@@ -12561,6 +12562,7 @@ BTF_ID(func, bpf_task_work_schedule_resume)
BTF_ID(func, bpf_arena_alloc_pages)
BTF_ID(func, bpf_arena_free_pages)
BTF_ID(func, bpf_arena_reserve_pages)
+BTF_ID(func, bpf_session_is_return)
static bool is_task_work_add_kfunc(u32 func_id)
{
@@ -12615,7 +12617,9 @@ get_kfunc_ptr_arg_type(struct bpf_verifier_env *env,
struct bpf_reg_state *reg = ®s[regno];
bool arg_mem_size = false;
- if (meta->func_id == special_kfunc_list[KF_bpf_cast_to_kern_ctx])
+ if (meta->func_id == special_kfunc_list[KF_bpf_cast_to_kern_ctx] ||
+ meta->func_id == special_kfunc_list[KF_bpf_session_is_return] ||
+ meta->func_id == special_kfunc_list[KF_bpf_session_cookie])
return KF_ARG_PTR_TO_CTX;
if (argno + 1 < nargs &&
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index d466a1503da3..13f0a2de33b7 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -3323,7 +3323,7 @@ static u64 bpf_uprobe_multi_entry_ip(struct bpf_run_ctx *ctx)
__bpf_kfunc_start_defs();
-__bpf_kfunc bool bpf_session_is_return(void)
+__bpf_kfunc bool bpf_session_is_return(void *ctx)
{
struct bpf_session_run_ctx *session_ctx;
@@ -3331,7 +3331,7 @@ __bpf_kfunc bool bpf_session_is_return(void)
return session_ctx->is_return;
}
-__bpf_kfunc __u64 *bpf_session_cookie(void)
+__bpf_kfunc __u64 *bpf_session_cookie(void *ctx)
{
struct bpf_session_run_ctx *session_ctx;
diff --git a/tools/testing/selftests/bpf/bpf_kfuncs.h b/tools/testing/selftests/bpf/bpf_kfuncs.h
index e0189254bb6e..7dad01439391 100644
--- a/tools/testing/selftests/bpf/bpf_kfuncs.h
+++ b/tools/testing/selftests/bpf/bpf_kfuncs.h
@@ -79,9 +79,6 @@ extern int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_ptr,
struct bpf_dynptr *sig_ptr,
struct bpf_key *trusted_keyring) __ksym;
-extern bool bpf_session_is_return(void) __ksym __weak;
-extern __u64 *bpf_session_cookie(void) __ksym __weak;
-
struct dentry;
/* Description
* Returns xattr of a dentry
diff --git a/tools/testing/selftests/bpf/progs/kprobe_multi_session_cookie.c b/tools/testing/selftests/bpf/progs/kprobe_multi_session_cookie.c
index 0835b5edf685..ad627016e3e5 100644
--- a/tools/testing/selftests/bpf/progs/kprobe_multi_session_cookie.c
+++ b/tools/testing/selftests/bpf/progs/kprobe_multi_session_cookie.c
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/bpf.h>
+#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <stdbool.h>
-#include "bpf_kfuncs.h"
char _license[] SEC("license") = "GPL";
@@ -23,16 +22,16 @@ int BPF_PROG(trigger)
return 0;
}
-static int check_cookie(__u64 val, __u64 *result)
+static int check_cookie(struct pt_regs *ctx, __u64 val, __u64 *result)
{
__u64 *cookie;
if (bpf_get_current_pid_tgid() >> 32 != pid)
return 1;
- cookie = bpf_session_cookie();
+ cookie = bpf_session_cookie(ctx);
- if (bpf_session_is_return())
+ if (bpf_session_is_return(ctx))
*result = *cookie == val ? val : 0;
else
*cookie = val;
@@ -42,17 +41,17 @@ static int check_cookie(__u64 val, __u64 *result)
SEC("kprobe.session/bpf_fentry_test1")
int test_kprobe_1(struct pt_regs *ctx)
{
- return check_cookie(1, &test_kprobe_1_result);
+ return check_cookie(ctx, 1, &test_kprobe_1_result);
}
SEC("kprobe.session/bpf_fentry_test1")
int test_kprobe_2(struct pt_regs *ctx)
{
- return check_cookie(2, &test_kprobe_2_result);
+ return check_cookie(ctx, 2, &test_kprobe_2_result);
}
SEC("kprobe.session/bpf_fentry_test1")
int test_kprobe_3(struct pt_regs *ctx)
{
- return check_cookie(3, &test_kprobe_3_result);
+ return check_cookie(ctx, 3, &test_kprobe_3_result);
}
diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi_session.c b/tools/testing/selftests/bpf/progs/uprobe_multi_session.c
index 30bff90b68dc..6e46bb00ff58 100644
--- a/tools/testing/selftests/bpf/progs/uprobe_multi_session.c
+++ b/tools/testing/selftests/bpf/progs/uprobe_multi_session.c
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/bpf.h>
+#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <stdbool.h>
-#include "bpf_kfuncs.h"
#include "bpf_misc.h"
char _license[] SEC("license") = "GPL";
@@ -51,7 +50,7 @@ static int uprobe_multi_check(void *ctx, bool is_return)
SEC("uprobe.session//proc/self/exe:uprobe_multi_func_*")
int uprobe(struct pt_regs *ctx)
{
- return uprobe_multi_check(ctx, bpf_session_is_return());
+ return uprobe_multi_check(ctx, bpf_session_is_return(ctx));
}
static __always_inline bool verify_sleepable_user_copy(void)
@@ -67,5 +66,5 @@ int uprobe_sleepable(struct pt_regs *ctx)
{
if (verify_sleepable_user_copy())
uprobe_multi_sleep_result++;
- return uprobe_multi_check(ctx, bpf_session_is_return());
+ return uprobe_multi_check(ctx, bpf_session_is_return(ctx));
}
diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi_session_cookie.c b/tools/testing/selftests/bpf/progs/uprobe_multi_session_cookie.c
index 5befdf944dc6..b5db196614a9 100644
--- a/tools/testing/selftests/bpf/progs/uprobe_multi_session_cookie.c
+++ b/tools/testing/selftests/bpf/progs/uprobe_multi_session_cookie.c
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/bpf.h>
+#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <stdbool.h>
-#include "bpf_kfuncs.h"
char _license[] SEC("license") = "GPL";
@@ -13,16 +12,16 @@ __u64 test_uprobe_1_result = 0;
__u64 test_uprobe_2_result = 0;
__u64 test_uprobe_3_result = 0;
-static int check_cookie(__u64 val, __u64 *result)
+static int check_cookie(struct pt_regs *ctx, __u64 val, __u64 *result)
{
__u64 *cookie;
if (bpf_get_current_pid_tgid() >> 32 != pid)
return 1;
- cookie = bpf_session_cookie();
+ cookie = bpf_session_cookie(ctx);
- if (bpf_session_is_return())
+ if (bpf_session_is_return(ctx))
*result = *cookie == val ? val : 0;
else
*cookie = val;
@@ -32,17 +31,17 @@ static int check_cookie(__u64 val, __u64 *result)
SEC("uprobe.session//proc/self/exe:uprobe_multi_func_1")
int uprobe_1(struct pt_regs *ctx)
{
- return check_cookie(1, &test_uprobe_1_result);
+ return check_cookie(ctx, 1, &test_uprobe_1_result);
}
SEC("uprobe.session//proc/self/exe:uprobe_multi_func_2")
int uprobe_2(struct pt_regs *ctx)
{
- return check_cookie(2, &test_uprobe_2_result);
+ return check_cookie(ctx, 2, &test_uprobe_2_result);
}
SEC("uprobe.session//proc/self/exe:uprobe_multi_func_3")
int uprobe_3(struct pt_regs *ctx)
{
- return check_cookie(3, &test_uprobe_3_result);
+ return check_cookie(ctx, 3, &test_uprobe_3_result);
}
diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi_session_recursive.c b/tools/testing/selftests/bpf/progs/uprobe_multi_session_recursive.c
index 8fbcd69fae22..3ce309248a04 100644
--- a/tools/testing/selftests/bpf/progs/uprobe_multi_session_recursive.c
+++ b/tools/testing/selftests/bpf/progs/uprobe_multi_session_recursive.c
@@ -1,9 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
-#include <linux/bpf.h>
+#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <stdbool.h>
-#include "bpf_kfuncs.h"
#include "bpf_misc.h"
char _license[] SEC("license") = "GPL";
@@ -16,11 +15,11 @@ int idx_return = 0;
__u64 test_uprobe_cookie_entry[6];
__u64 test_uprobe_cookie_return[3];
-static int check_cookie(void)
+static int check_cookie(struct pt_regs *ctx)
{
- __u64 *cookie = bpf_session_cookie();
+ __u64 *cookie = bpf_session_cookie(ctx);
- if (bpf_session_is_return()) {
+ if (bpf_session_is_return(ctx)) {
if (idx_return >= ARRAY_SIZE(test_uprobe_cookie_return))
return 1;
test_uprobe_cookie_return[idx_return++] = *cookie;
@@ -40,5 +39,5 @@ int uprobe_recursive(struct pt_regs *ctx)
if (bpf_get_current_pid_tgid() >> 32 != pid)
return 1;
- return check_cookie();
+ return check_cookie(ctx);
}
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 04/12] bpf: support fsession for bpf_session_is_return
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (2 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 03/12] bpf: change prototype of bpf_session_{cookie,is_return} Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 8:07 ` bot+bpf-ci
2026-01-23 7:35 ` [PATCH bpf-next v11 05/12] bpf: support fsession for bpf_session_cookie Menglong Dong
` (7 subsequent siblings)
11 siblings, 1 reply; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
If fsession exists, we will use the bit (1 << BPF_TRAMP_IS_RETURN_SHIFT)
in ((u64 *)ctx)[-1] to store the "is_return" flag.
The logic of bpf_session_is_return() for fsession is implemented in the
verifier by inline following code:
bool bpf_session_is_return(void *ctx)
{
return (((u64 *)ctx)[-1] >> BPF_TRAMP_IS_RETURN_SHIFT) & 1;
}
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
Co-developed-by: Leon Hwang <leon.hwang@linux.dev>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
v11:
- rename BPF_TRAMP_SHIFT_IS_RETURN to BPF_TRAMP_IS_RETURN_SHIFT
v10:
- fix the wrong description of bpf_session_is_return() in commit log and
comment
- rename the prefix from BPF_TRAMP_M_ tp BPF_TRAMP_SHIFT_
- remove the definition of BPF_TRAMP_M_NR_ARGS
- use 63 for the shift of BPF_TRAMP_SHIFT_IS_RETURN
- check the program type in bpf_session_filter()
v9:
- remove the definition of bpf_fsession_is_return()
v7:
- reuse the kfunc bpf_session_is_return() instead of introduce new kfunc
v4:
- split out the bpf_fsession_cookie() to another patch
v3:
- merge the bpf_tracing_is_exit and bpf_fsession_cookie into a single
patch
v2:
- store the session flags after return value, instead of before nr_args
- inline the bpf_tracing_is_exit, as Jiri suggested
---
include/linux/bpf.h | 2 ++
kernel/bpf/verifier.c | 13 +++++++++++++
kernel/trace/bpf_trace.c | 39 ++++++++++++++++++++++++++-------------
3 files changed, 41 insertions(+), 13 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 41228b0add52..29eecd79352e 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1229,6 +1229,8 @@ enum {
#endif
};
+#define BPF_TRAMP_IS_RETURN_SHIFT 63
+
struct bpf_tramp_links {
struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
int nr_links;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 19fd16697262..2ae8f29b854f 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -23011,6 +23011,19 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
*cnt = 1;
+ } else if (desc->func_id == special_kfunc_list[KF_bpf_session_is_return] &&
+ env->prog->expected_attach_type == BPF_TRACE_FSESSION) {
+ /*
+ * inline the bpf_session_is_return() for fsession:
+ * bool bpf_session_is_return(void *ctx)
+ * {
+ * return (((u64 *)ctx)[-1] >> BPF_TRAMP_IS_RETURN_SHIFT) & 1;
+ * }
+ */
+ insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
+ insn_buf[1] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, BPF_TRAMP_IS_RETURN_SHIFT);
+ insn_buf[2] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1);
+ *cnt = 3;
}
if (env->insn_aux_data[insn_idx].arg_prog) {
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 13f0a2de33b7..f7baeb8278ca 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1286,7 +1286,8 @@ static bool is_kprobe_multi(const struct bpf_prog *prog)
static inline bool is_kprobe_session(const struct bpf_prog *prog)
{
- return prog->expected_attach_type == BPF_TRACE_KPROBE_SESSION;
+ return prog->type == BPF_PROG_TYPE_KPROBE &&
+ prog->expected_attach_type == BPF_TRACE_KPROBE_SESSION;
}
static inline bool is_uprobe_multi(const struct bpf_prog *prog)
@@ -1297,7 +1298,14 @@ static inline bool is_uprobe_multi(const struct bpf_prog *prog)
static inline bool is_uprobe_session(const struct bpf_prog *prog)
{
- return prog->expected_attach_type == BPF_TRACE_UPROBE_SESSION;
+ return prog->type == BPF_PROG_TYPE_KPROBE &&
+ prog->expected_attach_type == BPF_TRACE_UPROBE_SESSION;
+}
+
+static inline bool is_trace_fsession(const struct bpf_prog *prog)
+{
+ return prog->type == BPF_PROG_TYPE_TRACING &&
+ prog->expected_attach_type == BPF_TRACE_FSESSION;
}
static const struct bpf_func_proto *
@@ -3341,34 +3349,39 @@ __bpf_kfunc __u64 *bpf_session_cookie(void *ctx)
__bpf_kfunc_end_defs();
-BTF_KFUNCS_START(kprobe_multi_kfunc_set_ids)
+BTF_KFUNCS_START(session_kfunc_set_ids)
BTF_ID_FLAGS(func, bpf_session_is_return)
BTF_ID_FLAGS(func, bpf_session_cookie)
-BTF_KFUNCS_END(kprobe_multi_kfunc_set_ids)
+BTF_KFUNCS_END(session_kfunc_set_ids)
-static int bpf_kprobe_multi_filter(const struct bpf_prog *prog, u32 kfunc_id)
+static int bpf_session_filter(const struct bpf_prog *prog, u32 kfunc_id)
{
- if (!btf_id_set8_contains(&kprobe_multi_kfunc_set_ids, kfunc_id))
+ if (!btf_id_set8_contains(&session_kfunc_set_ids, kfunc_id))
return 0;
- if (!is_kprobe_session(prog) && !is_uprobe_session(prog))
+ if (!is_kprobe_session(prog) && !is_uprobe_session(prog) && !is_trace_fsession(prog))
return -EACCES;
return 0;
}
-static const struct btf_kfunc_id_set bpf_kprobe_multi_kfunc_set = {
+static const struct btf_kfunc_id_set bpf_session_kfunc_set = {
.owner = THIS_MODULE,
- .set = &kprobe_multi_kfunc_set_ids,
- .filter = bpf_kprobe_multi_filter,
+ .set = &session_kfunc_set_ids,
+ .filter = bpf_session_filter,
};
-static int __init bpf_kprobe_multi_kfuncs_init(void)
+static int __init bpf_trace_kfuncs_init(void)
{
- return register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, &bpf_kprobe_multi_kfunc_set);
+ int err = 0;
+
+ err = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, &bpf_session_kfunc_set);
+ err = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &bpf_session_kfunc_set);
+
+ return err;
}
-late_initcall(bpf_kprobe_multi_kfuncs_init);
+late_initcall(bpf_trace_kfuncs_init);
typedef int (*copy_fn_t)(void *dst, const void *src, u32 size, struct task_struct *tsk);
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 04/12] bpf: support fsession for bpf_session_is_return
2026-01-23 7:35 ` [PATCH bpf-next v11 04/12] bpf: support fsession for bpf_session_is_return Menglong Dong
@ 2026-01-23 8:07 ` bot+bpf-ci
2026-01-23 8:15 ` Menglong Dong
0 siblings, 1 reply; 22+ messages in thread
From: bot+bpf-ci @ 2026-01-23 8:07 UTC (permalink / raw)
To: menglong8.dong, andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2463 bytes --]
> diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> index 41228b0add52..29eecd79352e 100644
> --- a/include/linux/bpf.h
> +++ b/include/linux/bpf.h
> @@ -1229,6 +1229,8 @@ enum {
> #endif
> };
>
> +#define BPF_TRAMP_IS_RETURN_SHIFT 63
> +
> struct bpf_tramp_links {
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 19fd16697262..2ae8f29b854f 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -23011,6 +23011,19 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
> desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
> insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
> *cnt = 1;
> + } else if (desc->func_id == special_kfunc_list[KF_bpf_session_is_return] &&
> + env->prog->expected_attach_type == BPF_TRACE_FSESSION) {
> + /*
> + * inline the bpf_session_is_return() for fsession:
> + * bool bpf_session_is_return(void *ctx)
> + * {
> + * return (((u64 *)ctx)[-1] >> BPF_TRAMP_IS_RETURN_SHIFT) & 1;
> + * }
> + */
> + insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> + insn_buf[1] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, BPF_TRAMP_IS_RETURN_SHIFT);
> + insn_buf[2] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1);
> + *cnt = 3;
> + }
The inline implementation reads bit 63 of ctx[-1] to check the is_return
flag. However, looking at the x86 trampoline code in
arch/x86/net/bpf_jit_comp.c, the trampoline only stores nr_regs in ctx[-1]:
emit_mov_imm64(&prog, BPF_REG_0, 0, (u32) nr_regs);
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -nregs_off);
The is_return flag (bit 63) is never set by the current trampoline code.
This means bpf_session_is_return() will always return 0 for fsession
programs, even when executing at the return point.
I see this is fixed later in the series by commit ba766b26e776 ("bpf,x86:
add fsession support for x86_64") which adds:
func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
if (bpf_fsession_cnt(tlinks))
emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
Should this commit be squashed with the x86 trampoline changes to ensure
the feature works correctly at each point in the series?
[ ... ]
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 04/12] bpf: support fsession for bpf_session_is_return
2026-01-23 8:07 ` bot+bpf-ci
@ 2026-01-23 8:15 ` Menglong Dong
0 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 8:15 UTC (permalink / raw)
To: menglong8.dong, andrii, bot+bpf-ci
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
On 2026/1/23 16:07 bot+bpf-ci@kernel.org write:
> > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > index 41228b0add52..29eecd79352e 100644
> > --- a/include/linux/bpf.h
> > +++ b/include/linux/bpf.h
> > @@ -1229,6 +1229,8 @@ enum {
> > #endif
> > };
> >
> > +#define BPF_TRAMP_IS_RETURN_SHIFT 63
> > +
> > struct bpf_tramp_links {
>
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 19fd16697262..2ae8f29b854f 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -23011,6 +23011,19 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
> > desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
> > insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
> > *cnt = 1;
> > + } else if (desc->func_id == special_kfunc_list[KF_bpf_session_is_return] &&
> > + env->prog->expected_attach_type == BPF_TRACE_FSESSION) {
> > + /*
> > + * inline the bpf_session_is_return() for fsession:
> > + * bool bpf_session_is_return(void *ctx)
> > + * {
> > + * return (((u64 *)ctx)[-1] >> BPF_TRAMP_IS_RETURN_SHIFT) & 1;
> > + * }
> > + */
> > + insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
> > + insn_buf[1] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, BPF_TRAMP_IS_RETURN_SHIFT);
> > + insn_buf[2] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1);
> > + *cnt = 3;
> > + }
>
> The inline implementation reads bit 63 of ctx[-1] to check the is_return
> flag. However, looking at the x86 trampoline code in
> arch/x86/net/bpf_jit_comp.c, the trampoline only stores nr_regs in ctx[-1]:
>
> emit_mov_imm64(&prog, BPF_REG_0, 0, (u32) nr_regs);
> emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -nregs_off);
>
> The is_return flag (bit 63) is never set by the current trampoline code.
> This means bpf_session_is_return() will always return 0 for fsession
> programs, even when executing at the return point.
>
> I see this is fixed later in the series by commit ba766b26e776 ("bpf,x86:
> add fsession support for x86_64") which adds:
>
> func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
> if (bpf_fsession_cnt(tlinks))
> emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
>
> Should this commit be squashed with the x86 trampoline changes to ensure
> the feature works correctly at each point in the series?
As I said before, this patch implement the common part of the fsession.
and we implement the architecture specific code for x86_64 in the later
patch.
>
> [ ... ]
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH bpf-next v11 05/12] bpf: support fsession for bpf_session_cookie
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (3 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 04/12] bpf: support fsession for bpf_session_is_return Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 06/12] bpf,x86: introduce emit_store_stack_imm64() for trampoline Menglong Dong
` (6 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Implement session cookie for fsession. The session cookies will be stored
in the stack, and the layout of the stack will look like this:
return value -> 8 bytes
argN -> 8 bytes
...
arg1 -> 8 bytes
nr_args -> 8 bytes
ip (optional) -> 8 bytes
cookie2 -> 8 bytes
cookie1 -> 8 bytes
The offset of the cookie for the current bpf program, which is in 8-byte
units, is stored in the
"(((u64 *)ctx)[-1] >> BPF_TRAMP_COOKIE_INDEX_SHIFT) & 0xFF". Therefore, we
can get the session cookie with ((u64 *)ctx)[-offset].
Implement and inline the bpf_session_cookie() for the fsession in the
verifier.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
v11:
- rename BPF_TRAMP_SHIFT_COOKIE to BPF_TRAMP_COOKIE_INDEX_SHIFT
v10:
- describe the offset of the session cookie more explicit
- make 8 as the bit shift of session cookie
- remove the session cookie count limitation
v9:
- remove the definition of bpf_fsession_cookie()
v7:
- reuse bpf_session_cookie() instead of introduce new kfunc
v5:
- remove "cookie_cnt" in struct bpf_trampoline
v4:
- limit the maximum of the cookie count to 4
- store the session cookies before nr_regs in stack
---
include/linux/bpf.h | 15 +++++++++++++++
kernel/bpf/verifier.c | 20 ++++++++++++++++++++
2 files changed, 35 insertions(+)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index 29eecd79352e..4427c6e98331 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1229,6 +1229,7 @@ enum {
#endif
};
+#define BPF_TRAMP_COOKIE_INDEX_SHIFT 8
#define BPF_TRAMP_IS_RETURN_SHIFT 63
struct bpf_tramp_links {
@@ -1782,6 +1783,7 @@ struct bpf_prog {
enforce_expected_attach_type:1, /* Enforce expected_attach_type checking at attach time */
call_get_stack:1, /* Do we call bpf_get_stack() or bpf_get_stackid() */
call_get_func_ip:1, /* Do we call get_func_ip() */
+ call_session_cookie:1, /* Do we call bpf_session_cookie() */
tstamp_type_access:1, /* Accessed __sk_buff->tstamp_type */
sleepable:1; /* BPF program is sleepable */
enum bpf_prog_type type; /* Type of BPF program */
@@ -2190,6 +2192,19 @@ static inline int bpf_fsession_cnt(struct bpf_tramp_links *links)
return cnt;
}
+static inline int bpf_fsession_cookie_cnt(struct bpf_tramp_links *links)
+{
+ struct bpf_tramp_links fentries = links[BPF_TRAMP_FENTRY];
+ int cnt = 0;
+
+ for (int i = 0; i < links[BPF_TRAMP_FENTRY].nr_links; i++) {
+ if (fentries.links[i]->link.prog->call_session_cookie)
+ cnt++;
+ }
+
+ return cnt;
+}
+
int bpf_prog_ctx_arg_info_init(struct bpf_prog *prog,
const struct bpf_ctx_arg_aux *info, u32 cnt);
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 2ae8f29b854f..1f171ac3462e 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -14406,6 +14406,9 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
return err;
}
+ if (meta.func_id == special_kfunc_list[KF_bpf_session_cookie])
+ env->prog->call_session_cookie = true;
+
return 0;
}
@@ -23024,6 +23027,23 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
insn_buf[1] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, BPF_TRAMP_IS_RETURN_SHIFT);
insn_buf[2] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 1);
*cnt = 3;
+ } else if (desc->func_id == special_kfunc_list[KF_bpf_session_cookie] &&
+ env->prog->expected_attach_type == BPF_TRACE_FSESSION) {
+ /*
+ * inline bpf_session_cookie() for fsession:
+ * __u64 *bpf_session_cookie(void *ctx)
+ * {
+ * u64 off = (((u64 *)ctx)[-1] >> BPF_TRAMP_COOKIE_INDEX_SHIFT) & 0xFF;
+ * return &((u64 *)ctx)[-off];
+ * }
+ */
+ insn_buf[0] = BPF_LDX_MEM(BPF_DW, BPF_REG_0, BPF_REG_1, -8);
+ insn_buf[1] = BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, BPF_TRAMP_COOKIE_INDEX_SHIFT);
+ insn_buf[2] = BPF_ALU64_IMM(BPF_AND, BPF_REG_0, 0xFF);
+ insn_buf[3] = BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3);
+ insn_buf[4] = BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1);
+ insn_buf[5] = BPF_ALU64_IMM(BPF_NEG, BPF_REG_0, 0);
+ *cnt = 6;
}
if (env->insn_aux_data[insn_idx].arg_prog) {
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 06/12] bpf,x86: introduce emit_store_stack_imm64() for trampoline
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (4 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 05/12] bpf: support fsession for bpf_session_cookie Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 07/12] bpf,x86: add fsession support for x86_64 Menglong Dong
` (5 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Introduce the helper emit_store_stack_imm64(), which is used to store a
imm64 to the stack with the help of a register.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
v10:
- add the "reg" to the function arguments of emit_store_stack_imm64()
- use the positive offset in emit_store_stack_imm64()
- remove some unnecessary comment, as we already have proper comment in
emit_store_stack_imm64()
v9:
- rename emit_st_r0_imm64() to emit_store_stack_imm64()
---
arch/x86/net/bpf_jit_comp.c | 26 ++++++++++++++------------
1 file changed, 14 insertions(+), 12 deletions(-)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index e3b1c4b1d550..2f31331955b5 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -1300,6 +1300,16 @@ static void emit_st_r12(u8 **pprog, u32 size, u32 dst_reg, int off, int imm)
emit_st_index(pprog, size, dst_reg, X86_REG_R12, off, imm);
}
+static void emit_store_stack_imm64(u8 **pprog, int reg, int stack_off, u64 imm64)
+{
+ /*
+ * mov reg, imm64
+ * mov QWORD PTR [rbp + stack_off], reg
+ */
+ emit_mov_imm64(pprog, reg, imm64 >> 32, (u32) imm64);
+ emit_stx(pprog, BPF_DW, BPF_REG_FP, reg, stack_off);
+}
+
static int emit_atomic_rmw(u8 **pprog, u32 atomic_op,
u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
{
@@ -3348,20 +3358,12 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
/* mov QWORD PTR [rbp - rbx_off], rbx */
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_6, -rbx_off);
- /* Store number of argument registers of the traced function:
- * mov rax, nr_regs
- * mov QWORD PTR [rbp - nregs_off], rax
- */
- emit_mov_imm64(&prog, BPF_REG_0, 0, (u32) nr_regs);
- emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -nregs_off);
+ /* Store number of argument registers of the traced function */
+ emit_store_stack_imm64(&prog, BPF_REG_0, -nregs_off, nr_regs);
if (flags & BPF_TRAMP_F_IP_ARG) {
- /* Store IP address of the traced function:
- * movabsq rax, func_addr
- * mov QWORD PTR [rbp - ip_off], rax
- */
- emit_mov_imm64(&prog, BPF_REG_0, (long) func_addr >> 32, (u32) (long) func_addr);
- emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -ip_off);
+ /* Store IP address of the traced function */
+ emit_store_stack_imm64(&prog, BPF_REG_0, -ip_off, (long)func_addr);
}
save_args(m, &prog, regs_off, false, flags);
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 07/12] bpf,x86: add fsession support for x86_64
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (5 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 06/12] bpf,x86: introduce emit_store_stack_imm64() for trampoline Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 08/12] libbpf: add fsession support Menglong Dong
` (4 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Add BPF_TRACE_FSESSION supporting to x86_64, including:
1. clear the return value in the stack before fentry to make the fentry
of the fsession can only get 0 with bpf_get_func_ret().
2. clear all the session cookies' value in the stack.
2. store the index of the cookie to ctx[-1] before the calling to fsession
3. store the "is_return" flag to ctx[-1] before the calling to fexit of
the fsession.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
Co-developed-by: Leon Hwang <leon.hwang@linux.dev>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
v10:
- use "|" for func_meta instead of "+"
- pass the "func_meta_off" to invoke_bpf() explicitly, instead of
computing it with "stack_size + 8"
- pass the "cookie_off" to invoke_bpf() instead of computing the current
cookie index with "func_meta"
v5:
- add the variable "func_meta"
- define cookie_off in a new line
v4:
- some adjustment to the 1st patch, such as we get the fsession prog from
fentry and fexit hlist
- remove the supporting of skipping fexit with fentry return non-zero
v2:
- add session cookie support
- add the session stuff after return value, instead of before nr_args
---
arch/x86/net/bpf_jit_comp.c | 52 ++++++++++++++++++++++++++++---------
1 file changed, 40 insertions(+), 12 deletions(-)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 2f31331955b5..5a075e06cf45 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3094,13 +3094,19 @@ static int emit_cond_near_jump(u8 **pprog, void *func, void *ip, u8 jmp_cond)
static int invoke_bpf(const struct btf_func_model *m, u8 **pprog,
struct bpf_tramp_links *tl, int stack_size,
- int run_ctx_off, bool save_ret,
- void *image, void *rw_image)
+ int run_ctx_off, int func_meta_off, bool save_ret,
+ void *image, void *rw_image, u64 func_meta,
+ int cookie_off)
{
- int i;
+ int i, cur_cookie = (cookie_off - stack_size) / 8;
u8 *prog = *pprog;
for (i = 0; i < tl->nr_links; i++) {
+ if (tl->links[i]->link.prog->call_session_cookie) {
+ emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off,
+ func_meta | (cur_cookie << BPF_TRAMP_COOKIE_INDEX_SHIFT));
+ cur_cookie--;
+ }
if (invoke_bpf_prog(m, &prog, tl->links[i], stack_size,
run_ctx_off, save_ret, image, rw_image))
return -EINVAL;
@@ -3218,12 +3224,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
void *func_addr)
{
int i, ret, nr_regs = m->nr_args, stack_size = 0;
- int regs_off, nregs_off, ip_off, run_ctx_off, arg_stack_off, rbx_off;
+ int regs_off, func_meta_off, ip_off, run_ctx_off, arg_stack_off, rbx_off;
struct bpf_tramp_links *fentry = &tlinks[BPF_TRAMP_FENTRY];
struct bpf_tramp_links *fexit = &tlinks[BPF_TRAMP_FEXIT];
struct bpf_tramp_links *fmod_ret = &tlinks[BPF_TRAMP_MODIFY_RETURN];
void *orig_call = func_addr;
+ int cookie_off, cookie_cnt;
u8 **branches = NULL;
+ u64 func_meta;
u8 *prog;
bool save_ret;
@@ -3259,7 +3267,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
* [ ... ]
* RBP - regs_off [ reg_arg1 ] program's ctx pointer
*
- * RBP - nregs_off [ regs count ] always
+ * RBP - func_meta_off [ regs count, etc ] always
*
* RBP - ip_off [ traced function ] BPF_TRAMP_F_IP_ARG flag
*
@@ -3282,15 +3290,20 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
stack_size += nr_regs * 8;
regs_off = stack_size;
- /* regs count */
+ /* function matedata, such as regs count */
stack_size += 8;
- nregs_off = stack_size;
+ func_meta_off = stack_size;
if (flags & BPF_TRAMP_F_IP_ARG)
stack_size += 8; /* room for IP address argument */
ip_off = stack_size;
+ cookie_cnt = bpf_fsession_cookie_cnt(tlinks);
+ /* room for session cookies */
+ stack_size += cookie_cnt * 8;
+ cookie_off = stack_size;
+
stack_size += 8;
rbx_off = stack_size;
@@ -3358,8 +3371,9 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
/* mov QWORD PTR [rbp - rbx_off], rbx */
emit_stx(&prog, BPF_DW, BPF_REG_FP, BPF_REG_6, -rbx_off);
+ func_meta = nr_regs;
/* Store number of argument registers of the traced function */
- emit_store_stack_imm64(&prog, BPF_REG_0, -nregs_off, nr_regs);
+ emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
if (flags & BPF_TRAMP_F_IP_ARG) {
/* Store IP address of the traced function */
@@ -3378,9 +3392,18 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
}
}
+ if (bpf_fsession_cnt(tlinks)) {
+ /* clear all the session cookies' value */
+ for (int i = 0; i < cookie_cnt; i++)
+ emit_store_stack_imm64(&prog, BPF_REG_0, -cookie_off + 8 * i, 0);
+ /* clear the return value to make sure fentry always get 0 */
+ emit_store_stack_imm64(&prog, BPF_REG_0, -8, 0);
+ }
+
if (fentry->nr_links) {
- if (invoke_bpf(m, &prog, fentry, regs_off, run_ctx_off,
- flags & BPF_TRAMP_F_RET_FENTRY_RET, image, rw_image))
+ if (invoke_bpf(m, &prog, fentry, regs_off, run_ctx_off, func_meta_off,
+ flags & BPF_TRAMP_F_RET_FENTRY_RET, image, rw_image,
+ func_meta, cookie_off))
return -EINVAL;
}
@@ -3440,9 +3463,14 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
}
}
+ /* set the "is_return" flag for fsession */
+ func_meta |= (1ULL << BPF_TRAMP_IS_RETURN_SHIFT);
+ if (bpf_fsession_cnt(tlinks))
+ emit_store_stack_imm64(&prog, BPF_REG_0, -func_meta_off, func_meta);
+
if (fexit->nr_links) {
- if (invoke_bpf(m, &prog, fexit, regs_off, run_ctx_off,
- false, image, rw_image)) {
+ if (invoke_bpf(m, &prog, fexit, regs_off, run_ctx_off, func_meta_off,
+ false, image, rw_image, func_meta, cookie_off)) {
ret = -EINVAL;
goto cleanup;
}
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 08/12] libbpf: add fsession support
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (6 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 07/12] bpf,x86: add fsession support for x86_64 Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 09/12] bpftool: " Menglong Dong
` (3 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Add BPF_TRACE_FSESSION to libbpf.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
v10:
- split the modification to bpftool to a separate patch
v5:
- remove the handling of BPF_TRACE_SESSION in legacy fallback path for
BPF_RAW_TRACEPOINT_OPEN
- use fsession terminology consistently
---
tools/lib/bpf/bpf.c | 1 +
tools/lib/bpf/libbpf.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 21b57a629916..5846de364209 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -794,6 +794,7 @@ int bpf_link_create(int prog_fd, int target_fd,
case BPF_TRACE_FENTRY:
case BPF_TRACE_FEXIT:
case BPF_MODIFY_RETURN:
+ case BPF_TRACE_FSESSION:
case BPF_LSM_MAC:
attr.link_create.tracing.cookie = OPTS_GET(opts, tracing.cookie, 0);
if (!OPTS_ZEROED(opts, tracing))
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index bbcfd72b07d5..0c8bf0b5cce4 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -115,6 +115,7 @@ static const char * const attach_type_name[] = {
[BPF_TRACE_FENTRY] = "trace_fentry",
[BPF_TRACE_FEXIT] = "trace_fexit",
[BPF_MODIFY_RETURN] = "modify_return",
+ [BPF_TRACE_FSESSION] = "trace_fsession",
[BPF_LSM_MAC] = "lsm_mac",
[BPF_LSM_CGROUP] = "lsm_cgroup",
[BPF_SK_LOOKUP] = "sk_lookup",
@@ -9859,6 +9860,8 @@ static const struct bpf_sec_def section_defs[] = {
SEC_DEF("fentry.s+", TRACING, BPF_TRACE_FENTRY, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_trace),
SEC_DEF("fmod_ret.s+", TRACING, BPF_MODIFY_RETURN, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_trace),
SEC_DEF("fexit.s+", TRACING, BPF_TRACE_FEXIT, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_trace),
+ SEC_DEF("fsession+", TRACING, BPF_TRACE_FSESSION, SEC_ATTACH_BTF, attach_trace),
+ SEC_DEF("fsession.s+", TRACING, BPF_TRACE_FSESSION, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_trace),
SEC_DEF("freplace+", EXT, 0, SEC_ATTACH_BTF, attach_trace),
SEC_DEF("lsm+", LSM, BPF_LSM_MAC, SEC_ATTACH_BTF, attach_lsm),
SEC_DEF("lsm.s+", LSM, BPF_LSM_MAC, SEC_ATTACH_BTF | SEC_SLEEPABLE, attach_lsm),
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 09/12] bpftool: add fsession support
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (7 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 08/12] libbpf: add fsession support Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 10/12] selftests/bpf: add testcases for fsession Menglong Dong
` (2 subsequent siblings)
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Add BPF_TRACE_FSESSION to bpftool.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
tools/bpf/bpftool/common.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index e8daf963ecef..8bfcff9e2f63 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -1191,6 +1191,7 @@ const char *bpf_attach_type_input_str(enum bpf_attach_type t)
case BPF_TRACE_FENTRY: return "fentry";
case BPF_TRACE_FEXIT: return "fexit";
case BPF_MODIFY_RETURN: return "mod_ret";
+ case BPF_TRACE_FSESSION: return "fsession";
case BPF_SK_REUSEPORT_SELECT: return "sk_skb_reuseport_select";
case BPF_SK_REUSEPORT_SELECT_OR_MIGRATE: return "sk_skb_reuseport_select_or_migrate";
default: return libbpf_bpf_attach_type_str(t);
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 10/12] selftests/bpf: add testcases for fsession
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (8 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 09/12] bpftool: " Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:57 ` bot+bpf-ci
2026-01-23 7:35 ` [PATCH bpf-next v11 11/12] selftests/bpf: add testcases for fsession cookie Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 12/12] selftests/bpf: test fsession mixed with fentry and fexit Menglong Dong
11 siblings, 1 reply; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Add testcases for BPF_TRACE_FSESSION. The function arguments and return
value are tested both in the entry and exit. And the kfunc
bpf_session_is_ret() is also tested.
As the layout of the stack changed for fsession, so we also test
bpf_get_func_ip() for it.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
v3:
- restructure the testcase by combine the testcases for session cookie and
get_func_ip into one patch
---
.../selftests/bpf/prog_tests/fsession_test.c | 90 ++++++++++++++
.../selftests/bpf/progs/fsession_test.c | 110 ++++++++++++++++++
2 files changed, 200 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/fsession_test.c
create mode 100644 tools/testing/selftests/bpf/progs/fsession_test.c
diff --git a/tools/testing/selftests/bpf/prog_tests/fsession_test.c b/tools/testing/selftests/bpf/prog_tests/fsession_test.c
new file mode 100644
index 000000000000..75bb42942b67
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/fsession_test.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 ChinaTelecom */
+#include <test_progs.h>
+#include "fsession_test.skel.h"
+
+static int check_result(struct fsession_test *skel)
+{
+ LIBBPF_OPTS(bpf_test_run_opts, topts);
+ int err, prog_fd;
+
+ /* Trigger test function calls */
+ prog_fd = bpf_program__fd(skel->progs.test1);
+ err = bpf_prog_test_run_opts(prog_fd, &topts);
+ if (!ASSERT_OK(err, "test_run_opts err"))
+ return err;
+ if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
+ return topts.retval;
+
+ for (int i = 0; i < sizeof(*skel->bss) / sizeof(__u64); i++) {
+ if (!ASSERT_EQ(((__u64 *)skel->bss)[i], 1, "test_result"))
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void test_fsession_basic(void)
+{
+ struct fsession_test *skel = NULL;
+ int err;
+
+ skel = fsession_test__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "fsession_test__open_and_load"))
+ goto cleanup;
+
+ err = fsession_test__attach(skel);
+ if (!ASSERT_OK(err, "fsession_attach"))
+ goto cleanup;
+
+ check_result(skel);
+cleanup:
+ fsession_test__destroy(skel);
+}
+
+static void test_fsession_reattach(void)
+{
+ struct fsession_test *skel = NULL;
+ int err;
+
+ skel = fsession_test__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "fsession_test__open_and_load"))
+ goto cleanup;
+
+ /* first attach */
+ err = fsession_test__attach(skel);
+ if (!ASSERT_OK(err, "fsession_first_attach"))
+ goto cleanup;
+
+ if (check_result(skel))
+ goto cleanup;
+
+ /* detach */
+ fsession_test__detach(skel);
+
+ /* reset counters */
+ memset(skel->bss, 0, sizeof(*skel->bss));
+
+ /* second attach */
+ err = fsession_test__attach(skel);
+ if (!ASSERT_OK(err, "fsession_second_attach"))
+ goto cleanup;
+
+ if (check_result(skel))
+ goto cleanup;
+
+cleanup:
+ fsession_test__destroy(skel);
+}
+
+void test_fsession_test(void)
+{
+#if !defined(__x86_64__)
+ test__skip();
+ return;
+#endif
+ if (test__start_subtest("fsession_test"))
+ test_fsession_basic();
+ if (test__start_subtest("fsession_reattach"))
+ test_fsession_reattach();
+}
diff --git a/tools/testing/selftests/bpf/progs/fsession_test.c b/tools/testing/selftests/bpf/progs/fsession_test.c
new file mode 100644
index 000000000000..f504984d42f2
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/fsession_test.c
@@ -0,0 +1,110 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2025 ChinaTelecom */
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+__u64 test1_entry_result = 0;
+__u64 test1_exit_result = 0;
+
+SEC("fsession/bpf_fentry_test1")
+int BPF_PROG(test1, int a, int ret)
+{
+ bool is_exit = bpf_session_is_return(ctx);
+
+ if (!is_exit) {
+ test1_entry_result = a == 1 && ret == 0;
+ return 0;
+ }
+
+ test1_exit_result = a == 1 && ret == 2;
+ return 0;
+}
+
+__u64 test2_entry_result = 0;
+__u64 test2_exit_result = 0;
+
+SEC("fsession/bpf_fentry_test3")
+int BPF_PROG(test2, char a, int b, __u64 c, int ret)
+{
+ bool is_exit = bpf_session_is_return(ctx);
+
+ if (!is_exit) {
+ test2_entry_result = a == 4 && b == 5 && c == 6 && ret == 0;
+ return 0;
+ }
+
+ test2_exit_result = a == 4 && b == 5 && c == 6 && ret == 15;
+ return 0;
+}
+
+__u64 test3_entry_result = 0;
+__u64 test3_exit_result = 0;
+
+SEC("fsession/bpf_fentry_test4")
+int BPF_PROG(test3, void *a, char b, int c, __u64 d, int ret)
+{
+ bool is_exit = bpf_session_is_return(ctx);
+
+ if (!is_exit) {
+ test3_entry_result = a == (void *)7 && b == 8 && c == 9 && d == 10 && ret == 0;
+ return 0;
+ }
+
+ test3_exit_result = a == (void *)7 && b == 8 && c == 9 && d == 10 && ret == 34;
+ return 0;
+}
+
+__u64 test4_entry_result = 0;
+__u64 test4_exit_result = 0;
+
+SEC("fsession/bpf_fentry_test5")
+int BPF_PROG(test4, __u64 a, void *b, short c, int d, __u64 e, int ret)
+{
+ bool is_exit = bpf_session_is_return(ctx);
+
+ if (!is_exit) {
+ test4_entry_result = a == 11 && b == (void *)12 && c == 13 && d == 14 &&
+ e == 15 && ret == 0;
+ return 0;
+ }
+
+ test4_exit_result = a == 11 && b == (void *)12 && c == 13 && d == 14 &&
+ e == 15 && ret == 65;
+ return 0;
+}
+
+__u64 test5_entry_result = 0;
+__u64 test5_exit_result = 0;
+
+SEC("fsession/bpf_fentry_test7")
+int BPF_PROG(test5, struct bpf_fentry_test_t *arg, int ret)
+{
+ bool is_exit = bpf_session_is_return(ctx);
+
+ if (!is_exit) {
+ if (!arg)
+ test5_entry_result = ret == 0;
+ return 0;
+ }
+
+ if (!arg)
+ test5_exit_result = 1;
+ return 0;
+}
+
+__u64 test6_entry_result = 0;
+__u64 test6_exit_result = 0;
+SEC("fsession/bpf_fentry_test1")
+int BPF_PROG(test6, int a)
+{
+ __u64 addr = bpf_get_func_ip(ctx);
+
+ if (bpf_session_is_return(ctx))
+ test6_exit_result = (const void *) addr == &bpf_fentry_test1;
+ else
+ test6_entry_result = (const void *) addr == &bpf_fentry_test1;
+ return 0;
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 10/12] selftests/bpf: add testcases for fsession
2026-01-23 7:35 ` [PATCH bpf-next v11 10/12] selftests/bpf: add testcases for fsession Menglong Dong
@ 2026-01-23 7:57 ` bot+bpf-ci
2026-01-23 8:05 ` Menglong Dong
0 siblings, 1 reply; 22+ messages in thread
From: bot+bpf-ci @ 2026-01-23 7:57 UTC (permalink / raw)
To: menglong8.dong, andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1674 bytes --]
> diff --git a/tools/testing/selftests/bpf/progs/fsession_test.c b/tools/testing/selftests/bpf/progs/fsession_test.c
> new file mode 100644
> index 000000000000..f504984d42f2
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/fsession_test.c
> @@ -0,0 +1,110 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2025 ChinaTelecom */
> +#include <vmlinux.h>
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +
> +char _license[] SEC("license") = "GPL";
[ ... ]
> +__u64 test6_entry_result = 0;
> +__u64 test6_exit_result = 0;
> +SEC("fsession/bpf_fentry_test1")
> +int BPF_PROG(test6, int a)
> +{
> + __u64 addr = bpf_get_func_ip(ctx);
> +
> + if (bpf_session_is_return(ctx))
> + test6_exit_result = (const void *) addr == &bpf_fentry_test1;
> + else
> + test6_entry_result = (const void *) addr == &bpf_fentry_test1;
^^^^^^^^^^^^^^^^^^
Is the bpf_fentry_test1 symbol declared somewhere? The code references
&bpf_fentry_test1 but there is no extern declaration with __ksym in this
file.
Other BPF selftests that take addresses of kernel symbols declare them
explicitly, for example get_func_ip_test.c has:
extern int bpf_fentry_test1(int a) __ksym;
And kprobe_multi_session.c has:
extern const void bpf_fentry_test1 __ksym;
Without a similar declaration, will this BPF program compile and load
correctly?
> + return 0;
> +}
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
^ permalink raw reply [flat|nested] 22+ messages in thread* Re: [PATCH bpf-next v11 10/12] selftests/bpf: add testcases for fsession
2026-01-23 7:57 ` bot+bpf-ci
@ 2026-01-23 8:05 ` Menglong Dong
0 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 8:05 UTC (permalink / raw)
To: menglong8.dong, andrii, bot+bpf-ci
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
On 2026/1/23 15:57 bot+bpf-ci@kernel.org write:
> > diff --git a/tools/testing/selftests/bpf/progs/fsession_test.c b/tools/testing/selftests/bpf/progs/fsession_test.c
> > new file mode 100644
> > index 000000000000..f504984d42f2
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/progs/fsession_test.c
> > @@ -0,0 +1,110 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +/* Copyright (c) 2025 ChinaTelecom */
> > +#include <vmlinux.h>
> > +#include <bpf/bpf_helpers.h>
> > +#include <bpf/bpf_tracing.h>
> > +
> > +char _license[] SEC("license") = "GPL";
>
> [ ... ]
>
> > +__u64 test6_entry_result = 0;
> > +__u64 test6_exit_result = 0;
> > +SEC("fsession/bpf_fentry_test1")
> > +int BPF_PROG(test6, int a)
> > +{
> > + __u64 addr = bpf_get_func_ip(ctx);
> > +
> > + if (bpf_session_is_return(ctx))
> > + test6_exit_result = (const void *) addr == &bpf_fentry_test1;
> > + else
> > + test6_entry_result = (const void *) addr == &bpf_fentry_test1;
> ^^^^^^^^^^^^^^^^^^
>
> Is the bpf_fentry_test1 symbol declared somewhere? The code references
> &bpf_fentry_test1 but there is no extern declaration with __ksym in this
> file.
The symbol "bpf_fentry_test1" will be declared in vmlinux.h, which is
generated automatically.
>
> Other BPF selftests that take addresses of kernel symbols declare them
> explicitly, for example get_func_ip_test.c has:
>
> extern int bpf_fentry_test1(int a) __ksym;
>
> And kprobe_multi_session.c has:
>
> extern const void bpf_fentry_test1 __ksym;
>
> Without a similar declaration, will this BPF program compile and load
> correctly?
As I said above, it won't cause compile problem.
Thanks!
Menglong Dong
>
> > + return 0;
> > +}
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/21278745581
>
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH bpf-next v11 11/12] selftests/bpf: add testcases for fsession cookie
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (9 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 10/12] selftests/bpf: add testcases for fsession Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
2026-01-23 7:35 ` [PATCH bpf-next v11 12/12] selftests/bpf: test fsession mixed with fentry and fexit Menglong Dong
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Test session cookie for fsession. Multiple fsession BPF progs is attached
to bpf_fentry_test1() and session cookie is read and write in the
testcase.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
v11:
- add "volatile" to the variable "cookie"
v3:
- restructure the testcase by combine the testcases for session cookie and
get_func_ip into one patch
---
.../selftests/bpf/progs/fsession_test.c | 53 +++++++++++++++++++
1 file changed, 53 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/fsession_test.c b/tools/testing/selftests/bpf/progs/fsession_test.c
index f504984d42f2..211332bdcccb 100644
--- a/tools/testing/selftests/bpf/progs/fsession_test.c
+++ b/tools/testing/selftests/bpf/progs/fsession_test.c
@@ -108,3 +108,56 @@ int BPF_PROG(test6, int a)
test6_entry_result = (const void *) addr == &bpf_fentry_test1;
return 0;
}
+
+__u64 test7_entry_ok = 0;
+__u64 test7_exit_ok = 0;
+SEC("fsession/bpf_fentry_test1")
+int BPF_PROG(test7, int a)
+{
+ volatile __u64 *cookie = bpf_session_cookie(ctx);
+
+ if (!bpf_session_is_return(ctx)) {
+ *cookie = 0xAAAABBBBCCCCDDDDull;
+ test7_entry_ok = *cookie == 0xAAAABBBBCCCCDDDDull;
+ return 0;
+ }
+
+ test7_exit_ok = *cookie == 0xAAAABBBBCCCCDDDDull;
+ return 0;
+}
+
+__u64 test8_entry_ok = 0;
+__u64 test8_exit_ok = 0;
+
+SEC("fsession/bpf_fentry_test1")
+int BPF_PROG(test8, int a)
+{
+ volatile __u64 *cookie = bpf_session_cookie(ctx);
+
+ if (!bpf_session_is_return(ctx)) {
+ *cookie = 0x1111222233334444ull;
+ test8_entry_ok = *cookie == 0x1111222233334444ull;
+ return 0;
+ }
+
+ test8_exit_ok = *cookie == 0x1111222233334444ull;
+ return 0;
+}
+
+__u64 test9_entry_result = 0;
+__u64 test9_exit_result = 0;
+
+SEC("fsession/bpf_fentry_test1")
+int BPF_PROG(test9, int a, int ret)
+{
+ __u64 *cookie = bpf_session_cookie(ctx);
+
+ if (!bpf_session_is_return(ctx)) {
+ test9_entry_result = a == 1 && ret == 0;
+ *cookie = 0x123456ULL;
+ return 0;
+ }
+
+ test9_exit_result = a == 1 && ret == 2 && *cookie == 0x123456ULL;
+ return 0;
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH bpf-next v11 12/12] selftests/bpf: test fsession mixed with fentry and fexit
2026-01-23 7:35 [PATCH bpf-next v11 00/12] bpf: fsession support Menglong Dong
` (10 preceding siblings ...)
2026-01-23 7:35 ` [PATCH bpf-next v11 11/12] selftests/bpf: add testcases for fsession cookie Menglong Dong
@ 2026-01-23 7:35 ` Menglong Dong
11 siblings, 0 replies; 22+ messages in thread
From: Menglong Dong @ 2026-01-23 7:35 UTC (permalink / raw)
To: andrii
Cc: daniel, martin.lau, eddyz87, song, yonghong.song, john.fastabend,
kpsingh, sdf, haoluo, jolsa, davem, dsahern, tglx, mingo,
jiang.biao, bp, dave.hansen, x86, hpa, bpf, netdev, linux-kernel
Test the fsession when it is used together with fentry, fexit.
Signed-off-by: Menglong Dong <dongml2@chinatelecom.cn>
---
.../testing/selftests/bpf/progs/fsession_test.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/fsession_test.c b/tools/testing/selftests/bpf/progs/fsession_test.c
index 211332bdcccb..86e8a2fe467e 100644
--- a/tools/testing/selftests/bpf/progs/fsession_test.c
+++ b/tools/testing/selftests/bpf/progs/fsession_test.c
@@ -161,3 +161,19 @@ int BPF_PROG(test9, int a, int ret)
test9_exit_result = a == 1 && ret == 2 && *cookie == 0x123456ULL;
return 0;
}
+
+__u64 test10_result = 0;
+SEC("fexit/bpf_fentry_test1")
+int BPF_PROG(test10, int a, int ret)
+{
+ test10_result = a == 1 && ret == 2;
+ return 0;
+}
+
+__u64 test11_result = 0;
+SEC("fentry/bpf_fentry_test1")
+int BPF_PROG(test11, int a)
+{
+ test11_result = a == 1;
+ return 0;
+}
--
2.52.0
^ permalink raw reply related [flat|nested] 22+ messages in thread