From: Shuran Liu <electronlsr@gmail.com>
To: song@kernel.org, mattbobrowski@google.com, bpf@vger.kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org,
martin.lau@linux.dev, eddyz87@gmail.com, yonghong.song@linux.dev,
john.fastabend@gmail.com, kpsingh@kernel.org, sdf@fomichev.me,
haoluo@google.com, jolsa@kernel.org, rostedt@goodmis.org,
mhiramat@kernel.org, mathieu.desnoyers@efficios.com,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
electronlsr@gmail.com, Zesen Liu <ftyg@live.com>,
Peili Gao <gplhust955@gmail.com>,
Haoran Ni <haoran.ni.cs@gmail.com>
Subject: [PATCH bpf v2 2/2] selftests/bpf: fix and consolidate d_path LSM regression test
Date: Tue, 2 Dec 2025 15:54:41 +0800 [thread overview]
Message-ID: <20251202075441.1409-3-electronlsr@gmail.com> (raw)
In-Reply-To: <20251202075441.1409-1-electronlsr@gmail.com>
Add a regression test for bpf_d_path() when invoked from an LSM program.
The test attaches to the bprm_check_security hook, calls bpf_d_path() on
the binary being executed, and verifies that a simple prefix comparison on
the returned pathname behaves correctly after the fix in patch 1.
To avoid nondeterminism, the LSM program now filters based on the
expected PID, which is populated from userspace before the test binary is
executed. This prevents unrelated processes that also trigger the
bprm_check_security LSM hook from overwriting test results. Parent and
child processes are synchronized through a pipe to ensure the PID is set
before the child execs the test binary.
Per review feedback, the new test is merged into the existing d_path
selftest rather than adding new prog_tests/ or progs/ files.
Co-developed-by: Zesen Liu <ftyg@live.com>
Signed-off-by: Zesen Liu <ftyg@live.com>
Co-developed-by: Peili Gao <gplhust955@gmail.com>
Signed-off-by: Peili Gao <gplhust955@gmail.com>
Co-developed-by: Haoran Ni <haoran.ni.cs@gmail.com>
Signed-off-by: Haoran Ni <haoran.ni.cs@gmail.com>
Signed-off-by: Shuran Liu <electronlsr@gmail.com>
---
.../testing/selftests/bpf/prog_tests/d_path.c | 64 +++++++++++++++++++
.../testing/selftests/bpf/progs/test_d_path.c | 33 ++++++++++
2 files changed, 97 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/d_path.c b/tools/testing/selftests/bpf/prog_tests/d_path.c
index ccc768592e66..2909ca3bae0f 100644
--- a/tools/testing/selftests/bpf/prog_tests/d_path.c
+++ b/tools/testing/selftests/bpf/prog_tests/d_path.c
@@ -195,6 +195,67 @@ static void test_d_path_check_types(void)
test_d_path_check_types__destroy(skel);
}
+static void test_d_path_lsm(void)
+{
+ struct test_d_path *skel;
+ int err;
+ int pipefd[2];
+ pid_t pid;
+
+ skel = test_d_path__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "d_path skeleton failed"))
+ return;
+
+ err = test_d_path__attach(skel);
+ if (!ASSERT_OK(err, "attach failed"))
+ goto cleanup;
+
+ /* Prepare the test binary */
+ system("cp /bin/true /tmp/bpf_d_path_test 2>/dev/null || :");
+
+ if (!ASSERT_OK(pipe(pipefd), "pipe failed"))
+ goto cleanup;
+
+ pid = fork();
+ if (!ASSERT_GE(pid, 0, "fork failed")) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ goto cleanup;
+ }
+
+ if (pid == 0) {
+ /* Child */
+ char buf;
+
+ close(pipefd[1]);
+ /* Wait for parent to set PID in BPF map */
+ if (read(pipefd[0], &buf, 1) != 1)
+ exit(1);
+ close(pipefd[0]);
+ execl("/tmp/bpf_d_path_test", "/tmp/bpf_d_path_test", NULL);
+ exit(1);
+ }
+
+ /* Parent */
+ close(pipefd[0]);
+
+ /* Update BPF map with child PID */
+ skel->bss->my_pid = pid;
+
+ /* Signal child to proceed */
+ write(pipefd[1], "G", 1);
+ close(pipefd[1]);
+
+ /* Wait for child */
+ waitpid(pid, NULL, 0);
+
+ ASSERT_EQ(skel->bss->called_lsm, 1, "lsm hook called");
+ ASSERT_EQ(skel->bss->lsm_match, 1, "lsm match");
+
+cleanup:
+ test_d_path__destroy(skel);
+}
+
void test_d_path(void)
{
if (test__start_subtest("basic"))
@@ -205,4 +266,7 @@ void test_d_path(void)
if (test__start_subtest("check_alloc_mem"))
test_d_path_check_types();
+
+ if (test__start_subtest("lsm"))
+ test_d_path_lsm();
}
diff --git a/tools/testing/selftests/bpf/progs/test_d_path.c b/tools/testing/selftests/bpf/progs/test_d_path.c
index 84e1f883f97b..7f65c282069a 100644
--- a/tools/testing/selftests/bpf/progs/test_d_path.c
+++ b/tools/testing/selftests/bpf/progs/test_d_path.c
@@ -17,6 +17,8 @@ int rets_close[MAX_FILES] = {};
int called_stat = 0;
int called_close = 0;
+int called_lsm = 0;
+int lsm_match = 0;
SEC("fentry/security_inode_getattr")
int BPF_PROG(prog_stat, struct path *path, struct kstat *stat,
@@ -62,4 +64,35 @@ int BPF_PROG(prog_close, struct file *file, void *id)
return 0;
}
+SEC("lsm/bprm_check_security")
+int BPF_PROG(prog_lsm, struct linux_binprm *bprm)
+{
+ pid_t pid = bpf_get_current_pid_tgid() >> 32;
+ char path[MAX_PATH_LEN] = {};
+ int ret;
+
+ if (pid != my_pid)
+ return 0;
+
+ called_lsm = 1;
+ ret = bpf_d_path(&bprm->file->f_path, path, MAX_PATH_LEN);
+ if (ret < 0)
+ return 0;
+
+ {
+ static const char target_dir[] = "/tmp/";
+
+#pragma unroll
+ for (int i = 0; i < sizeof(target_dir) - 1; i++) {
+ if (path[i] != target_dir[i]) {
+ lsm_match = -1; /* mismatch */
+ return 0;
+ }
+ }
+ }
+
+ lsm_match = 1; /* prefix match */
+ return 0;
+}
+
char _license[] SEC("license") = "GPL";
--
2.52.0
next prev parent reply other threads:[~2025-12-02 7:55 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-02 7:54 [PATCH bpf v2 0/2] bpf: fix bpf_d_path() helper prototype Shuran Liu
2025-12-02 7:54 ` [PATCH bpf v2 1/2] bpf: mark bpf_d_path() buffer as writeable Shuran Liu
2025-12-02 8:19 ` Matt Bobrowski
2025-12-02 7:54 ` Shuran Liu [this message]
2025-12-02 8:59 ` [PATCH bpf v2 2/2] selftests/bpf: fix and consolidate d_path LSM regression test Matt Bobrowski
[not found] ` <F1F96C9B-EAD1-4FD7-A053-EE072A5F4E53@gmail.com>
2025-12-02 10:51 ` Matt Bobrowski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251202075441.1409-3-electronlsr@gmail.com \
--to=electronlsr@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=ftyg@live.com \
--cc=gplhust955@gmail.com \
--cc=haoluo@google.com \
--cc=haoran.ni.cs@gmail.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=mathieu.desnoyers@efficios.com \
--cc=mattbobrowski@google.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
--cc=sdf@fomichev.me \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).