1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2021 Facebook */ 3 #include <test_progs.h> 4 #include <sys/types.h> 5 #include <unistd.h> 6 #include "find_vma.skel.h" 7 #include "find_vma_fail1.skel.h" 8 #include "find_vma_fail2.skel.h" 9 10 static void test_and_reset_skel(struct find_vma *skel, int expected_find_zero_ret, bool need_test) 11 { 12 if (need_test) { 13 ASSERT_EQ(skel->bss->found_vm_exec, 1, "found_vm_exec"); 14 ASSERT_EQ(skel->data->find_addr_ret, 0, "find_addr_ret"); 15 ASSERT_EQ(skel->data->find_zero_ret, expected_find_zero_ret, "find_zero_ret"); 16 ASSERT_OK_PTR(strstr(skel->bss->d_iname, "test_progs"), "find_test_progs"); 17 } 18 19 skel->bss->found_vm_exec = 0; 20 skel->data->find_addr_ret = -1; 21 skel->data->find_zero_ret = -1; 22 skel->bss->d_iname[0] = 0; 23 } 24 25 static int open_pe(void) 26 { 27 struct perf_event_attr attr = {0}; 28 int pfd; 29 30 /* create perf event */ 31 attr.size = sizeof(attr); 32 attr.type = PERF_TYPE_HARDWARE; 33 attr.config = PERF_COUNT_HW_CPU_CYCLES; 34 attr.freq = 1; 35 attr.sample_freq = 1000; 36 pfd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, PERF_FLAG_FD_CLOEXEC); 37 38 return pfd >= 0 ? pfd : -errno; 39 } 40 41 static bool find_vma_pe_condition(struct find_vma *skel) 42 { 43 return skel->bss->found_vm_exec == 0 || 44 skel->data->find_addr_ret != 0 || 45 skel->data->find_zero_ret == -1 || 46 strcmp(skel->bss->d_iname, "test_progs") != 0; 47 } 48 49 static void test_find_vma_pe(struct find_vma *skel) 50 { 51 struct bpf_link *link = NULL; 52 volatile int j = 0; 53 int pfd, i; 54 const int one_bn = 1000000000; 55 56 pfd = open_pe(); 57 if (pfd < 0) { 58 if (pfd == -ENOENT || pfd == -EOPNOTSUPP) { 59 printf("%s:SKIP:no PERF_COUNT_HW_CPU_CYCLES\n", __func__); 60 test__skip(); 61 goto cleanup; 62 } 63 if (!ASSERT_GE(pfd, 0, "perf_event_open")) 64 goto cleanup; 65 } 66 67 link = bpf_program__attach_perf_event(skel->progs.handle_pe, pfd); 68 if (!ASSERT_OK_PTR(link, "attach_perf_event")) 69 goto cleanup; 70 71 for (i = 0; i < one_bn && find_vma_pe_condition(skel); ++i) 72 ++j; 73 74 test_and_reset_skel(skel, -EBUSY /* in nmi, irq_work is busy */, i == one_bn); 75 cleanup: 76 bpf_link__destroy(link); 77 close(pfd); 78 } 79 80 static void test_find_vma_kprobe(struct find_vma *skel) 81 { 82 int err; 83 84 err = find_vma__attach(skel); 85 if (!ASSERT_OK(err, "get_branch_snapshot__attach")) 86 return; 87 88 getpgid(skel->bss->target_pid); 89 test_and_reset_skel(skel, -ENOENT /* could not find vma for ptr 0 */, true); 90 } 91 92 static void test_illegal_write_vma(void) 93 { 94 struct find_vma_fail1 *skel; 95 96 skel = find_vma_fail1__open_and_load(); 97 if (!ASSERT_ERR_PTR(skel, "find_vma_fail1__open_and_load")) 98 find_vma_fail1__destroy(skel); 99 } 100 101 static void test_illegal_write_task(void) 102 { 103 struct find_vma_fail2 *skel; 104 105 skel = find_vma_fail2__open_and_load(); 106 if (!ASSERT_ERR_PTR(skel, "find_vma_fail2__open_and_load")) 107 find_vma_fail2__destroy(skel); 108 } 109 110 void serial_test_find_vma(void) 111 { 112 struct find_vma *skel; 113 114 skel = find_vma__open_and_load(); 115 if (!ASSERT_OK_PTR(skel, "find_vma__open_and_load")) 116 return; 117 118 skel->bss->target_pid = getpid(); 119 skel->bss->addr = (__u64)(uintptr_t)test_find_vma_pe; 120 121 test_find_vma_pe(skel); 122 test_find_vma_kprobe(skel); 123 124 find_vma__destroy(skel); 125 test_illegal_write_vma(); 126 test_illegal_write_task(); 127 } 128