* [PATCH bpf-next v2 0/2] bpf: Fix sleepable check for tracing prog
@ 2026-07-25 13:26 Leon Hwang
2026-07-25 13:26 ` [PATCH bpf-next v2 1/2] " Leon Hwang
2026-07-25 13:26 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable " Leon Hwang
0 siblings, 2 replies; 4+ messages in thread
From: Leon Hwang @ 2026-07-25 13:26 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Sechang Lim,
Varun R Mallya, Leon Hwang, Viktor Malik, linux-kernel,
linux-kselftest, netdev
When CONFIG_FUNCTION_ERROR_INJECTION is disabled, a sleepable tracing prog
is allowed to attach to '__x64_'-alike prefix symbols.
It is because the verifier does not verify whether the symbol is a kernel
function or a bpf prog. That said, a sleepable tracing prog is allowed to
attach to a bpf prog target whose name has '__x64_'-alike prefix.
For example, a sleepable fentry prog attaches to a '__x64_sys_nop' XDP
prog, and copies buffer from a user pointer with bpf_copy_from_user()
helper. After attaching the XDP prog to lo interface, the kernel BUG
could be triggered by 'ping -c 1 -W 1 127.0.0.1':
[ 3.460756] BUG: sleeping function called from invalid context at kernel/bpf/trampoline.c:1324
Fix it by disallowing sleepable tracing prog always when its target is
bpf prog.
Changes:
v1 -> v2:
* Drop redundant 'prog->sleepable' check.
* Collect Acked-by from Viktor, Thanks.
* v1: https://lore.kernel.org/bpf/20260724141422.10463-1-leon.hwang@linux.dev/
Leon Hwang (2):
bpf: Fix sleepable check for tracing prog
selftests/bpf: Verify rejection of sleepable tracing prog
kernel/bpf/verifier.c | 9 ++-
.../selftests/bpf/prog_tests/fexit_bpf2bpf.c | 57 +++++++++++++++++++
.../selftests/bpf/progs/fentry_sleepable.c | 19 +++++++
tools/testing/selftests/bpf/progs/xdp_dummy.c | 6 ++
4 files changed, 88 insertions(+), 3 deletions(-)
create mode 100644 tools/testing/selftests/bpf/progs/fentry_sleepable.c
--
2.55.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH bpf-next v2 1/2] bpf: Fix sleepable check for tracing prog
2026-07-25 13:26 [PATCH bpf-next v2 0/2] bpf: Fix sleepable check for tracing prog Leon Hwang
@ 2026-07-25 13:26 ` Leon Hwang
2026-07-25 13:26 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable " Leon Hwang
1 sibling, 0 replies; 4+ messages in thread
From: Leon Hwang @ 2026-07-25 13:26 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Sechang Lim,
Varun R Mallya, Leon Hwang, Viktor Malik, linux-kernel,
linux-kselftest, netdev
When CONFIG_FUNCTION_ERROR_INJECTION is disabled, a sleepable tracing prog
is allowed to attach to '__x64_'-alike prefix symbols.
It is because the verifier does not verify whether the symbol is a kernel
function or a bpf prog. That said, a sleepable tracing prog is allowed to
attach to a bpf prog target whose name has '__x64_'-alike prefix.
For example, a sleepable fentry prog attaches to a '__x64_sys_nop' XDP
prog, and copies buffer from a user pointer with bpf_copy_from_user()
helper. After attaching the XDP prog to lo interface, the kernel BUG
could be triggered by 'ping -c 1 -W 1 127.0.0.1':
[ 3.460756] BUG: sleeping function called from invalid context at kernel/bpf/trampoline.c:1324
Fix it by disallowing sleepable tracing prog always when its target is
bpf prog.
Fixes: 16d9c5660692 ("bpf: Always allow sleepable programs on syscalls")
Acked-by: Viktor Malik <vmalik@redhat.com>
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
kernel/bpf/verifier.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 52be0a118cce..22ac47d9a553 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -18935,13 +18935,16 @@ static bool is_tracing_multi_id(const struct bpf_prog *prog, u32 btf_id)
}
static int btf_id_allow_sleepable(u32 btf_id, unsigned long addr, const struct bpf_prog *prog,
- const struct btf *btf)
+ const struct btf *btf, const struct bpf_prog *tgt_prog)
{
const struct btf_type *t;
const char *tname;
switch (prog->type) {
case BPF_PROG_TYPE_TRACING:
+ if (tgt_prog)
+ return -EINVAL;
+
t = btf_type_by_id(btf, btf_id);
if (!t)
return -EINVAL;
@@ -19324,7 +19327,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
}
if (prog->sleepable) {
- ret = btf_id_allow_sleepable(btf_id, addr, prog, btf);
+ ret = btf_id_allow_sleepable(btf_id, addr, prog, btf, tgt_prog);
if (ret) {
module_put(mod);
bpf_log(log, "%s is not sleepable\n", tname);
@@ -19575,7 +19578,7 @@ int bpf_check_attach_btf_id_multi(struct btf *btf, struct bpf_prog *prog, u32 bt
/* Check sleepable program attachment. */
if (prog->sleepable) {
- err = btf_id_allow_sleepable(btf_id, addr, prog, btf);
+ err = btf_id_allow_sleepable(btf_id, addr, prog, btf, NULL);
if (err)
return err;
}
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable tracing prog
2026-07-25 13:26 [PATCH bpf-next v2 0/2] bpf: Fix sleepable check for tracing prog Leon Hwang
2026-07-25 13:26 ` [PATCH bpf-next v2 1/2] " Leon Hwang
@ 2026-07-25 13:26 ` Leon Hwang
2026-07-25 13:33 ` sashiko-bot
1 sibling, 1 reply; 4+ messages in thread
From: Leon Hwang @ 2026-07-25 13:26 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Shuah Khan, Sechang Lim,
Varun R Mallya, Leon Hwang, Viktor Malik, linux-kernel,
linux-kselftest, netdev
Add a test to verify that the sleepable tracing prog cannot attach to a
'__x64_sys' prefix prog target.
When CONFIG_FUNCTION_ERROR_INJECTION is disabled, without the fix, the
test would trigger the BUG:
[ 3.460756] BUG: sleeping function called from invalid context at kernel/bpf/trampoline.c:1324
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
.../selftests/bpf/prog_tests/fexit_bpf2bpf.c | 57 +++++++++++++++++++
.../selftests/bpf/progs/fentry_sleepable.c | 19 +++++++
tools/testing/selftests/bpf/progs/xdp_dummy.c | 6 ++
3 files changed, 82 insertions(+)
create mode 100644 tools/testing/selftests/bpf/progs/fentry_sleepable.c
diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
index 4a87d7163c8c..2523c07a16c6 100644
--- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
+++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
@@ -5,6 +5,7 @@
#include <bpf/btf.h>
#include "bind4_prog.skel.h"
#include "freplace_progmap.skel.h"
+#include "fentry_sleepable.skel.h"
#include "xdp_dummy.skel.h"
typedef int (*test_cb)(struct bpf_object *obj);
@@ -576,6 +577,60 @@ static void test_func_replace_progmap(void)
freplace_progmap__destroy(skel);
}
+static void test_sleepable_fentry_to_xdp(void)
+{
+ struct fentry_sleepable *skel = NULL;
+ struct xdp_dummy *skel_xdp = NULL;
+ int ifindex, prog_fd, err;
+ char buff[64] = {};
+
+#ifndef __x86_64__
+ test__skip();
+ return;
+#endif
+
+ ifindex = if_nametoindex("lo");
+ if (!ASSERT_GT(ifindex, 0, "if_nametoindex"))
+ return;
+
+ skel_xdp = xdp_dummy__open_and_load();
+ if (!ASSERT_OK_PTR(skel_xdp, "xdp_dummy__open_and_load"))
+ return;
+
+ skel = fentry_sleepable__open();
+ if (!ASSERT_OK_PTR(skel, "fentry_sleepable__open"))
+ goto out;
+
+ skel->bss->user_ptr = buff;
+
+ prog_fd = bpf_program__fd(skel_xdp->progs.__x64_sys_nop);
+ err = bpf_program__set_attach_target(skel->progs.fentry_xdp, prog_fd, "__x64_sys_nop");
+ if (!ASSERT_OK(err, "bpf_program__set_attach_target"))
+ goto out;
+
+ err = fentry_sleepable__load(skel);
+ ASSERT_ERR(err, "fentry_sleepable__load");
+ if (err)
+ goto out;
+
+ skel->links.fentry_xdp = bpf_program__attach_trace(skel->progs.fentry_xdp);
+ if (!ASSERT_OK_PTR(skel->links.fentry_xdp, "bpf_program__attach_trace"))
+ goto out;
+
+ skel_xdp->links.__x64_sys_nop = bpf_program__attach_xdp(skel_xdp->progs.__x64_sys_nop,
+ ifindex);
+ if (!ASSERT_OK_PTR(skel_xdp->links.__x64_sys_nop, "bpf_program__attach_xdp"))
+ goto out;
+
+ err = system("ping -q -c 1 -W 1 127.0.0.1 > /dev/null");
+ ASSERT_OK(err, "ping");
+ ASSERT_ERR(skel->bss->retval, "retval");
+
+out:
+ fentry_sleepable__destroy(skel);
+ xdp_dummy__destroy(skel_xdp);
+}
+
/* NOTE: affect other tests, must run in serial mode */
void serial_test_fexit_bpf2bpf(void)
{
@@ -607,4 +662,6 @@ void serial_test_fexit_bpf2bpf(void)
test_func_replace_int_with_void();
if (test__start_subtest("freplace_void"))
test_func_replace_void();
+ if (test__start_subtest("sleepable_fentry_to_xdp"))
+ test_sleepable_fentry_to_xdp();
}
diff --git a/tools/testing/selftests/bpf/progs/fentry_sleepable.c b/tools/testing/selftests/bpf/progs/fentry_sleepable.c
new file mode 100644
index 000000000000..44b938f485e2
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/fentry_sleepable.c
@@ -0,0 +1,19 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char LICENSE[] SEC("license") = "GPL";
+
+void *user_ptr;
+int retval;
+
+SEC("fentry.s")
+int BPF_PROG(fentry_xdp)
+{
+ char buff[64];
+
+ retval = bpf_copy_from_user(buff, sizeof(buff), user_ptr);
+ return 0;
+}
+
diff --git a/tools/testing/selftests/bpf/progs/xdp_dummy.c b/tools/testing/selftests/bpf/progs/xdp_dummy.c
index d988b2e0cee8..5f1e0771021d 100644
--- a/tools/testing/selftests/bpf/progs/xdp_dummy.c
+++ b/tools/testing/selftests/bpf/progs/xdp_dummy.c
@@ -10,4 +10,10 @@ int xdp_dummy_prog(struct xdp_md *ctx)
return XDP_PASS;
}
+SEC("xdp")
+int __x64_sys_nop(struct xdp_md *ctx)
+{
+ return XDP_PASS;
+}
+
char _license[] SEC("license") = "GPL";
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable tracing prog
2026-07-25 13:26 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable " Leon Hwang
@ 2026-07-25 13:33 ` sashiko-bot
0 siblings, 0 replies; 4+ messages in thread
From: sashiko-bot @ 2026-07-25 13:33 UTC (permalink / raw)
To: Leon Hwang; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The test contains dead code after the expected failure of `fentry_sleepable__load()`. If this code executes on an unfixed kernel, it intentionally triggers a kernel BUG and crashes the test environment.
--
--- Patch [2]: [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable tracing prog ---
commit 44292a230f0467503b72b0ecb8c6c25244de310b
Author: Leon Hwang <leon.hwang@linux.dev>
selftests/bpf: Verify rejection of sleepable tracing prog
This commit adds a selftest to verify that a sleepable tracing program
cannot attach to a '__x64_sys' prefix program target. The test attempts
to load the program and expects the load to fail, avoiding a kernel BUG
on unpatched kernels.
> diff --git a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
> --- a/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
> +++ b/tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
[ ... ]
> @@ -576,6 +577,60 @@ static void test_func_replace_progmap(void)
[ ... ]
> +static void test_sleepable_fentry_to_xdp(void)
> +{
[ ... ]
> + err = fentry_sleepable__load(skel);
> + ASSERT_ERR(err, "fentry_sleepable__load");
> + if (err)
> + goto out;
> +
> + skel->links.fentry_xdp = bpf_program__attach_trace(skel->progs.fentry_xdp);
> + if (!ASSERT_OK_PTR(skel->links.fentry_xdp, "bpf_program__attach_trace"))
> + goto out;
> +
> + skel_xdp->links.__x64_sys_nop = bpf_program__attach_xdp(skel_xdp->progs.__x64_sys_nop,
> + ifindex);
> + if (!ASSERT_OK_PTR(skel_xdp->links.__x64_sys_nop, "bpf_program__attach_xdp"))
> + goto out;
> +
> + err = system("ping -q -c 1 -W 1 127.0.0.1 > /dev/null");
> + ASSERT_OK(err, "ping");
> + ASSERT_ERR(skel->bss->retval, "retval");
> +
> +out:
> + fentry_sleepable__destroy(skel);
> + xdp_dummy__destroy(skel_xdp);
> +}
[Severity: Medium]
Since the test expects fentry_sleepable__load() to fail (meaning err < 0),
won't the "if (err) goto out;" statement cause the test to immediately branch
to out?
If this code behaves as expected, it appears all the subsequent logic for
bpf_program__attach_trace(), bpf_program__attach_xdp(), and the ping command
becomes unreachable dead code.
Conversely, if the test runs on an unpatched kernel where the load
unexpectedly succeeds (err == 0), the test would fall through to the attach
and ping logic. Could executing this sequence on an unpatched kernel trigger
the exact kernel BUG mentioned in the commit message, potentially crashing
the test environment instead of gracefully failing the test?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260725132624.78373-1-leon.hwang@linux.dev?part=2
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-25 13:33 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-25 13:26 [PATCH bpf-next v2 0/2] bpf: Fix sleepable check for tracing prog Leon Hwang
2026-07-25 13:26 ` [PATCH bpf-next v2 1/2] " Leon Hwang
2026-07-25 13:26 ` [PATCH bpf-next v2 2/2] selftests/bpf: Verify rejection of sleepable " Leon Hwang
2026-07-25 13:33 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.