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

tools/testing/selftests/bpf: Add self-tests for new helper bpf_get_ns_current_pid_tgid.

Self tests added for new helper bpf_get_ns_current_pid_tgid

Signed-off-by: Carlos Neira <cneirabustos@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200304204157.58695-4-cneirabustos@gmail.com

authored by

Carlos Neira and committed by
Alexei Starovoitov
1c1052e0 b4490c5c

+287 -1
+1
tools/testing/selftests/bpf/.gitignore
··· 31 31 test_sysctl 32 32 test_hashmap 33 33 test_btf_dump 34 + test_current_pid_tgid_new_ns 34 35 xdping 35 36 test_cpp 36 37 *.skel.h
+2 -1
tools/testing/selftests/bpf/Makefile
··· 32 32 test_sock test_btf test_sockmap get_cgroup_id_user test_socket_cookie \ 33 33 test_cgroup_storage \ 34 34 test_netcnt test_tcpnotify_user test_sock_fields test_sysctl test_hashmap \ 35 - test_progs-no_alu32 35 + test_progs-no_alu32 \ 36 + test_current_pid_tgid_new_ns 36 37 37 38 # Also test bpf-gcc, if present 38 39 ifneq ($(BPF_GCC),)
+88
tools/testing/selftests/bpf/prog_tests/ns_current_pid_tgid.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Carlos Neira cneirabustos@gmail.com */ 3 + #include <test_progs.h> 4 + #include <sys/stat.h> 5 + #include <sys/types.h> 6 + #include <unistd.h> 7 + #include <sys/syscall.h> 8 + 9 + struct bss { 10 + __u64 dev; 11 + __u64 ino; 12 + __u64 pid_tgid; 13 + __u64 user_pid_tgid; 14 + }; 15 + 16 + void test_ns_current_pid_tgid(void) 17 + { 18 + const char *probe_name = "raw_tracepoint/sys_enter"; 19 + const char *file = "test_ns_current_pid_tgid.o"; 20 + int err, key = 0, duration = 0; 21 + struct bpf_link *link = NULL; 22 + struct bpf_program *prog; 23 + struct bpf_map *bss_map; 24 + struct bpf_object *obj; 25 + struct bss bss; 26 + struct stat st; 27 + __u64 id; 28 + 29 + obj = bpf_object__open_file(file, NULL); 30 + if (CHECK(IS_ERR(obj), "obj_open", "err %ld\n", PTR_ERR(obj))) 31 + return; 32 + 33 + err = bpf_object__load(obj); 34 + if (CHECK(err, "obj_load", "err %d errno %d\n", err, errno)) 35 + goto cleanup; 36 + 37 + bss_map = bpf_object__find_map_by_name(obj, "test_ns_.bss"); 38 + if (CHECK(!bss_map, "find_bss_map", "failed\n")) 39 + goto cleanup; 40 + 41 + prog = bpf_object__find_program_by_title(obj, probe_name); 42 + if (CHECK(!prog, "find_prog", "prog '%s' not found\n", 43 + probe_name)) 44 + goto cleanup; 45 + 46 + memset(&bss, 0, sizeof(bss)); 47 + pid_t tid = syscall(SYS_gettid); 48 + pid_t pid = getpid(); 49 + 50 + id = (__u64) tid << 32 | pid; 51 + bss.user_pid_tgid = id; 52 + 53 + if (CHECK_FAIL(stat("/proc/self/ns/pid", &st))) { 54 + perror("Failed to stat /proc/self/ns/pid"); 55 + goto cleanup; 56 + } 57 + 58 + bss.dev = st.st_dev; 59 + bss.ino = st.st_ino; 60 + 61 + err = bpf_map_update_elem(bpf_map__fd(bss_map), &key, &bss, 0); 62 + if (CHECK(err, "setting_bss", "failed to set bss : %d\n", err)) 63 + goto cleanup; 64 + 65 + link = bpf_program__attach_raw_tracepoint(prog, "sys_enter"); 66 + if (CHECK(IS_ERR(link), "attach_raw_tp", "err %ld\n", 67 + PTR_ERR(link))) { 68 + link = NULL; 69 + goto cleanup; 70 + } 71 + 72 + /* trigger some syscalls */ 73 + usleep(1); 74 + 75 + err = bpf_map_lookup_elem(bpf_map__fd(bss_map), &key, &bss); 76 + if (CHECK(err, "set_bss", "failed to get bss : %d\n", err)) 77 + goto cleanup; 78 + 79 + if (CHECK(id != bss.pid_tgid, "Compare user pid/tgid vs. bpf pid/tgid", 80 + "User pid/tgid %llu BPF pid/tgid %llu\n", id, bss.pid_tgid)) 81 + goto cleanup; 82 + cleanup: 83 + if (!link) { 84 + bpf_link__destroy(link); 85 + link = NULL; 86 + } 87 + bpf_object__close(obj); 88 + }
+37
tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2019 Carlos Neira cneirabustos@gmail.com */ 3 + 4 + #include <linux/bpf.h> 5 + #include <stdint.h> 6 + #include <bpf/bpf_helpers.h> 7 + 8 + static volatile struct { 9 + __u64 dev; 10 + __u64 ino; 11 + __u64 pid_tgid; 12 + __u64 user_pid_tgid; 13 + } res; 14 + 15 + SEC("raw_tracepoint/sys_enter") 16 + int trace(void *ctx) 17 + { 18 + __u64 ns_pid_tgid, expected_pid; 19 + struct bpf_pidns_info nsdata; 20 + __u32 key = 0; 21 + 22 + if (bpf_get_ns_current_pid_tgid(res.dev, res.ino, &nsdata, 23 + sizeof(struct bpf_pidns_info))) 24 + return 0; 25 + 26 + ns_pid_tgid = (__u64)nsdata.tgid << 32 | nsdata.pid; 27 + expected_pid = res.user_pid_tgid; 28 + 29 + if (expected_pid != ns_pid_tgid) 30 + return 0; 31 + 32 + res.pid_tgid = ns_pid_tgid; 33 + 34 + return 0; 35 + } 36 + 37 + char _license[] SEC("license") = "GPL";
+159
tools/testing/selftests/bpf/test_current_pid_tgid_new_ns.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2020 Carlos Neira cneirabustos@gmail.com */ 3 + #define _GNU_SOURCE 4 + #include <sys/stat.h> 5 + #include <sys/types.h> 6 + #include <unistd.h> 7 + #include <sys/syscall.h> 8 + #include <sched.h> 9 + #include <sys/wait.h> 10 + #include <sys/mount.h> 11 + #include "test_progs.h" 12 + 13 + #define CHECK_NEWNS(condition, tag, format...) ({ \ 14 + int __ret = !!(condition); \ 15 + if (__ret) { \ 16 + printf("%s:FAIL:%s ", __func__, tag); \ 17 + printf(format); \ 18 + } else { \ 19 + printf("%s:PASS:%s\n", __func__, tag); \ 20 + } \ 21 + __ret; \ 22 + }) 23 + 24 + struct bss { 25 + __u64 dev; 26 + __u64 ino; 27 + __u64 pid_tgid; 28 + __u64 user_pid_tgid; 29 + }; 30 + 31 + int main(int argc, char **argv) 32 + { 33 + pid_t pid; 34 + int exit_code = 1; 35 + struct stat st; 36 + 37 + printf("Testing bpf_get_ns_current_pid_tgid helper in new ns\n"); 38 + 39 + if (stat("/proc/self/ns/pid", &st)) { 40 + perror("stat failed on /proc/self/ns/pid ns\n"); 41 + printf("%s:FAILED\n", argv[0]); 42 + return exit_code; 43 + } 44 + 45 + if (CHECK_NEWNS(unshare(CLONE_NEWPID | CLONE_NEWNS), 46 + "unshare CLONE_NEWPID | CLONE_NEWNS", "error errno=%d\n", errno)) 47 + return exit_code; 48 + 49 + pid = fork(); 50 + if (pid == -1) { 51 + perror("Fork() failed\n"); 52 + printf("%s:FAILED\n", argv[0]); 53 + return exit_code; 54 + } 55 + 56 + if (pid > 0) { 57 + int status; 58 + 59 + usleep(5); 60 + waitpid(pid, &status, 0); 61 + return 0; 62 + } else { 63 + 64 + pid = fork(); 65 + if (pid == -1) { 66 + perror("Fork() failed\n"); 67 + printf("%s:FAILED\n", argv[0]); 68 + return exit_code; 69 + } 70 + 71 + if (pid > 0) { 72 + int status; 73 + waitpid(pid, &status, 0); 74 + return 0; 75 + } else { 76 + if (CHECK_NEWNS(mount("none", "/proc", NULL, MS_PRIVATE|MS_REC, NULL), 77 + "Unmounting proc", "Cannot umount proc! errno=%d\n", errno)) 78 + return exit_code; 79 + 80 + if (CHECK_NEWNS(mount("proc", "/proc", "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL), 81 + "Mounting proc", "Cannot mount proc! errno=%d\n", errno)) 82 + return exit_code; 83 + 84 + const char *probe_name = "raw_tracepoint/sys_enter"; 85 + const char *file = "test_ns_current_pid_tgid.o"; 86 + struct bpf_link *link = NULL; 87 + struct bpf_program *prog; 88 + struct bpf_map *bss_map; 89 + struct bpf_object *obj; 90 + int exit_code = 1; 91 + int err, key = 0; 92 + struct bss bss; 93 + struct stat st; 94 + __u64 id; 95 + 96 + obj = bpf_object__open_file(file, NULL); 97 + if (CHECK_NEWNS(IS_ERR(obj), "obj_open", "err %ld\n", PTR_ERR(obj))) 98 + return exit_code; 99 + 100 + err = bpf_object__load(obj); 101 + if (CHECK_NEWNS(err, "obj_load", "err %d errno %d\n", err, errno)) 102 + goto cleanup; 103 + 104 + bss_map = bpf_object__find_map_by_name(obj, "test_ns_.bss"); 105 + if (CHECK_NEWNS(!bss_map, "find_bss_map", "failed\n")) 106 + goto cleanup; 107 + 108 + prog = bpf_object__find_program_by_title(obj, probe_name); 109 + if (CHECK_NEWNS(!prog, "find_prog", "prog '%s' not found\n", 110 + probe_name)) 111 + goto cleanup; 112 + 113 + memset(&bss, 0, sizeof(bss)); 114 + pid_t tid = syscall(SYS_gettid); 115 + pid_t pid = getpid(); 116 + 117 + id = (__u64) tid << 32 | pid; 118 + bss.user_pid_tgid = id; 119 + 120 + if (CHECK_NEWNS(stat("/proc/self/ns/pid", &st), 121 + "stat new ns", "Failed to stat /proc/self/ns/pid errno=%d\n", errno)) 122 + goto cleanup; 123 + 124 + bss.dev = st.st_dev; 125 + bss.ino = st.st_ino; 126 + 127 + err = bpf_map_update_elem(bpf_map__fd(bss_map), &key, &bss, 0); 128 + if (CHECK_NEWNS(err, "setting_bss", "failed to set bss : %d\n", err)) 129 + goto cleanup; 130 + 131 + link = bpf_program__attach_raw_tracepoint(prog, "sys_enter"); 132 + if (CHECK_NEWNS(IS_ERR(link), "attach_raw_tp", "err %ld\n", 133 + PTR_ERR(link))) { 134 + link = NULL; 135 + goto cleanup; 136 + } 137 + 138 + /* trigger some syscalls */ 139 + usleep(1); 140 + 141 + err = bpf_map_lookup_elem(bpf_map__fd(bss_map), &key, &bss); 142 + if (CHECK_NEWNS(err, "set_bss", "failed to get bss : %d\n", err)) 143 + goto cleanup; 144 + 145 + if (CHECK_NEWNS(id != bss.pid_tgid, "Compare user pid/tgid vs. bpf pid/tgid", 146 + "User pid/tgid %llu BPF pid/tgid %llu\n", id, bss.pid_tgid)) 147 + goto cleanup; 148 + 149 + exit_code = 0; 150 + printf("%s:PASS\n", argv[0]); 151 + cleanup: 152 + if (!link) { 153 + bpf_link__destroy(link); 154 + link = NULL; 155 + } 156 + bpf_object__close(obj); 157 + } 158 + } 159 + }