1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <test_progs.h> 4 5 #ifdef __x86_64__ 6 7 #include <unistd.h> 8 #include <asm/ptrace.h> 9 #include <linux/compiler.h> 10 #include <linux/stringify.h> 11 #include <sys/wait.h> 12 #include <sys/syscall.h> 13 #include <sys/prctl.h> 14 #include <asm/prctl.h> 15 #include "uprobe_syscall.skel.h" 16 #include "uprobe_syscall_executed.skel.h" 17 18 __naked unsigned long uretprobe_regs_trigger(void) 19 { 20 asm volatile ( 21 "movq $0xdeadbeef, %rax\n" 22 "ret\n" 23 ); 24 } 25 26 __naked void uretprobe_regs(struct pt_regs *before, struct pt_regs *after) 27 { 28 asm volatile ( 29 "movq %r15, 0(%rdi)\n" 30 "movq %r14, 8(%rdi)\n" 31 "movq %r13, 16(%rdi)\n" 32 "movq %r12, 24(%rdi)\n" 33 "movq %rbp, 32(%rdi)\n" 34 "movq %rbx, 40(%rdi)\n" 35 "movq %r11, 48(%rdi)\n" 36 "movq %r10, 56(%rdi)\n" 37 "movq %r9, 64(%rdi)\n" 38 "movq %r8, 72(%rdi)\n" 39 "movq %rax, 80(%rdi)\n" 40 "movq %rcx, 88(%rdi)\n" 41 "movq %rdx, 96(%rdi)\n" 42 "movq %rsi, 104(%rdi)\n" 43 "movq %rdi, 112(%rdi)\n" 44 "movq $0, 120(%rdi)\n" /* orig_rax */ 45 "movq $0, 128(%rdi)\n" /* rip */ 46 "movq $0, 136(%rdi)\n" /* cs */ 47 "pushf\n" 48 "pop %rax\n" 49 "movq %rax, 144(%rdi)\n" /* eflags */ 50 "movq %rsp, 152(%rdi)\n" /* rsp */ 51 "movq $0, 160(%rdi)\n" /* ss */ 52 53 /* save 2nd argument */ 54 "pushq %rsi\n" 55 "call uretprobe_regs_trigger\n" 56 57 /* save return value and load 2nd argument pointer to rax */ 58 "pushq %rax\n" 59 "movq 8(%rsp), %rax\n" 60 61 "movq %r15, 0(%rax)\n" 62 "movq %r14, 8(%rax)\n" 63 "movq %r13, 16(%rax)\n" 64 "movq %r12, 24(%rax)\n" 65 "movq %rbp, 32(%rax)\n" 66 "movq %rbx, 40(%rax)\n" 67 "movq %r11, 48(%rax)\n" 68 "movq %r10, 56(%rax)\n" 69 "movq %r9, 64(%rax)\n" 70 "movq %r8, 72(%rax)\n" 71 "movq %rcx, 88(%rax)\n" 72 "movq %rdx, 96(%rax)\n" 73 "movq %rsi, 104(%rax)\n" 74 "movq %rdi, 112(%rax)\n" 75 "movq $0, 120(%rax)\n" /* orig_rax */ 76 "movq $0, 128(%rax)\n" /* rip */ 77 "movq $0, 136(%rax)\n" /* cs */ 78 79 /* restore return value and 2nd argument */ 80 "pop %rax\n" 81 "pop %rsi\n" 82 83 "movq %rax, 80(%rsi)\n" 84 85 "pushf\n" 86 "pop %rax\n" 87 88 "movq %rax, 144(%rsi)\n" /* eflags */ 89 "movq %rsp, 152(%rsi)\n" /* rsp */ 90 "movq $0, 160(%rsi)\n" /* ss */ 91 "ret\n" 92 ); 93 } 94 95 static void test_uretprobe_regs_equal(void) 96 { 97 struct uprobe_syscall *skel = NULL; 98 struct pt_regs before = {}, after = {}; 99 unsigned long *pb = (unsigned long *) &before; 100 unsigned long *pa = (unsigned long *) &after; 101 unsigned long *pp; 102 unsigned int i, cnt; 103 int err; 104 105 skel = uprobe_syscall__open_and_load(); 106 if (!ASSERT_OK_PTR(skel, "uprobe_syscall__open_and_load")) 107 goto cleanup; 108 109 err = uprobe_syscall__attach(skel); 110 if (!ASSERT_OK(err, "uprobe_syscall__attach")) 111 goto cleanup; 112 113 uretprobe_regs(&before, &after); 114 115 pp = (unsigned long *) &skel->bss->regs; 116 cnt = sizeof(before)/sizeof(*pb); 117 118 for (i = 0; i < cnt; i++) { 119 unsigned int offset = i * sizeof(unsigned long); 120 121 /* 122 * Check register before and after uretprobe_regs_trigger call 123 * that triggers the uretprobe. 124 */ 125 switch (offset) { 126 case offsetof(struct pt_regs, rax): 127 ASSERT_EQ(pa[i], 0xdeadbeef, "return value"); 128 break; 129 default: 130 if (!ASSERT_EQ(pb[i], pa[i], "register before-after value check")) 131 fprintf(stdout, "failed register offset %u\n", offset); 132 } 133 134 /* 135 * Check register seen from bpf program and register after 136 * uretprobe_regs_trigger call 137 */ 138 switch (offset) { 139 /* 140 * These values will be different (not set in uretprobe_regs), 141 * we don't care. 142 */ 143 case offsetof(struct pt_regs, orig_rax): 144 case offsetof(struct pt_regs, rip): 145 case offsetof(struct pt_regs, cs): 146 case offsetof(struct pt_regs, rsp): 147 case offsetof(struct pt_regs, ss): 148 break; 149 default: 150 if (!ASSERT_EQ(pp[i], pa[i], "register prog-after value check")) 151 fprintf(stdout, "failed register offset %u\n", offset); 152 } 153 } 154 155 cleanup: 156 uprobe_syscall__destroy(skel); 157 } 158 159 #define BPF_TESTMOD_UPROBE_TEST_FILE "/sys/kernel/bpf_testmod_uprobe" 160 161 static int write_bpf_testmod_uprobe(unsigned long offset) 162 { 163 size_t n, ret; 164 char buf[30]; 165 int fd; 166 167 n = sprintf(buf, "%lu", offset); 168 169 fd = open(BPF_TESTMOD_UPROBE_TEST_FILE, O_WRONLY); 170 if (fd < 0) 171 return -errno; 172 173 ret = write(fd, buf, n); 174 close(fd); 175 return ret != n ? (int) ret : 0; 176 } 177 178 static void test_uretprobe_regs_change(void) 179 { 180 struct pt_regs before = {}, after = {}; 181 unsigned long *pb = (unsigned long *) &before; 182 unsigned long *pa = (unsigned long *) &after; 183 unsigned long cnt = sizeof(before)/sizeof(*pb); 184 unsigned int i, err, offset; 185 186 offset = get_uprobe_offset(uretprobe_regs_trigger); 187 188 err = write_bpf_testmod_uprobe(offset); 189 if (!ASSERT_OK(err, "register_uprobe")) 190 return; 191 192 uretprobe_regs(&before, &after); 193 194 err = write_bpf_testmod_uprobe(0); 195 if (!ASSERT_OK(err, "unregister_uprobe")) 196 return; 197 198 for (i = 0; i < cnt; i++) { 199 unsigned int offset = i * sizeof(unsigned long); 200 201 switch (offset) { 202 case offsetof(struct pt_regs, rax): 203 ASSERT_EQ(pa[i], 0x12345678deadbeef, "rax"); 204 break; 205 case offsetof(struct pt_regs, rcx): 206 ASSERT_EQ(pa[i], 0x87654321feebdaed, "rcx"); 207 break; 208 case offsetof(struct pt_regs, r11): 209 ASSERT_EQ(pa[i], (__u64) -1, "r11"); 210 break; 211 default: 212 if (!ASSERT_EQ(pa[i], pb[i], "register before-after value check")) 213 fprintf(stdout, "failed register offset %u\n", offset); 214 } 215 } 216 } 217 218 #ifndef __NR_uretprobe 219 #define __NR_uretprobe 335 220 #endif 221 222 __naked unsigned long uretprobe_syscall_call_1(void) 223 { 224 /* 225 * Pretend we are uretprobe trampoline to trigger the return 226 * probe invocation in order to verify we get SIGILL. 227 */ 228 asm volatile ( 229 "pushq %rax\n" 230 "pushq %rcx\n" 231 "pushq %r11\n" 232 "movq $" __stringify(__NR_uretprobe) ", %rax\n" 233 "syscall\n" 234 "popq %r11\n" 235 "popq %rcx\n" 236 "retq\n" 237 ); 238 } 239 240 __naked unsigned long uretprobe_syscall_call(void) 241 { 242 asm volatile ( 243 "call uretprobe_syscall_call_1\n" 244 "retq\n" 245 ); 246 } 247 248 static void test_uretprobe_syscall_call(void) 249 { 250 LIBBPF_OPTS(bpf_uprobe_multi_opts, opts, 251 .retprobe = true, 252 ); 253 struct uprobe_syscall_executed *skel; 254 int pid, status, err, go[2], c; 255 256 if (!ASSERT_OK(pipe(go), "pipe")) 257 return; 258 259 skel = uprobe_syscall_executed__open_and_load(); 260 if (!ASSERT_OK_PTR(skel, "uprobe_syscall_executed__open_and_load")) 261 goto cleanup; 262 263 pid = fork(); 264 if (!ASSERT_GE(pid, 0, "fork")) 265 goto cleanup; 266 267 /* child */ 268 if (pid == 0) { 269 close(go[1]); 270 271 /* wait for parent's kick */ 272 err = read(go[0], &c, 1); 273 if (err != 1) 274 exit(-1); 275 276 uretprobe_syscall_call(); 277 _exit(0); 278 } 279 280 skel->links.test = bpf_program__attach_uprobe_multi(skel->progs.test, pid, 281 "/proc/self/exe", 282 "uretprobe_syscall_call", &opts); 283 if (!ASSERT_OK_PTR(skel->links.test, "bpf_program__attach_uprobe_multi")) 284 goto cleanup; 285 286 /* kick the child */ 287 write(go[1], &c, 1); 288 err = waitpid(pid, &status, 0); 289 ASSERT_EQ(err, pid, "waitpid"); 290 291 /* verify the child got killed with SIGILL */ 292 ASSERT_EQ(WIFSIGNALED(status), 1, "WIFSIGNALED"); 293 ASSERT_EQ(WTERMSIG(status), SIGILL, "WTERMSIG"); 294 295 /* verify the uretprobe program wasn't called */ 296 ASSERT_EQ(skel->bss->executed, 0, "executed"); 297 298 cleanup: 299 uprobe_syscall_executed__destroy(skel); 300 close(go[1]); 301 close(go[0]); 302 } 303 304 /* 305 * Borrowed from tools/testing/selftests/x86/test_shadow_stack.c. 306 * 307 * For use in inline enablement of shadow stack. 308 * 309 * The program can't return from the point where shadow stack gets enabled 310 * because there will be no address on the shadow stack. So it can't use 311 * syscall() for enablement, since it is a function. 312 * 313 * Based on code from nolibc.h. Keep a copy here because this can't pull 314 * in all of nolibc.h. 315 */ 316 #define ARCH_PRCTL(arg1, arg2) \ 317 ({ \ 318 long _ret; \ 319 register long _num asm("eax") = __NR_arch_prctl; \ 320 register long _arg1 asm("rdi") = (long)(arg1); \ 321 register long _arg2 asm("rsi") = (long)(arg2); \ 322 \ 323 asm volatile ( \ 324 "syscall\n" \ 325 : "=a"(_ret) \ 326 : "r"(_arg1), "r"(_arg2), \ 327 "0"(_num) \ 328 : "rcx", "r11", "memory", "cc" \ 329 ); \ 330 _ret; \ 331 }) 332 333 #ifndef ARCH_SHSTK_ENABLE 334 #define ARCH_SHSTK_ENABLE 0x5001 335 #define ARCH_SHSTK_DISABLE 0x5002 336 #define ARCH_SHSTK_SHSTK (1ULL << 0) 337 #endif 338 339 static void test_uretprobe_shadow_stack(void) 340 { 341 if (ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK)) { 342 test__skip(); 343 return; 344 } 345 346 /* Run all of the uretprobe tests. */ 347 test_uretprobe_regs_equal(); 348 test_uretprobe_regs_change(); 349 test_uretprobe_syscall_call(); 350 351 ARCH_PRCTL(ARCH_SHSTK_DISABLE, ARCH_SHSTK_SHSTK); 352 } 353 #else 354 static void test_uretprobe_regs_equal(void) 355 { 356 test__skip(); 357 } 358 359 static void test_uretprobe_regs_change(void) 360 { 361 test__skip(); 362 } 363 364 static void test_uretprobe_syscall_call(void) 365 { 366 test__skip(); 367 } 368 369 static void test_uretprobe_shadow_stack(void) 370 { 371 test__skip(); 372 } 373 #endif 374 375 void test_uprobe_syscall(void) 376 { 377 if (test__start_subtest("uretprobe_regs_equal")) 378 test_uretprobe_regs_equal(); 379 if (test__start_subtest("uretprobe_regs_change")) 380 test_uretprobe_regs_change(); 381 if (test__start_subtest("uretprobe_syscall_call")) 382 test_uretprobe_syscall_call(); 383 if (test__start_subtest("uretprobe_shadow_stack")) 384 test_uretprobe_shadow_stack(); 385 } 386