Add BPF selftests that exercise the new dentry kfuncs via an LSM program attached to the file_open hook. Signed-off-by: David Windsor --- .../selftests/bpf/prog_tests/dentry_lsm.c | 48 +++++++++++++++++ .../testing/selftests/bpf/progs/dentry_lsm.c | 51 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/dentry_lsm.c create mode 100644 tools/testing/selftests/bpf/progs/dentry_lsm.c diff --git a/tools/testing/selftests/bpf/prog_tests/dentry_lsm.c b/tools/testing/selftests/bpf/prog_tests/dentry_lsm.c new file mode 100644 index 000000000000..3e8c68017954 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/dentry_lsm.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 David Windsor */ + +#include +#include +#include +#include +#include +#include +#include +#include "dentry_lsm.skel.h" + +void test_dentry_lsm(void) +{ + struct dentry_lsm *skel; + char test_file[PATH_MAX]; + int fd, ret; + + skel = dentry_lsm__open_and_load(); + if (!ASSERT_OK_PTR(skel, "dentry_lsm__open_and_load")) + return; + + ret = dentry_lsm__attach(skel); + if (!ASSERT_OK(ret, "dentry_lsm__attach")) + goto cleanup; + + /* Create a temporary file to trigger file_open LSM hook */ + ret = snprintf(test_file, sizeof(test_file), "/tmp/bpf_test_file_%d", getpid()); + if (!ASSERT_GT(ret, 0, "snprintf")) + goto cleanup_link; + if (!ASSERT_LT(ret, sizeof(test_file), "snprintf")) + goto cleanup_link; + + fd = open(test_file, O_CREAT | O_RDWR, 0644); + if (!ASSERT_GE(fd, 0, "open")) + goto cleanup_link; + close(fd); + + /* Test passes if BPF program loaded and ran without error */ + + /* Clean up test file */ + unlink(test_file); + +cleanup_link: + unlink(test_file); +cleanup: + dentry_lsm__destroy(skel); +} diff --git a/tools/testing/selftests/bpf/progs/dentry_lsm.c b/tools/testing/selftests/bpf/progs/dentry_lsm.c new file mode 100644 index 000000000000..fa6d65d2c50f --- /dev/null +++ b/tools/testing/selftests/bpf/progs/dentry_lsm.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2025 David Windsor */ + +#include "vmlinux.h" +#include +#include +#include + +extern struct dentry *bpf_dget(struct dentry *dentry) __ksym; +extern void bpf_dput(struct dentry *dentry) __ksym; +extern struct dentry *bpf_dget_parent(struct dentry *dentry) __ksym; +extern struct dentry *bpf_d_find_alias(struct inode *inode) __ksym; +extern struct dentry *bpf_file_dentry(struct file *file) __ksym; +extern struct vfsmount *bpf_file_vfsmount(struct file *file) __ksym; + +SEC("lsm.s/file_open") +int BPF_PROG(file_open, struct file *file) +{ + struct dentry *dentry, *parent, *alias, *dentry_ref; + struct vfsmount *vfs_mnt; + + if (!file) + return 0; + + dentry = bpf_file_dentry(file); + if (dentry) { + dentry_ref = bpf_dget(dentry); + if (dentry_ref) + bpf_dput(dentry_ref); + + parent = bpf_dget_parent(dentry); + if (parent) + bpf_dput(parent); + } + + if (file->f_inode) { + alias = bpf_d_find_alias(file->f_inode); + if (alias) + bpf_dput(alias); + } + + vfs_mnt = bpf_file_vfsmount(file); + if (vfs_mnt) { + /* Test that we can access vfsmount */ + (void)vfs_mnt; + } + + return 0; +} + +char _license[] SEC("license") = "GPL"; -- 2.43.0