This adds a test case for verifying that file local storage map works as intended. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@xxxxxxxxx> --- .../bpf/prog_tests/test_local_storage.c | 51 +++++++++++++++++++ .../selftests/bpf/progs/local_storage.c | 23 +++++++++ 2 files changed, 74 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/test_local_storage.c b/tools/testing/selftests/bpf/prog_tests/test_local_storage.c index d2c16eaae367..154dee32320c 100644 --- a/tools/testing/selftests/bpf/prog_tests/test_local_storage.c +++ b/tools/testing/selftests/bpf/prog_tests/test_local_storage.c @@ -24,6 +24,7 @@ static inline int sys_pidfd_open(pid_t pid, unsigned int flags) static unsigned int duration; #define TEST_STORAGE_VALUE 0xbeefdead +#define DUMMY_STORAGE_VALUE 0xdeadbeef struct storage { void *inode; @@ -111,6 +112,51 @@ static bool check_syscall_operations(int map_fd, int obj_fd) return true; } +int test_file_local_storage(struct bpf_map *map) +{ + struct storage ls; + int fd, ret; + + fd = open("/dev/null", O_RDONLY); + if (!ASSERT_GE(fd, 0, "open(/dev/null)")) + return -errno; + + ret = bpf_map_lookup_elem(bpf_map__fd(map), &fd, &ls); + if (!ASSERT_OK(ret, "bpf_map_lookup_elem for file local storage")) + goto end; + + ASSERT_EQ(ls.value, DUMMY_STORAGE_VALUE, "file local value match"); + + ret = bpf_map_delete_elem(bpf_map__fd(map), &fd); + if (!ASSERT_OK(ret, "bpf_map_delete_elem for file local storage")) + goto end; + + ret = bpf_map_lookup_elem(bpf_map__fd(map), &fd, &ls); + if (!ASSERT_EQ(ret, -ENOENT, "bpf_map_lookup_elem should fail")) + goto end; + + memset(&ls, 0, sizeof(ls)); + ls.value = DUMMY_STORAGE_VALUE; + ret = bpf_map_update_elem(bpf_map__fd(map), &fd, &ls, BPF_NOEXIST); + if (!ASSERT_OK(ret, "bpf_map_update_elem for file local storage")) + goto end; + + ret = bpf_map_lookup_elem(bpf_map__fd(map), &fd, &ls); + if (!ASSERT_OK(ret, "bpf_map_lookup_elem for file local storage")) + goto end; + + close(fd); + + ret = bpf_map_lookup_elem(bpf_map__fd(map), &fd, &ls); + if (!ASSERT_EQ(ret, -EBADF, "bpf_map_lookup_elem should fail")) + return -EINVAL; + + return 0; +end: + close(fd); + return ret; +} + void test_test_local_storage(void) { char tmp_dir_path[] = "/tmp/local_storageXXXXXX"; @@ -167,6 +213,11 @@ void test_test_local_storage(void) /* Set the process being monitored to be the current process */ skel->bss->monitored_pid = getpid(); + /* Test file local storage */ + err = test_file_local_storage(skel->maps.file_storage_map); + if (!ASSERT_OK(err, "test_file_local_storage")) + goto close_prog_rmdir; + /* Move copy_of_rm to a new location so that it triggers the * inode_rename LSM hook with a new_dentry that has a NULL inode ptr. */ diff --git a/tools/testing/selftests/bpf/progs/local_storage.c b/tools/testing/selftests/bpf/progs/local_storage.c index 95868bc7ada9..68561812f454 100644 --- a/tools/testing/selftests/bpf/progs/local_storage.c +++ b/tools/testing/selftests/bpf/progs/local_storage.c @@ -44,6 +44,13 @@ struct { __type(value, struct local_storage); } task_storage_map SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_FILE_STORAGE); + __uint(map_flags, BPF_F_NO_PREALLOC); + __type(key, int); + __type(value, struct local_storage); +} file_storage_map SEC(".maps"); + SEC("lsm/inode_unlink") int BPF_PROG(unlink_hook, struct inode *dir, struct dentry *victim) { @@ -181,3 +188,19 @@ void BPF_PROG(exec, struct linux_binprm *bprm) storage->value = DUMMY_STORAGE_VALUE; bpf_spin_unlock(&storage->lock); } + +SEC("lsm/file_open") +int BPF_PROG(file_open, struct file *file) +{ + __u32 pid = bpf_get_current_pid_tgid() >> 32; + struct local_storage *storage; + + if (pid != monitored_pid) + return 0; + + storage = bpf_file_storage_get(&file_storage_map, file, 0, + BPF_LOCAL_STORAGE_GET_F_CREATE); + if (storage) + storage->value = DUMMY_STORAGE_VALUE; + return 0; +} -- 2.33.0