public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
* [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