* [PATCH v2 0/2] selftests/bpf: make probe_user safe for parallel runs
@ 2026-02-26 9:31 Sun Jian
2026-02-26 9:31 ` [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference Sun Jian
2026-02-26 9:31 ` [PATCH v2 2/2] selftests/bpf: probe_user: drop serial restriction Sun Jian
0 siblings, 2 replies; 5+ messages in thread
From: Sun Jian @ 2026-02-26 9:31 UTC (permalink / raw)
To: Andrii Nakryiko, Shuah Khan
Cc: Eduard Zingerman, Alexei Starovoitov, Daniel Borkmann, bpf,
linux-kselftest, linux-kernel, Sun Jian
The probe_user selftest attaches ksyscall hooks for connect() (and
socketcall() on s390). Historically it could corrupt other tests
calling connect() in parallel, causing flaky failures.
This series confines the instrumentation to the current test process only,
and then drops the serial restriction and removes the stale TODO.
v1: <https://lore.kernel.org/all/cover.1772079741.git.sun.jian.kdev@gmail.com/>
Changes in v2:
- Replace pid_map with a global .bss struct initialized via
bpf_map__set_initial_value() before bpf_object__load().
- Add bpf_map__value_size() check for the .bss map to catch
layout mismatch.
- Move PID filtering into handle_sys_connect_common() (covers both
connect() and s390 socketcall() paths).
- Keep existing validation flow intact (bridge via tmp buffer).
Tested:
- cd .kselftest-out/selftests-bpf
./test_progs -t probe_user -v
- cd .kselftest-out/selftests-bpf
./test_progs -j"$(nproc)" -t probe_user -v
Sun Jian (2):
selftests/bpf: probe_user: filter by pid to avoid cross-test
interference
selftests/bpf: probe_user: drop serial restriction
.../selftests/bpf/prog_tests/probe_user.c | 30 +++++++++++++++++--
.../selftests/bpf/progs/test_probe_user.c | 13 ++++++--
2 files changed, 38 insertions(+), 5 deletions(-)
base-commit: 7dff99b354601dd01829e1511711846e04340a69
--
2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference
2026-02-26 9:31 [PATCH v2 0/2] selftests/bpf: make probe_user safe for parallel runs Sun Jian
@ 2026-02-26 9:31 ` Sun Jian
2026-02-26 15:18 ` Mykyta Yatsenko
2026-03-05 23:10 ` Andrii Nakryiko
2026-02-26 9:31 ` [PATCH v2 2/2] selftests/bpf: probe_user: drop serial restriction Sun Jian
1 sibling, 2 replies; 5+ messages in thread
From: Sun Jian @ 2026-02-26 9:31 UTC (permalink / raw)
To: Andrii Nakryiko, Shuah Khan
Cc: Eduard Zingerman, Alexei Starovoitov, Daniel Borkmann, bpf,
linux-kselftest, linux-kernel, Sun Jian
The test installs a kprobe on __sys_connect and checks that
bpf_probe_write_user() can modify the syscall argument. However, any
concurrent thread in any other test that calls connect() will also
trigger the kprobe and have its sockaddr silently overwritten, causing
flaky failures in unrelated tests.
Constrain the hook to the current test process by filtering on a PID
stored as a global variable in .bss. Initialize the .bss value from
user space before bpf_object__load() using bpf_map__set_initial_value(),
and validate the bss map value size to catch layout mismatches.
No new map is introduced and the test keeps the existing non-skeleton
flow.
Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
---
.../selftests/bpf/prog_tests/probe_user.c | 27 ++++++++++++++++++-
.../selftests/bpf/progs/test_probe_user.c | 13 +++++++--
2 files changed, 37 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/probe_user.c b/tools/testing/selftests/bpf/prog_tests/probe_user.c
index 8721671321de..280dcdb5ddef 100644
--- a/tools/testing/selftests/bpf/prog_tests/probe_user.c
+++ b/tools/testing/selftests/bpf/prog_tests/probe_user.c
@@ -20,6 +20,11 @@ void serial_test_probe_user(void)
struct bpf_program *kprobe_progs[prog_count];
struct bpf_object *obj;
static const int zero = 0;
+ struct test_pro_bss {
+ struct sockaddr_in old;
+ __u32 test_pid;
+ };
+ struct test_pro_bss results = {};
size_t i;
obj = bpf_object__open_file(obj_file, &opts);
@@ -34,6 +39,24 @@ void serial_test_probe_user(void)
goto cleanup;
}
+ {
+ struct bpf_map *bss_map;
+ struct test_pro_bss bss_init = {};
+
+ bss_init.test_pid = getpid();
+ bss_map = bpf_object__find_map_by_name(obj, "test_pro.bss");
+ if (CHECK(!bss_map, "find_bss_map", "no bss map\n"))
+ goto cleanup;
+ if (CHECK(bpf_map__value_size(bss_map) != sizeof(bss_init),
+ "bss_size", "bss value_size %u != %zu\n",
+ bpf_map__value_size(bss_map), sizeof(bss_init)))
+ goto cleanup;
+ err = bpf_map__set_initial_value(bss_map, &bss_init,
+ sizeof(bss_init));
+ if (CHECK(err, "set_bss_init", "err %d\n", err))
+ goto cleanup;
+ }
+
err = bpf_object__load(obj);
if (CHECK(err, "obj_load", "err %d\n", err))
goto cleanup;
@@ -62,11 +85,13 @@ void serial_test_probe_user(void)
connect(sock_fd, &curr, sizeof(curr));
close(sock_fd);
- err = bpf_map_lookup_elem(results_map_fd, &zero, &tmp);
+ err = bpf_map_lookup_elem(results_map_fd, &zero, &results);
if (CHECK(err, "get_kprobe_res",
"failed to get kprobe res: %d\n", err))
goto cleanup;
+ memcpy(&tmp, &results.old, sizeof(tmp));
+
in = (struct sockaddr_in *)&tmp;
if (CHECK(memcmp(&tmp, &orig, sizeof(orig)), "check_kprobe_res",
"wrong kprobe res from probe read: %s:%u\n",
diff --git a/tools/testing/selftests/bpf/progs/test_probe_user.c b/tools/testing/selftests/bpf/progs/test_probe_user.c
index a8e501af9604..4bc86c7654b1 100644
--- a/tools/testing/selftests/bpf/progs/test_probe_user.c
+++ b/tools/testing/selftests/bpf/progs/test_probe_user.c
@@ -5,13 +5,22 @@
#include <bpf/bpf_core_read.h>
#include "bpf_misc.h"
-static struct sockaddr_in old;
+struct test_pro_bss {
+ struct sockaddr_in old;
+ __u32 test_pid;
+};
+
+struct test_pro_bss bss;
static int handle_sys_connect_common(struct sockaddr_in *uservaddr)
{
struct sockaddr_in new;
+ __u32 cur = bpf_get_current_pid_tgid() >> 32;
+
+ if (bss.test_pid && cur != bss.test_pid)
+ return 0;
- bpf_probe_read_user(&old, sizeof(old), uservaddr);
+ bpf_probe_read_user(&bss.old, sizeof(bss.old), uservaddr);
__builtin_memset(&new, 0xab, sizeof(new));
bpf_probe_write_user(uservaddr, &new, sizeof(new));
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] selftests/bpf: probe_user: drop serial restriction
2026-02-26 9:31 [PATCH v2 0/2] selftests/bpf: make probe_user safe for parallel runs Sun Jian
2026-02-26 9:31 ` [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference Sun Jian
@ 2026-02-26 9:31 ` Sun Jian
1 sibling, 0 replies; 5+ messages in thread
From: Sun Jian @ 2026-02-26 9:31 UTC (permalink / raw)
To: Andrii Nakryiko, Shuah Khan
Cc: Eduard Zingerman, Alexei Starovoitov, Daniel Borkmann, bpf,
linux-kselftest, linux-kernel, Sun Jian
Patch 1/2 added PID filtering to the probe_user BPF program to avoid
cross-test interference from the global connect() hooks.
With the interference removed, drop the serial_ prefix and remove the
stale TODO comment so the test can run in parallel.
Tested:
./test_progs -t probe_user -v
./test_progs -j$(nproc) -t probe_user
Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
---
tools/testing/selftests/bpf/prog_tests/probe_user.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/probe_user.c b/tools/testing/selftests/bpf/prog_tests/probe_user.c
index 280dcdb5ddef..930cded1602f 100644
--- a/tools/testing/selftests/bpf/prog_tests/probe_user.c
+++ b/tools/testing/selftests/bpf/prog_tests/probe_user.c
@@ -1,8 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
-/* TODO: corrupts other tests uses connect() */
-void serial_test_probe_user(void)
+void test_probe_user(void)
{
static const char *const prog_names[] = {
"handle_sys_connect",
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference
2026-02-26 9:31 ` [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference Sun Jian
@ 2026-02-26 15:18 ` Mykyta Yatsenko
2026-03-05 23:10 ` Andrii Nakryiko
1 sibling, 0 replies; 5+ messages in thread
From: Mykyta Yatsenko @ 2026-02-26 15:18 UTC (permalink / raw)
To: Sun Jian, Andrii Nakryiko, Shuah Khan
Cc: Eduard Zingerman, Alexei Starovoitov, Daniel Borkmann, bpf,
linux-kselftest, linux-kernel, Sun Jian
Sun Jian <sun.jian.kdev@gmail.com> writes:
> The test installs a kprobe on __sys_connect and checks that
> bpf_probe_write_user() can modify the syscall argument. However, any
> concurrent thread in any other test that calls connect() will also
> trigger the kprobe and have its sockaddr silently overwritten, causing
> flaky failures in unrelated tests.
>
> Constrain the hook to the current test process by filtering on a PID
> stored as a global variable in .bss. Initialize the .bss value from
> user space before bpf_object__load() using bpf_map__set_initial_value(),
> and validate the bss map value size to catch layout mismatches.
>
> No new map is introduced and the test keeps the existing non-skeleton
> flow.
>
> Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
> ---
> .../selftests/bpf/prog_tests/probe_user.c | 27 ++++++++++++++++++-
> .../selftests/bpf/progs/test_probe_user.c | 13 +++++++--
> 2 files changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/probe_user.c b/tools/testing/selftests/bpf/prog_tests/probe_user.c
> index 8721671321de..280dcdb5ddef 100644
> --- a/tools/testing/selftests/bpf/prog_tests/probe_user.c
> +++ b/tools/testing/selftests/bpf/prog_tests/probe_user.c
> @@ -20,6 +20,11 @@ void serial_test_probe_user(void)
> struct bpf_program *kprobe_progs[prog_count];
> struct bpf_object *obj;
> static const int zero = 0;
> + struct test_pro_bss {
> + struct sockaddr_in old;
> + __u32 test_pid;
> + };
> + struct test_pro_bss results = {};
> size_t i;
>
> obj = bpf_object__open_file(obj_file, &opts);
> @@ -34,6 +39,24 @@ void serial_test_probe_user(void)
> goto cleanup;
> }
>
> + {
> + struct bpf_map *bss_map;
> + struct test_pro_bss bss_init = {};
> +
> + bss_init.test_pid = getpid();
> + bss_map = bpf_object__find_map_by_name(obj, "test_pro.bss");
> + if (CHECK(!bss_map, "find_bss_map", "no bss map\n"))
> + goto cleanup;
> + if (CHECK(bpf_map__value_size(bss_map) != sizeof(bss_init),
> + "bss_size", "bss value_size %u != %zu\n",
> + bpf_map__value_size(bss_map), sizeof(bss_init)))
> + goto cleanup;
> + err = bpf_map__set_initial_value(bss_map, &bss_init,
> + sizeof(bss_init));
> + if (CHECK(err, "set_bss_init", "err %d\n", err))
> + goto cleanup;
> + }
> +
> err = bpf_object__load(obj);
> if (CHECK(err, "obj_load", "err %d\n", err))
> goto cleanup;
> @@ -62,11 +85,13 @@ void serial_test_probe_user(void)
> connect(sock_fd, &curr, sizeof(curr));
> close(sock_fd);
>
> - err = bpf_map_lookup_elem(results_map_fd, &zero, &tmp);
> + err = bpf_map_lookup_elem(results_map_fd, &zero, &results);
> if (CHECK(err, "get_kprobe_res",
> "failed to get kprobe res: %d\n", err))
> goto cleanup;
>
> + memcpy(&tmp, &results.old, sizeof(tmp));
> +
> in = (struct sockaddr_in *)&tmp;
> if (CHECK(memcmp(&tmp, &orig, sizeof(orig)), "check_kprobe_res",
> "wrong kprobe res from probe read: %s:%u\n",
> diff --git a/tools/testing/selftests/bpf/progs/test_probe_user.c b/tools/testing/selftests/bpf/progs/test_probe_user.c
> index a8e501af9604..4bc86c7654b1 100644
> --- a/tools/testing/selftests/bpf/progs/test_probe_user.c
> +++ b/tools/testing/selftests/bpf/progs/test_probe_user.c
> @@ -5,13 +5,22 @@
> #include <bpf/bpf_core_read.h>
> #include "bpf_misc.h"
>
> -static struct sockaddr_in old;
> +struct test_pro_bss {
> + struct sockaddr_in old;
> + __u32 test_pid;
> +};
> +
> +struct test_pro_bss bss;
>
> static int handle_sys_connect_common(struct sockaddr_in *uservaddr)
> {
> struct sockaddr_in new;
> + __u32 cur = bpf_get_current_pid_tgid() >> 32;
> +
> + if (bss.test_pid && cur != bss.test_pid)
> + return 0;
>
> - bpf_probe_read_user(&old, sizeof(old), uservaddr);
> + bpf_probe_read_user(&bss.old, sizeof(bss.old), uservaddr);
> __builtin_memset(&new, 0xab, sizeof(new));
> bpf_probe_write_user(uservaddr, &new, sizeof(new));
>
> --
> 2.43.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference
2026-02-26 9:31 ` [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference Sun Jian
2026-02-26 15:18 ` Mykyta Yatsenko
@ 2026-03-05 23:10 ` Andrii Nakryiko
1 sibling, 0 replies; 5+ messages in thread
From: Andrii Nakryiko @ 2026-03-05 23:10 UTC (permalink / raw)
To: Sun Jian
Cc: Andrii Nakryiko, Shuah Khan, Eduard Zingerman, Alexei Starovoitov,
Daniel Borkmann, bpf, linux-kselftest, linux-kernel
On Thu, Feb 26, 2026 at 1:31 AM Sun Jian <sun.jian.kdev@gmail.com> wrote:
>
> The test installs a kprobe on __sys_connect and checks that
> bpf_probe_write_user() can modify the syscall argument. However, any
> concurrent thread in any other test that calls connect() will also
> trigger the kprobe and have its sockaddr silently overwritten, causing
> flaky failures in unrelated tests.
>
> Constrain the hook to the current test process by filtering on a PID
> stored as a global variable in .bss. Initialize the .bss value from
> user space before bpf_object__load() using bpf_map__set_initial_value(),
> and validate the bss map value size to catch layout mismatches.
>
> No new map is introduced and the test keeps the existing non-skeleton
> flow.
>
> Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
> ---
> .../selftests/bpf/prog_tests/probe_user.c | 27 ++++++++++++++++++-
> .../selftests/bpf/progs/test_probe_user.c | 13 +++++++--
> 2 files changed, 37 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/probe_user.c b/tools/testing/selftests/bpf/prog_tests/probe_user.c
> index 8721671321de..280dcdb5ddef 100644
> --- a/tools/testing/selftests/bpf/prog_tests/probe_user.c
> +++ b/tools/testing/selftests/bpf/prog_tests/probe_user.c
> @@ -20,6 +20,11 @@ void serial_test_probe_user(void)
> struct bpf_program *kprobe_progs[prog_count];
> struct bpf_object *obj;
> static const int zero = 0;
> + struct test_pro_bss {
> + struct sockaddr_in old;
> + __u32 test_pid;
> + };
> + struct test_pro_bss results = {};
> size_t i;
>
> obj = bpf_object__open_file(obj_file, &opts);
> @@ -34,6 +39,24 @@ void serial_test_probe_user(void)
> goto cleanup;
> }
>
> + {
> + struct bpf_map *bss_map;
> + struct test_pro_bss bss_init = {};
> +
> + bss_init.test_pid = getpid();
> + bss_map = bpf_object__find_map_by_name(obj, "test_pro.bss");
> + if (CHECK(!bss_map, "find_bss_map", "no bss map\n"))
> + goto cleanup;
> + if (CHECK(bpf_map__value_size(bss_map) != sizeof(bss_init),
> + "bss_size", "bss value_size %u != %zu\n",
> + bpf_map__value_size(bss_map), sizeof(bss_init)))
> + goto cleanup;
> + err = bpf_map__set_initial_value(bss_map, &bss_init,
> + sizeof(bss_init));
> + if (CHECK(err, "set_bss_init", "err %d\n", err))
> + goto cleanup;
don't use CHECK() macro, use sproper ASSERT_xxx()
and for email subject, stick to "selftest/bpf:" without extra
"something: " after this
pw-bot: cr
> + }
> +
> err = bpf_object__load(obj);
> if (CHECK(err, "obj_load", "err %d\n", err))
> goto cleanup;
> @@ -62,11 +85,13 @@ void serial_test_probe_user(void)
> connect(sock_fd, &curr, sizeof(curr));
> close(sock_fd);
>
> - err = bpf_map_lookup_elem(results_map_fd, &zero, &tmp);
> + err = bpf_map_lookup_elem(results_map_fd, &zero, &results);
> if (CHECK(err, "get_kprobe_res",
> "failed to get kprobe res: %d\n", err))
> goto cleanup;
>
> + memcpy(&tmp, &results.old, sizeof(tmp));
> +
> in = (struct sockaddr_in *)&tmp;
> if (CHECK(memcmp(&tmp, &orig, sizeof(orig)), "check_kprobe_res",
> "wrong kprobe res from probe read: %s:%u\n",
> diff --git a/tools/testing/selftests/bpf/progs/test_probe_user.c b/tools/testing/selftests/bpf/progs/test_probe_user.c
> index a8e501af9604..4bc86c7654b1 100644
> --- a/tools/testing/selftests/bpf/progs/test_probe_user.c
> +++ b/tools/testing/selftests/bpf/progs/test_probe_user.c
> @@ -5,13 +5,22 @@
> #include <bpf/bpf_core_read.h>
> #include "bpf_misc.h"
>
> -static struct sockaddr_in old;
> +struct test_pro_bss {
> + struct sockaddr_in old;
> + __u32 test_pid;
> +};
> +
> +struct test_pro_bss bss;
>
> static int handle_sys_connect_common(struct sockaddr_in *uservaddr)
> {
> struct sockaddr_in new;
> + __u32 cur = bpf_get_current_pid_tgid() >> 32;
> +
> + if (bss.test_pid && cur != bss.test_pid)
> + return 0;
>
> - bpf_probe_read_user(&old, sizeof(old), uservaddr);
> + bpf_probe_read_user(&bss.old, sizeof(bss.old), uservaddr);
> __builtin_memset(&new, 0xab, sizeof(new));
> bpf_probe_write_user(uservaddr, &new, sizeof(new));
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-03-05 23:10 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-26 9:31 [PATCH v2 0/2] selftests/bpf: make probe_user safe for parallel runs Sun Jian
2026-02-26 9:31 ` [PATCH v2 1/2] selftests/bpf: probe_user: filter by pid to avoid cross-test interference Sun Jian
2026-02-26 15:18 ` Mykyta Yatsenko
2026-03-05 23:10 ` Andrii Nakryiko
2026-02-26 9:31 ` [PATCH v2 2/2] selftests/bpf: probe_user: drop serial restriction Sun Jian
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox