Hi, Adding test for bpf_file_d_path helper. It passed the test in my environment using QEMU (./test_progs -t file_d_path) Below are some partial results: ''' + [ -x /etc/rcS.d/S50-startup ] + /etc/rcS.d/S50-startup ./test_progs -t file_d_path Summary: 1/0 PASSED, 0 SKIPPED, 0 FAILED ''' Signed-off-by: Lin Yikai <yikai.lin@xxxxxxxx> --- .../selftests/bpf/prog_tests/file_d_path.c | 115 ++++++++++++++++++ .../selftests/bpf/progs/test_file_d_path.c | 32 +++++ 2 files changed, 147 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/file_d_path.c create mode 100644 tools/testing/selftests/bpf/progs/test_file_d_path.c diff --git a/tools/testing/selftests/bpf/prog_tests/file_d_path.c b/tools/testing/selftests/bpf/prog_tests/file_d_path.c new file mode 100644 index 000000000000..ba76d9467f3e --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/file_d_path.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <test_progs.h> +#include <sys/syscall.h> + +#include "test_file_d_path.skel.h" + +/* Compatible with older versions of glibc begin */ +#ifndef __NR_close_range +#ifdef __alpha__ +#define __NR_close_range 546 +#else +#define __NR_close_range 436 +#endif +#endif + +#define close_fd(fd) syscall(__NR_close_range, fd, fd, 0) +/* Compatible with older versions of glibc end */ + + +#define MAX_PATH_LEN 256 +#define TEST_FILES_NUM 2 + +static int duration; + +static struct { + __u32 cnt; + char paths[TEST_FILES_NUM][MAX_PATH_LEN]; +} record; + +static int set_pathname(int fd, pid_t pid) +{ + char buf[MAX_PATH_LEN]; + + snprintf(buf, MAX_PATH_LEN, "/proc/%d/fd/%d", pid, fd); + return readlink(buf, record.paths[record.cnt++], MAX_PATH_LEN); +} + +static int trigger_filp_close(pid_t pid) +{ + int ret = -1; + const char *comm_path = "/proc/self/comm"; + int commfd = -1; + const char *tmp_path = "/tmp/test_bpf_file_d_path.txt"; + int tmpfd = -1; + + /* open file */ + commfd = open(comm_path, O_RDONLY); + if (CHECK(commfd < 0, "test_file_d_path", "open %s failed\n", comm_path)) + goto fd_close; + + tmpfd = open(tmp_path, O_CREAT | O_RDONLY, 0644); + if (CHECK(tmpfd < 0, "test_file_d_path", "open %s failed\n", tmp_path)) + goto fd_close; + remove(tmp_path); + + /* record file */ + memset(&record, 0, sizeof(record)); + ret = set_pathname(commfd, pid); + if (CHECK(ret < 0, "test_file_d_path", "set_pathname failed for commfd\n")) + goto fd_close; + ret = set_pathname(tmpfd, pid); + if (CHECK(ret < 0, "test_file_d_path", "set_pathname failed for tmpfd\n")) + goto fd_close; + + ret = 0; + /* close file */ +fd_close: + if (commfd != -1) + close_fd(commfd); + if (tmpfd != -1) + close_fd(tmpfd); + return ret; +} + +static void test_base(void) +{ + int err = -1; + struct test_file_d_path__bss *bss; + struct test_file_d_path *skel; + + skel = test_file_d_path__open_and_load(); + if (CHECK(!skel, "open_and_load", "load file_d_path skeleton failed\n")) + goto cleanup; + + err = test_file_d_path__attach(skel); + if (CHECK(err, "attach", "attach file_d_path failed: %s\n", strerror(errno))) + goto cleanup; + + bss = skel->bss; + bss->monitor_pid = getpid(); + + err = trigger_filp_close(bss->monitor_pid); + if (err < 0) + goto cleanup; + + if (CHECK(bss->bpf_called_cnt != TEST_FILES_NUM, + "bpf_called_cnt", + "prog called times diff from with the expectations\n")) + goto cleanup; + + for (int i = 0; i < TEST_FILES_NUM; i++) { + CHECK(strncmp(record.paths[i], bss->bpf_paths_close[i], MAX_PATH_LEN), + "bpf_paths_close", + "the paths diff from the expectations: id=[%d], path: %s vs %s\n", + i, record.paths[i], bss->bpf_paths_close[i]); + } + +cleanup: + test_file_d_path__destroy(skel); +} + +void test_file_d_path(void) +{ + test_base(); +} diff --git a/tools/testing/selftests/bpf/progs/test_file_d_path.c b/tools/testing/selftests/bpf/progs/test_file_d_path.c new file mode 100644 index 000000000000..8db2bcd1179f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_file_d_path.c @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "vmlinux.h" +#include <bpf/bpf_helpers.h> +#include <bpf/bpf_tracing.h> + +#define MAX_PATH_LEN 256 +#define TEST_FILES_NUM 2 + +pid_t monitor_pid = 0; + +__u32 bpf_called_cnt = 0; +char bpf_paths_close[TEST_FILES_NUM][MAX_PATH_LEN] = {0}; + +SEC("kprobe/filp_close") +int test_bpf_file_to_path(struct pt_regs *regs) +{ + void *file = NULL; + pid_t cur_pid = bpf_get_current_pid_tgid() >> 32; + + if (cur_pid != monitor_pid) + return 0; + + if (bpf_called_cnt >= TEST_FILES_NUM) + return 0; + + file = (void *)PT_REGS_PARM1(regs); + bpf_file_d_path(file, bpf_paths_close[bpf_called_cnt++], MAX_PATH_LEN); + + return 0; +} + +char _license[] SEC("license") = "GPL"; -- 2.34.1