Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kernel/trace/bpf_trace.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,7 +965,7 @@ static const struct bpf_func_proto bpf_d_path_proto = {
.ret_type = RET_INTEGER,
.arg1_type = ARG_PTR_TO_BTF_ID,
.arg1_btf_id = &bpf_d_path_btf_ids[0],
.arg2_type = ARG_PTR_TO_MEM,
.arg2_type = ARG_PTR_TO_MEM | MEM_WRITE,
.arg3_type = ARG_CONST_SIZE_OR_ZERO,
.allowed = bpf_d_path_allowed,
};
Expand Down
88 changes: 71 additions & 17 deletions tools/testing/selftests/bpf/prog_tests/d_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ static int set_pathname(int fd, pid_t pid)
return readlink(buf, src.paths[src.cnt++], MAX_PATH_LEN);
}

static inline long syscall_close(int fd)
{
return syscall(__NR_close_range,
(unsigned int)fd,
(unsigned int)fd,
0u);
}

static int trigger_fstat_events(pid_t pid)
{
int sockfd = -1, procfd = -1, devfd = -1;
Expand Down Expand Up @@ -104,18 +112,34 @@ static int trigger_fstat_events(pid_t pid)
/* sys_close no longer triggers filp_close, but we can
* call sys_close_range instead which still does
*/
#define close(fd) syscall(__NR_close_range, fd, fd, 0)
syscall_close(pipefd[0]);
syscall_close(pipefd[1]);
syscall_close(sockfd);
syscall_close(procfd);
syscall_close(devfd);
syscall_close(localfd);
syscall_close(indicatorfd);
return ret;
}

close(pipefd[0]);
close(pipefd[1]);
close(sockfd);
close(procfd);
close(devfd);
close(localfd);
close(indicatorfd);
static void attach_and_load(struct test_d_path **skel)
{
int err;

#undef close
return ret;
*skel = test_d_path__open_and_load();
if (CHECK(!*skel, "setup", "d_path skeleton failed\n"))
goto cleanup;

err = test_d_path__attach(*skel);
if (CHECK(err, "setup", "attach failed: %d\n", err))
goto cleanup;

(*skel)->bss->my_pid = getpid();
return;

cleanup:
test_d_path__destroy(*skel);
*skel = NULL;
}

static void test_d_path_basic(void)
Expand All @@ -124,16 +148,11 @@ static void test_d_path_basic(void)
struct test_d_path *skel;
int err;

skel = test_d_path__open_and_load();
if (CHECK(!skel, "setup", "d_path skeleton failed\n"))
goto cleanup;

err = test_d_path__attach(skel);
if (CHECK(err, "setup", "attach failed: %d\n", err))
attach_and_load(&skel);
if (!skel)
goto cleanup;

bss = skel->bss;
bss->my_pid = getpid();

err = trigger_fstat_events(bss->my_pid);
if (err < 0)
Expand Down Expand Up @@ -195,6 +214,38 @@ static void test_d_path_check_types(void)
test_d_path_check_types__destroy(skel);
}

/* Check if the verifier correctly generates code for
* accessing the memory modified by d_path helper.
*/
static void test_d_path_mem_access(void)
{
int localfd = -1;
struct test_d_path__bss *bss;
struct test_d_path *skel;

attach_and_load(&skel);
if (!skel)
goto cleanup;

bss = skel->bss;

localfd = open("/tmp/d_path_loadgen.txt", O_CREAT | O_RDWR, 0644);
if (CHECK(localfd < 0, "trigger", "open /tmp/d_path_loadgen.txt failed\n"))
goto cleanup;

if (CHECK(fallocate(localfd, 0, 0, 1024) < 0, "trigger", "fallocate failed\n"))
goto cleanup;
remove("/tmp/d_path_loadgen.txt");

if (CHECK(!bss->path_match_fallocate, "check",
"failed to match actual opened path"))
goto cleanup;

cleanup:
syscall_close(localfd);
test_d_path__destroy(skel);
}

void test_d_path(void)
{
if (test__start_subtest("basic"))
Expand All @@ -205,4 +256,7 @@ void test_d_path(void)

if (test__start_subtest("check_alloc_mem"))
test_d_path_check_types();

if (test__start_subtest("check_mem_access"))
test_d_path_mem_access();
}
23 changes: 23 additions & 0 deletions tools/testing/selftests/bpf/progs/test_d_path.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ int rets_close[MAX_FILES] = {};

int called_stat = 0;
int called_close = 0;
int path_match_fallocate = 0;

SEC("fentry/security_inode_getattr")
int BPF_PROG(prog_stat, struct path *path, struct kstat *stat,
Expand Down Expand Up @@ -62,4 +63,26 @@ int BPF_PROG(prog_close, struct file *file, void *id)
return 0;
}

SEC("fentry/vfs_fallocate")
int BPF_PROG(prog_fallocate, struct file *file, int mode, loff_t offset, loff_t len)
{
pid_t pid = bpf_get_current_pid_tgid() >> 32;
int ret = 0;
char path_fallocate[MAX_PATH_LEN] = {};

if (pid != my_pid)
return 0;

ret = bpf_d_path(&file->f_path,
path_fallocate, MAX_PATH_LEN);
if (ret < 0)
return 0;

if (path_fallocate[0] != '/')
return 0;

path_match_fallocate = 1;
return 0;
}

char _license[] SEC("license") = "GPL";