1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020 Carlos Neira cneirabustos@gmail.com */ 3 4 #define _GNU_SOURCE 5 #include <test_progs.h> 6 #include "test_ns_current_pid_tgid.skel.h" 7 #include <sys/stat.h> 8 #include <sys/types.h> 9 #include <unistd.h> 10 #include <sys/syscall.h> 11 #include <sched.h> 12 #include <sys/wait.h> 13 #include <sys/mount.h> 14 #include <fcntl.h> 15 #include "network_helpers.h" 16 17 #define STACK_SIZE (1024 * 1024) 18 static char child_stack[STACK_SIZE]; 19 20 static int get_pid_tgid(pid_t *pid, pid_t *tgid, 21 struct test_ns_current_pid_tgid__bss *bss) 22 { 23 struct stat st; 24 int err; 25 26 *pid = sys_gettid(); 27 *tgid = getpid(); 28 29 err = stat("/proc/self/ns/pid", &st); 30 if (!ASSERT_OK(err, "stat /proc/self/ns/pid")) 31 return err; 32 33 bss->dev = st.st_dev; 34 bss->ino = st.st_ino; 35 bss->user_pid = 0; 36 bss->user_tgid = 0; 37 return 0; 38 } 39 40 static int test_current_pid_tgid_tp(void *args) 41 { 42 struct test_ns_current_pid_tgid__bss *bss; 43 struct test_ns_current_pid_tgid *skel; 44 int ret = -1, err; 45 pid_t tgid, pid; 46 47 skel = test_ns_current_pid_tgid__open(); 48 if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open")) 49 return ret; 50 51 bpf_program__set_autoload(skel->progs.tp_handler, true); 52 53 err = test_ns_current_pid_tgid__load(skel); 54 if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load")) 55 goto cleanup; 56 57 bss = skel->bss; 58 if (get_pid_tgid(&pid, &tgid, bss)) 59 goto cleanup; 60 61 err = test_ns_current_pid_tgid__attach(skel); 62 if (!ASSERT_OK(err, "test_ns_current_pid_tgid__attach")) 63 goto cleanup; 64 65 /* trigger tracepoint */ 66 usleep(1); 67 if (!ASSERT_EQ(bss->user_pid, pid, "pid")) 68 goto cleanup; 69 if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid")) 70 goto cleanup; 71 ret = 0; 72 73 cleanup: 74 test_ns_current_pid_tgid__destroy(skel); 75 return ret; 76 } 77 78 static int test_current_pid_tgid_cgrp(void *args) 79 { 80 struct test_ns_current_pid_tgid__bss *bss; 81 struct test_ns_current_pid_tgid *skel; 82 int server_fd = -1, ret = -1, err; 83 int cgroup_fd = *(int *)args; 84 pid_t tgid, pid; 85 86 skel = test_ns_current_pid_tgid__open(); 87 if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open")) 88 return ret; 89 90 bpf_program__set_autoload(skel->progs.cgroup_bind4, true); 91 92 err = test_ns_current_pid_tgid__load(skel); 93 if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load")) 94 goto cleanup; 95 96 bss = skel->bss; 97 if (get_pid_tgid(&pid, &tgid, bss)) 98 goto cleanup; 99 100 skel->links.cgroup_bind4 = bpf_program__attach_cgroup( 101 skel->progs.cgroup_bind4, cgroup_fd); 102 if (!ASSERT_OK_PTR(skel->links.cgroup_bind4, "bpf_program__attach_cgroup")) 103 goto cleanup; 104 105 server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0); 106 if (!ASSERT_GE(server_fd, 0, "start_server")) 107 goto cleanup; 108 109 if (!ASSERT_EQ(bss->user_pid, pid, "pid")) 110 goto cleanup; 111 if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid")) 112 goto cleanup; 113 ret = 0; 114 115 cleanup: 116 if (server_fd >= 0) 117 close(server_fd); 118 test_ns_current_pid_tgid__destroy(skel); 119 return ret; 120 } 121 122 static int test_current_pid_tgid_sk_msg(void *args) 123 { 124 int verdict, map, server_fd = -1, client_fd = -1; 125 struct test_ns_current_pid_tgid__bss *bss; 126 static const char send_msg[] = "message"; 127 struct test_ns_current_pid_tgid *skel; 128 int ret = -1, err, key = 0; 129 pid_t tgid, pid; 130 131 skel = test_ns_current_pid_tgid__open(); 132 if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open")) 133 return ret; 134 135 bpf_program__set_autoload(skel->progs.sk_msg, true); 136 137 err = test_ns_current_pid_tgid__load(skel); 138 if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load")) 139 goto cleanup; 140 141 bss = skel->bss; 142 if (get_pid_tgid(&pid, &tgid, skel->bss)) 143 goto cleanup; 144 145 verdict = bpf_program__fd(skel->progs.sk_msg); 146 map = bpf_map__fd(skel->maps.sock_map); 147 err = bpf_prog_attach(verdict, map, BPF_SK_MSG_VERDICT, 0); 148 if (!ASSERT_OK(err, "prog_attach")) 149 goto cleanup; 150 151 server_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0); 152 if (!ASSERT_GE(server_fd, 0, "start_server")) 153 goto cleanup; 154 155 client_fd = connect_to_fd(server_fd, 0); 156 if (!ASSERT_GE(client_fd, 0, "connect_to_fd")) 157 goto cleanup; 158 159 err = bpf_map_update_elem(map, &key, &client_fd, BPF_ANY); 160 if (!ASSERT_OK(err, "bpf_map_update_elem")) 161 goto cleanup; 162 163 err = send(client_fd, send_msg, sizeof(send_msg), 0); 164 if (!ASSERT_EQ(err, sizeof(send_msg), "send(msg)")) 165 goto cleanup; 166 167 if (!ASSERT_EQ(bss->user_pid, pid, "pid")) 168 goto cleanup; 169 if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid")) 170 goto cleanup; 171 ret = 0; 172 173 cleanup: 174 if (server_fd >= 0) 175 close(server_fd); 176 if (client_fd >= 0) 177 close(client_fd); 178 test_ns_current_pid_tgid__destroy(skel); 179 return ret; 180 } 181 182 static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg) 183 { 184 int wstatus; 185 pid_t cpid; 186 187 /* Create a process in a new namespace, this process 188 * will be the init process of this new namespace hence will be pid 1. 189 */ 190 cpid = clone(fn, child_stack + STACK_SIZE, 191 CLONE_NEWPID | SIGCHLD, arg); 192 193 if (!ASSERT_NEQ(cpid, -1, "clone")) 194 return; 195 196 if (!ASSERT_NEQ(waitpid(cpid, &wstatus, 0), -1, "waitpid")) 197 return; 198 199 if (!ASSERT_OK(WEXITSTATUS(wstatus), "newns_pidtgid")) 200 return; 201 } 202 203 static void test_in_netns(int (*fn)(void *), void *arg) 204 { 205 struct nstoken *nstoken = NULL; 206 207 SYS(cleanup, "ip netns add ns_current_pid_tgid"); 208 SYS(cleanup, "ip -net ns_current_pid_tgid link set dev lo up"); 209 210 nstoken = open_netns("ns_current_pid_tgid"); 211 if (!ASSERT_OK_PTR(nstoken, "open_netns")) 212 goto cleanup; 213 214 test_ns_current_pid_tgid_new_ns(fn, arg); 215 216 cleanup: 217 if (nstoken) 218 close_netns(nstoken); 219 SYS_NOFAIL("ip netns del ns_current_pid_tgid"); 220 } 221 222 /* TODO: use a different tracepoint */ 223 void serial_test_ns_current_pid_tgid(void) 224 { 225 if (test__start_subtest("root_ns_tp")) 226 test_current_pid_tgid_tp(NULL); 227 if (test__start_subtest("new_ns_tp")) 228 test_ns_current_pid_tgid_new_ns(test_current_pid_tgid_tp, NULL); 229 if (test__start_subtest("new_ns_cgrp")) { 230 int cgroup_fd = -1; 231 232 cgroup_fd = test__join_cgroup("/sock_addr"); 233 if (ASSERT_GE(cgroup_fd, 0, "join_cgroup")) { 234 test_in_netns(test_current_pid_tgid_cgrp, &cgroup_fd); 235 close(cgroup_fd); 236 } 237 } 238 if (test__start_subtest("new_ns_sk_msg")) 239 test_in_netns(test_current_pid_tgid_sk_msg, NULL); 240 } 241