Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add non-BPF_LSM test for task local storage

Task local storage is enabled for tracing programs. Add two tests for
task local storage without CONFIG_BPF_LSM.

The first test stores a value in sys_enter and read it back in sys_exit.

The second test checks whether the kernel allows allocating task local
storage in exit_creds() (which it should not).

Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20210225234319.336131-4-songliubraving@fb.com

authored by

Song Liu and committed by
Alexei Starovoitov
1f87dcf1 bc235cdb

+165
+69
tools/testing/selftests/bpf/prog_tests/task_local_storage.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2021 Facebook */ 3 + 4 + #define _GNU_SOURCE /* See feature_test_macros(7) */ 5 + #include <unistd.h> 6 + #include <sys/syscall.h> /* For SYS_xxx definitions */ 7 + #include <sys/types.h> 8 + #include <test_progs.h> 9 + #include "task_local_storage.skel.h" 10 + #include "task_local_storage_exit_creds.skel.h" 11 + 12 + static void test_sys_enter_exit(void) 13 + { 14 + struct task_local_storage *skel; 15 + int err; 16 + 17 + skel = task_local_storage__open_and_load(); 18 + if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 19 + return; 20 + 21 + skel->bss->target_pid = syscall(SYS_gettid); 22 + 23 + err = task_local_storage__attach(skel); 24 + if (!ASSERT_OK(err, "skel_attach")) 25 + goto out; 26 + 27 + syscall(SYS_gettid); 28 + syscall(SYS_gettid); 29 + 30 + /* 3x syscalls: 1x attach and 2x gettid */ 31 + ASSERT_EQ(skel->bss->enter_cnt, 3, "enter_cnt"); 32 + ASSERT_EQ(skel->bss->exit_cnt, 3, "exit_cnt"); 33 + ASSERT_EQ(skel->bss->mismatch_cnt, 0, "mismatch_cnt"); 34 + out: 35 + task_local_storage__destroy(skel); 36 + } 37 + 38 + static void test_exit_creds(void) 39 + { 40 + struct task_local_storage_exit_creds *skel; 41 + int err; 42 + 43 + skel = task_local_storage_exit_creds__open_and_load(); 44 + if (!ASSERT_OK_PTR(skel, "skel_open_and_load")) 45 + return; 46 + 47 + err = task_local_storage_exit_creds__attach(skel); 48 + if (!ASSERT_OK(err, "skel_attach")) 49 + goto out; 50 + 51 + /* trigger at least one exit_creds() */ 52 + if (CHECK_FAIL(system("ls > /dev/null"))) 53 + goto out; 54 + 55 + /* sync rcu to make sure exit_creds() is called for "ls" */ 56 + kern_sync_rcu(); 57 + ASSERT_EQ(skel->bss->valid_ptr_count, 0, "valid_ptr_count"); 58 + ASSERT_NEQ(skel->bss->null_ptr_count, 0, "null_ptr_count"); 59 + out: 60 + task_local_storage_exit_creds__destroy(skel); 61 + } 62 + 63 + void test_task_local_storage(void) 64 + { 65 + if (test__start_subtest("sys_enter_exit")) 66 + test_sys_enter_exit(); 67 + if (test__start_subtest("exit_creds")) 68 + test_exit_creds(); 69 + }
+64
tools/testing/selftests/bpf/progs/task_local_storage.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2021 Facebook */ 3 + 4 + #include "vmlinux.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + 8 + char _license[] SEC("license") = "GPL"; 9 + 10 + struct { 11 + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); 12 + __uint(map_flags, BPF_F_NO_PREALLOC); 13 + __type(key, int); 14 + __type(value, long); 15 + } enter_id SEC(".maps"); 16 + 17 + #define MAGIC_VALUE 0xabcd1234 18 + 19 + pid_t target_pid = 0; 20 + int mismatch_cnt = 0; 21 + int enter_cnt = 0; 22 + int exit_cnt = 0; 23 + 24 + SEC("tp_btf/sys_enter") 25 + int BPF_PROG(on_enter, struct pt_regs *regs, long id) 26 + { 27 + struct task_struct *task; 28 + long *ptr; 29 + 30 + task = bpf_get_current_task_btf(); 31 + if (task->pid != target_pid) 32 + return 0; 33 + 34 + ptr = bpf_task_storage_get(&enter_id, task, 0, 35 + BPF_LOCAL_STORAGE_GET_F_CREATE); 36 + if (!ptr) 37 + return 0; 38 + 39 + __sync_fetch_and_add(&enter_cnt, 1); 40 + *ptr = MAGIC_VALUE + enter_cnt; 41 + 42 + return 0; 43 + } 44 + 45 + SEC("tp_btf/sys_exit") 46 + int BPF_PROG(on_exit, struct pt_regs *regs, long id) 47 + { 48 + struct task_struct *task; 49 + long *ptr; 50 + 51 + task = bpf_get_current_task_btf(); 52 + if (task->pid != target_pid) 53 + return 0; 54 + 55 + ptr = bpf_task_storage_get(&enter_id, task, 0, 56 + BPF_LOCAL_STORAGE_GET_F_CREATE); 57 + if (!ptr) 58 + return 0; 59 + 60 + __sync_fetch_and_add(&exit_cnt, 1); 61 + if (*ptr != MAGIC_VALUE + exit_cnt) 62 + __sync_fetch_and_add(&mismatch_cnt, 1); 63 + return 0; 64 + }
+32
tools/testing/selftests/bpf/progs/task_local_storage_exit_creds.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2021 Facebook */ 3 + 4 + #include "vmlinux.h" 5 + #include <bpf/bpf_helpers.h> 6 + #include <bpf/bpf_tracing.h> 7 + 8 + char _license[] SEC("license") = "GPL"; 9 + 10 + struct { 11 + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); 12 + __uint(map_flags, BPF_F_NO_PREALLOC); 13 + __type(key, int); 14 + __type(value, __u64); 15 + } task_storage SEC(".maps"); 16 + 17 + int valid_ptr_count = 0; 18 + int null_ptr_count = 0; 19 + 20 + SEC("fentry/exit_creds") 21 + int BPF_PROG(trace_exit_creds, struct task_struct *task) 22 + { 23 + __u64 *ptr; 24 + 25 + ptr = bpf_task_storage_get(&task_storage, task, 0, 26 + BPF_LOCAL_STORAGE_GET_F_CREATE); 27 + if (ptr) 28 + __sync_fetch_and_add(&valid_ptr_count, 1); 29 + else 30 + __sync_fetch_and_add(&null_ptr_count, 1); 31 + return 0; 32 + }