1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * User Events Dyn Events Test Program 4 * 5 * Copyright (c) 2021 Beau Belgrave <beaub@linux.microsoft.com> 6 */ 7 8 #include <errno.h> 9 #include <linux/user_events.h> 10 #include <stdio.h> 11 #include <stdlib.h> 12 #include <fcntl.h> 13 #include <sys/ioctl.h> 14 #include <sys/stat.h> 15 #include <unistd.h> 16 17 #include "../kselftest_harness.h" 18 #include "user_events_selftests.h" 19 20 const char *abi_file = "/sys/kernel/tracing/user_events_data"; 21 const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable"; 22 23 static bool wait_for_delete(void) 24 { 25 int i; 26 27 for (i = 0; i < 1000; ++i) { 28 int fd = open(enable_file, O_RDONLY); 29 30 if (fd == -1) 31 return true; 32 33 close(fd); 34 usleep(1000); 35 } 36 37 return false; 38 } 39 40 static int reg_event(int fd, int *check, int bit, const char *value) 41 { 42 struct user_reg reg = {0}; 43 44 reg.size = sizeof(reg); 45 reg.name_args = (__u64)value; 46 reg.enable_bit = bit; 47 reg.enable_addr = (__u64)check; 48 reg.enable_size = sizeof(*check); 49 50 if (ioctl(fd, DIAG_IOCSREG, ®) == -1) 51 return -1; 52 53 return 0; 54 } 55 56 static int unreg_event(int fd, int *check, int bit) 57 { 58 struct user_unreg unreg = {0}; 59 60 unreg.size = sizeof(unreg); 61 unreg.disable_bit = bit; 62 unreg.disable_addr = (__u64)check; 63 64 return ioctl(fd, DIAG_IOCSUNREG, &unreg); 65 } 66 67 static int parse(int *check, const char *value) 68 { 69 int fd = open(abi_file, O_RDWR); 70 int ret; 71 72 if (fd == -1) 73 return -1; 74 75 /* Until we have persist flags via dynamic events, use the base name */ 76 if (value[0] != 'u' || value[1] != ':') { 77 close(fd); 78 return -1; 79 } 80 81 ret = reg_event(fd, check, 31, value + 2); 82 83 if (ret != -1) { 84 if (unreg_event(fd, check, 31) == -1) 85 printf("WARN: Couldn't unreg event\n"); 86 } 87 88 close(fd); 89 90 return ret; 91 } 92 93 static int check_match(int *check, const char *first, const char *second, bool *match) 94 { 95 int fd = open(abi_file, O_RDWR); 96 int ret = -1; 97 98 if (fd == -1) 99 return -1; 100 101 if (reg_event(fd, check, 31, first) == -1) 102 goto cleanup; 103 104 if (reg_event(fd, check, 30, second) == -1) { 105 if (errno == EADDRINUSE) { 106 /* Name is in use, with different fields */ 107 *match = false; 108 ret = 0; 109 } 110 111 goto cleanup; 112 } 113 114 *match = true; 115 ret = 0; 116 cleanup: 117 unreg_event(fd, check, 31); 118 unreg_event(fd, check, 30); 119 120 close(fd); 121 122 wait_for_delete(); 123 124 return ret; 125 } 126 127 #define TEST_MATCH(x, y) \ 128 do { \ 129 bool match; \ 130 ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \ 131 ASSERT_EQ(true, match); \ 132 } while (0) 133 134 #define TEST_NMATCH(x, y) \ 135 do { \ 136 bool match; \ 137 ASSERT_NE(-1, check_match(&self->check, x, y, &match)); \ 138 ASSERT_EQ(false, match); \ 139 } while (0) 140 141 #define TEST_PARSE(x) ASSERT_NE(-1, parse(&self->check, x)) 142 143 #define TEST_NPARSE(x) ASSERT_EQ(-1, parse(&self->check, x)) 144 145 FIXTURE(user) { 146 int check; 147 }; 148 149 FIXTURE_SETUP(user) { 150 USER_EVENT_FIXTURE_SETUP(return); 151 } 152 153 FIXTURE_TEARDOWN(user) { 154 wait_for_delete(); 155 } 156 157 TEST_F(user, basic_types) { 158 /* All should work */ 159 TEST_PARSE("u:__test_event u64 a"); 160 TEST_PARSE("u:__test_event u32 a"); 161 TEST_PARSE("u:__test_event u16 a"); 162 TEST_PARSE("u:__test_event u8 a"); 163 TEST_PARSE("u:__test_event char a"); 164 TEST_PARSE("u:__test_event unsigned char a"); 165 TEST_PARSE("u:__test_event int a"); 166 TEST_PARSE("u:__test_event unsigned int a"); 167 TEST_PARSE("u:__test_event short a"); 168 TEST_PARSE("u:__test_event unsigned short a"); 169 TEST_PARSE("u:__test_event char[20] a"); 170 TEST_PARSE("u:__test_event unsigned char[20] a"); 171 TEST_PARSE("u:__test_event char[0x14] a"); 172 TEST_PARSE("u:__test_event unsigned char[0x14] a"); 173 /* Bad size format should fail */ 174 TEST_NPARSE("u:__test_event char[aa] a"); 175 /* Large size should fail */ 176 TEST_NPARSE("u:__test_event char[9999] a"); 177 /* Long size string should fail */ 178 TEST_NPARSE("u:__test_event char[0x0000000000001] a"); 179 } 180 181 TEST_F(user, loc_types) { 182 /* All should work */ 183 TEST_PARSE("u:__test_event __data_loc char[] a"); 184 TEST_PARSE("u:__test_event __data_loc unsigned char[] a"); 185 TEST_PARSE("u:__test_event __rel_loc char[] a"); 186 TEST_PARSE("u:__test_event __rel_loc unsigned char[] a"); 187 } 188 189 TEST_F(user, size_types) { 190 /* Should work */ 191 TEST_PARSE("u:__test_event struct custom a 20"); 192 /* Size not specified on struct should fail */ 193 TEST_NPARSE("u:__test_event struct custom a"); 194 /* Size specified on non-struct should fail */ 195 TEST_NPARSE("u:__test_event char a 20"); 196 } 197 198 TEST_F(user, matching) { 199 /* Single name matches */ 200 TEST_MATCH("__test_event u32 a", 201 "__test_event u32 a"); 202 203 /* Multiple names match */ 204 TEST_MATCH("__test_event u32 a; u32 b", 205 "__test_event u32 a; u32 b"); 206 207 /* Multiple names match with dangling ; */ 208 TEST_MATCH("__test_event u32 a; u32 b", 209 "__test_event u32 a; u32 b;"); 210 211 /* Single name doesn't match */ 212 TEST_NMATCH("__test_event u32 a", 213 "__test_event u32 b"); 214 215 /* Multiple names don't match */ 216 TEST_NMATCH("__test_event u32 a; u32 b", 217 "__test_event u32 b; u32 a"); 218 219 /* Types don't match */ 220 TEST_NMATCH("__test_event u64 a; u64 b", 221 "__test_event u32 a; u32 b"); 222 223 /* Struct name and size matches */ 224 TEST_MATCH("__test_event struct my_struct a 20", 225 "__test_event struct my_struct a 20"); 226 227 /* Struct name don't match */ 228 TEST_NMATCH("__test_event struct my_struct a 20", 229 "__test_event struct my_struct b 20"); 230 231 /* Struct size don't match */ 232 TEST_NMATCH("__test_event struct my_struct a 20", 233 "__test_event struct my_struct a 21"); 234 } 235 236 int main(int argc, char **argv) 237 { 238 return test_harness_run(argc, argv); 239 } 240