1 // SPDX-License-Identifier: GPL-2.0 2 /* Copyright (c) 2020 Facebook */ 3 4 #include <test_progs.h> 5 #include <stdbool.h> 6 #include "test_module_attach.skel.h" 7 #include "testing_helpers.h" 8 9 static const char * const read_tests[] = { 10 "handle_raw_tp", 11 "handle_tp_btf", 12 "handle_fentry", 13 "handle_fentry_explicit", 14 "handle_fmod_ret", 15 }; 16 17 static const char * const detach_tests[] = { 18 "handle_fentry", 19 "handle_fexit", 20 "kprobe_multi", 21 }; 22 23 static const int READ_SZ = 456; 24 static const int WRITE_SZ = 457; 25 26 static int trigger_module_test_writable(int *val) 27 { 28 int fd, err; 29 char buf[65]; 30 ssize_t rd; 31 32 fd = open(BPF_TESTMOD_TEST_FILE, O_RDONLY); 33 err = -errno; 34 if (!ASSERT_GE(fd, 0, "testmode_file_open")) 35 return err; 36 37 rd = read(fd, buf, sizeof(buf) - 1); 38 err = -errno; 39 if (!ASSERT_GT(rd, 0, "testmod_file_rd_val")) { 40 close(fd); 41 return err; 42 } 43 44 buf[rd] = '\0'; 45 *val = strtol(buf, NULL, 0); 46 close(fd); 47 48 return 0; 49 } 50 51 static void test_module_attach_prog(const char *prog_name, int sz, 52 const char *attach_target, int ret) 53 { 54 struct test_module_attach *skel; 55 struct bpf_program *prog; 56 int err; 57 58 skel = test_module_attach__open(); 59 if (!ASSERT_OK_PTR(skel, "module_attach open")) 60 return; 61 62 prog = bpf_object__find_program_by_name(skel->obj, prog_name); 63 if (!ASSERT_OK_PTR(prog, "module_attach find_program")) 64 goto cleanup; 65 bpf_program__set_autoload(prog, true); 66 67 if (attach_target) { 68 err = bpf_program__set_attach_target(prog, 0, attach_target); 69 if (!ASSERT_OK(err, attach_target)) 70 goto cleanup; 71 } 72 73 err = test_module_attach__load(skel); 74 if (!ASSERT_OK(err, "module_attach load")) 75 goto cleanup; 76 77 err = test_module_attach__attach(skel); 78 if (!ASSERT_OK(err, "module_attach attach")) 79 goto cleanup; 80 81 if (sz) { 82 /* trigger both read and write though each test uses only one */ 83 ASSERT_OK(trigger_module_test_read(sz), "trigger_read"); 84 ASSERT_OK(trigger_module_test_write(sz), "trigger_write"); 85 86 ASSERT_EQ(skel->bss->sz, sz, prog_name); 87 } 88 89 if (ret) 90 ASSERT_EQ(skel->bss->retval, ret, "ret"); 91 cleanup: 92 test_module_attach__destroy(skel); 93 } 94 95 static void test_module_attach_writable(void) 96 { 97 struct test_module_attach__bss *bss; 98 struct test_module_attach *skel; 99 int writable_val = 0; 100 int err; 101 102 skel = test_module_attach__open(); 103 if (!ASSERT_OK_PTR(skel, "module_attach open")) 104 return; 105 106 bpf_program__set_autoload(skel->progs.handle_raw_tp_writable_bare, true); 107 108 err = test_module_attach__load(skel); 109 if (!ASSERT_OK(err, "module_attach load")) 110 goto cleanup; 111 112 bss = skel->bss; 113 114 err = test_module_attach__attach(skel); 115 if (!ASSERT_OK(err, "module_attach attach")) 116 goto cleanup; 117 118 bss->raw_tp_writable_bare_early_ret = true; 119 bss->raw_tp_writable_bare_out_val = 0xf1f2f3f4; 120 ASSERT_OK(trigger_module_test_writable(&writable_val), 121 "trigger_writable"); 122 ASSERT_EQ(bss->raw_tp_writable_bare_in_val, 1024, "writable_test_in"); 123 ASSERT_EQ(bss->raw_tp_writable_bare_out_val, writable_val, 124 "writable_test_out"); 125 cleanup: 126 test_module_attach__destroy(skel); 127 } 128 129 static void test_module_attach_detach(const char *prog_name) 130 { 131 struct test_module_attach *skel; 132 struct bpf_program *prog; 133 struct bpf_link *link; 134 int err; 135 136 skel = test_module_attach__open(); 137 if (!ASSERT_OK_PTR(skel, "module_attach open")) 138 return; 139 140 prog = bpf_object__find_program_by_name(skel->obj, prog_name); 141 if (!ASSERT_OK_PTR(prog, "module_attach find_program")) 142 goto cleanup; 143 bpf_program__set_autoload(prog, true); 144 145 err = test_module_attach__load(skel); 146 if (!ASSERT_OK(err, "module_attach load")) 147 goto cleanup; 148 149 /* attach and make sure it gets module reference */ 150 link = bpf_program__attach(prog); 151 if (!ASSERT_OK_PTR(link, "module_attach attach")) 152 goto cleanup; 153 154 ASSERT_ERR(try_unload_module("bpf_testmod", 1, false), "try_unload_module"); 155 bpf_link__destroy(link); 156 cleanup: 157 test_module_attach__destroy(skel); 158 } 159 160 void test_module_attach(void) 161 { 162 int i; 163 164 for (i = 0; i < ARRAY_SIZE(read_tests); i++) { 165 if (!test__start_subtest(read_tests[i])) 166 continue; 167 test_module_attach_prog(read_tests[i], READ_SZ, NULL, 0); 168 } 169 if (test__start_subtest("handle_raw_tp_bare")) 170 test_module_attach_prog("handle_raw_tp_bare", WRITE_SZ, NULL, 0); 171 if (test__start_subtest("handle_raw_tp_writable_bare")) 172 test_module_attach_writable(); 173 if (test__start_subtest("handle_fentry_manual")) { 174 test_module_attach_prog("handle_fentry_manual", READ_SZ, 175 "bpf_testmod_test_read", 0); 176 } 177 if (test__start_subtest("handle_fentry_explicit_manual")) { 178 test_module_attach_prog("handle_fentry_explicit_manual", 179 READ_SZ, 180 "bpf_testmod:bpf_testmod_test_read", 0); 181 } 182 if (test__start_subtest("handle_fexit")) 183 test_module_attach_prog("handle_fexit", READ_SZ, NULL, -EIO); 184 if (test__start_subtest("handle_fexit_ret")) 185 test_module_attach_prog("handle_fexit_ret", 0, NULL, 0); 186 for (i = 0; i < ARRAY_SIZE(detach_tests); i++) { 187 char test_name[50]; 188 189 snprintf(test_name, sizeof(test_name), "%s_detach", detach_tests[i]); 190 if (!test__start_subtest(test_name)) 191 continue; 192 test_module_attach_detach(detach_tests[i]); 193 } 194 } 195