1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * User Events ABI Test Program 4 * 5 * Copyright (c) 2022 Beau Belgrave <beaub@linux.microsoft.com> 6 */ 7 8 #define _GNU_SOURCE 9 #include <sched.h> 10 11 #include <errno.h> 12 #include <linux/user_events.h> 13 #include <stdio.h> 14 #include <stdlib.h> 15 #include <fcntl.h> 16 #include <sys/ioctl.h> 17 #include <sys/stat.h> 18 #include <unistd.h> 19 #include <glob.h> 20 #include <string.h> 21 #include <asm/unistd.h> 22 23 #include "kselftest_harness.h" 24 #include "user_events_selftests.h" 25 26 const char *data_file = "/sys/kernel/tracing/user_events_data"; 27 const char *enable_file = "/sys/kernel/tracing/events/user_events/__abi_event/enable"; 28 const char *multi_dir_glob = "/sys/kernel/tracing/events/user_events_multi/__abi_event.*"; 29 30 static int wait_for_delete(char *dir) 31 { 32 struct stat buf; 33 int i; 34 35 for (i = 0; i < 10000; ++i) { 36 if (stat(dir, &buf) == -1 && errno == ENOENT) 37 return 0; 38 39 usleep(1000); 40 } 41 42 return -1; 43 } 44 45 static int find_multi_event_dir(char *unique_field, char *out_dir, int dir_len) 46 { 47 char path[256]; 48 glob_t buf; 49 int i, ret; 50 51 ret = glob(multi_dir_glob, GLOB_ONLYDIR, NULL, &buf); 52 53 if (ret) 54 return -1; 55 56 ret = -1; 57 58 for (i = 0; i < buf.gl_pathc; ++i) { 59 FILE *fp; 60 61 snprintf(path, sizeof(path), "%s/format", buf.gl_pathv[i]); 62 fp = fopen(path, "r"); 63 64 if (!fp) 65 continue; 66 67 while (fgets(path, sizeof(path), fp) != NULL) { 68 if (strstr(path, unique_field)) { 69 fclose(fp); 70 /* strscpy is not available, use snprintf */ 71 snprintf(out_dir, dir_len, "%s", buf.gl_pathv[i]); 72 ret = 0; 73 goto out; 74 } 75 } 76 77 fclose(fp); 78 } 79 out: 80 globfree(&buf); 81 82 return ret; 83 } 84 85 static bool event_exists(void) 86 { 87 int fd = open(enable_file, O_RDWR); 88 89 if (fd < 0) 90 return false; 91 92 close(fd); 93 94 return true; 95 } 96 97 static int change_event(bool enable) 98 { 99 int fd = open(enable_file, O_RDWR); 100 int ret; 101 102 if (fd < 0) 103 return -1; 104 105 if (enable) 106 ret = write(fd, "1", 1); 107 else 108 ret = write(fd, "0", 1); 109 110 close(fd); 111 112 if (ret == 1) 113 ret = 0; 114 else 115 ret = -1; 116 117 return ret; 118 } 119 120 static int event_delete(void) 121 { 122 int fd = open(data_file, O_RDWR); 123 int ret; 124 125 if (fd < 0) 126 return -1; 127 128 ret = ioctl(fd, DIAG_IOCSDEL, "__abi_event"); 129 130 close(fd); 131 132 return ret; 133 } 134 135 /* 136 * Deleting an event drops its last reference, but an unregister may defer 137 * that put (and the freeing of the associated enabler) past an RCU grace 138 * period. The delete can therefore transiently fail with -EBUSY while the 139 * previous reference is still being dropped. Retry only on that transient 140 * failure; treat an already-deleted event (-ENOENT) as success and return 141 * any other error immediately rather than spinning for the full timeout. 142 */ 143 static int wait_for_event_delete(void) 144 { 145 int i, ret; 146 147 for (i = 0; i < 10000; ++i) { 148 ret = event_delete(); 149 150 if (ret == 0 || errno == ENOENT) 151 return 0; 152 153 if (errno != EBUSY) 154 return ret; 155 156 usleep(1000); 157 } 158 159 return ret; 160 } 161 162 static int reg_enable_multi(void *enable, int size, int bit, int flags, 163 char *args) 164 { 165 struct user_reg reg = {0}; 166 char full_args[512] = {0}; 167 int fd = open(data_file, O_RDWR); 168 int len; 169 int ret; 170 171 if (fd < 0) 172 return -1; 173 174 len = snprintf(full_args, sizeof(full_args), "__abi_event %s", args); 175 176 if (len > sizeof(full_args)) { 177 ret = -E2BIG; 178 goto out; 179 } 180 181 reg.size = sizeof(reg); 182 reg.name_args = (__u64)full_args; 183 reg.flags = USER_EVENT_REG_MULTI_FORMAT | flags; 184 reg.enable_bit = bit; 185 reg.enable_addr = (__u64)enable; 186 reg.enable_size = size; 187 188 ret = ioctl(fd, DIAG_IOCSREG, ®); 189 out: 190 close(fd); 191 192 return ret; 193 } 194 195 static int reg_enable_flags(void *enable, int size, int bit, int flags) 196 { 197 struct user_reg reg = {0}; 198 int fd = open(data_file, O_RDWR); 199 int ret; 200 201 if (fd < 0) 202 return -1; 203 204 reg.size = sizeof(reg); 205 reg.name_args = (__u64)"__abi_event"; 206 reg.flags = flags; 207 reg.enable_bit = bit; 208 reg.enable_addr = (__u64)enable; 209 reg.enable_size = size; 210 211 ret = ioctl(fd, DIAG_IOCSREG, ®); 212 213 close(fd); 214 215 return ret; 216 } 217 218 static int reg_enable(void *enable, int size, int bit) 219 { 220 return reg_enable_flags(enable, size, bit, 0); 221 } 222 223 static int reg_disable(void *enable, int bit) 224 { 225 struct user_unreg reg = {0}; 226 int fd = open(data_file, O_RDWR); 227 int ret; 228 229 if (fd < 0) 230 return -1; 231 232 reg.size = sizeof(reg); 233 reg.disable_bit = bit; 234 reg.disable_addr = (__u64)enable; 235 236 ret = ioctl(fd, DIAG_IOCSUNREG, ®); 237 238 close(fd); 239 240 return ret; 241 } 242 243 FIXTURE(user) { 244 int check; 245 long check_long; 246 bool umount; 247 }; 248 249 FIXTURE_SETUP(user) { 250 USER_EVENT_FIXTURE_SETUP(return, self->umount); 251 252 change_event(false); 253 self->check = 0; 254 self->check_long = 0; 255 } 256 257 FIXTURE_TEARDOWN(user) { 258 USER_EVENT_FIXTURE_TEARDOWN(self->umount); 259 } 260 261 TEST_F(user, enablement) { 262 /* Changes should be reflected immediately */ 263 ASSERT_EQ(0, self->check); 264 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 265 ASSERT_EQ(0, change_event(true)); 266 ASSERT_EQ(1, self->check); 267 ASSERT_EQ(0, change_event(false)); 268 ASSERT_EQ(0, self->check); 269 270 /* Ensure kernel clears bit after disable */ 271 ASSERT_EQ(0, change_event(true)); 272 ASSERT_EQ(1, self->check); 273 ASSERT_EQ(0, reg_disable(&self->check, 0)); 274 ASSERT_EQ(0, self->check); 275 276 /* Ensure doesn't change after unreg */ 277 ASSERT_EQ(0, change_event(true)); 278 ASSERT_EQ(0, self->check); 279 ASSERT_EQ(0, change_event(false)); 280 } 281 282 TEST_F(user, flags) { 283 /* USER_EVENT_REG_PERSIST is allowed */ 284 ASSERT_EQ(0, reg_enable_flags(&self->check, sizeof(int), 0, 285 USER_EVENT_REG_PERSIST)); 286 ASSERT_EQ(0, reg_disable(&self->check, 0)); 287 288 /* Ensure it exists after close and disable */ 289 ASSERT_TRUE(event_exists()); 290 291 /* Ensure we can delete it */ 292 ASSERT_EQ(0, wait_for_event_delete()); 293 294 /* USER_EVENT_REG_MAX or above is not allowed */ 295 ASSERT_EQ(-1, reg_enable_flags(&self->check, sizeof(int), 0, 296 USER_EVENT_REG_MAX)); 297 298 /* Ensure it does not exist after invalid flags */ 299 ASSERT_FALSE(event_exists()); 300 } 301 302 TEST_F(user, bit_sizes) { 303 /* Allow 0-31 bits for 32-bit */ 304 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 305 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 31)); 306 ASSERT_NE(0, reg_enable(&self->check, sizeof(int), 32)); 307 ASSERT_EQ(0, reg_disable(&self->check, 0)); 308 ASSERT_EQ(0, reg_disable(&self->check, 31)); 309 310 #if BITS_PER_LONG == 8 311 /* Allow 0-64 bits for 64-bit */ 312 ASSERT_EQ(0, reg_enable(&self->check_long, sizeof(long), 63)); 313 ASSERT_NE(0, reg_enable(&self->check_long, sizeof(long), 64)); 314 ASSERT_EQ(0, reg_disable(&self->check_long, 63)); 315 #endif 316 317 /* Disallowed sizes (everything beside 4 and 8) */ 318 ASSERT_NE(0, reg_enable(&self->check, 1, 0)); 319 ASSERT_NE(0, reg_enable(&self->check, 2, 0)); 320 ASSERT_NE(0, reg_enable(&self->check, 3, 0)); 321 ASSERT_NE(0, reg_enable(&self->check, 5, 0)); 322 ASSERT_NE(0, reg_enable(&self->check, 6, 0)); 323 ASSERT_NE(0, reg_enable(&self->check, 7, 0)); 324 ASSERT_NE(0, reg_enable(&self->check, 9, 0)); 325 ASSERT_NE(0, reg_enable(&self->check, 128, 0)); 326 } 327 328 TEST_F(user, multi_format) { 329 char first_dir[256]; 330 char second_dir[256]; 331 struct stat buf; 332 333 /* Multiple formats for the same name should work */ 334 ASSERT_EQ(0, reg_enable_multi(&self->check, sizeof(int), 0, 335 0, "u32 multi_first")); 336 337 ASSERT_EQ(0, reg_enable_multi(&self->check, sizeof(int), 1, 338 0, "u64 multi_second")); 339 340 /* Same name with same format should also work */ 341 ASSERT_EQ(0, reg_enable_multi(&self->check, sizeof(int), 2, 342 0, "u64 multi_second")); 343 344 ASSERT_EQ(0, find_multi_event_dir("multi_first", 345 first_dir, sizeof(first_dir))); 346 347 ASSERT_EQ(0, find_multi_event_dir("multi_second", 348 second_dir, sizeof(second_dir))); 349 350 /* Should not be found in the same dir */ 351 ASSERT_NE(0, strcmp(first_dir, second_dir)); 352 353 /* First dir should still exist */ 354 ASSERT_EQ(0, stat(first_dir, &buf)); 355 356 /* Disabling first register should remove first dir */ 357 ASSERT_EQ(0, reg_disable(&self->check, 0)); 358 ASSERT_EQ(0, wait_for_delete(first_dir)); 359 360 /* Second dir should still exist */ 361 ASSERT_EQ(0, stat(second_dir, &buf)); 362 363 /* Disabling second register should remove second dir */ 364 ASSERT_EQ(0, reg_disable(&self->check, 1)); 365 /* Ensure bit 1 and 2 are tied together, should not delete yet */ 366 ASSERT_EQ(0, stat(second_dir, &buf)); 367 ASSERT_EQ(0, reg_disable(&self->check, 2)); 368 ASSERT_EQ(0, wait_for_delete(second_dir)); 369 } 370 371 TEST_F(user, forks) { 372 int i; 373 374 /* Ensure COW pages get updated after fork */ 375 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 376 ASSERT_EQ(0, self->check); 377 378 if (fork() == 0) { 379 /* Force COW */ 380 self->check = 0; 381 382 /* Up to 1 sec for enablement */ 383 for (i = 0; i < 10; ++i) { 384 usleep(100000); 385 386 if (self->check) 387 exit(0); 388 } 389 390 exit(1); 391 } 392 393 /* Allow generous time for COW, then enable */ 394 usleep(100000); 395 ASSERT_EQ(0, change_event(true)); 396 397 ASSERT_NE(-1, wait(&i)); 398 ASSERT_EQ(0, WEXITSTATUS(i)); 399 400 /* Ensure child doesn't disable parent */ 401 if (fork() == 0) 402 exit(reg_disable(&self->check, 0)); 403 404 ASSERT_NE(-1, wait(&i)); 405 ASSERT_EQ(0, WEXITSTATUS(i)); 406 ASSERT_EQ(1, self->check); 407 ASSERT_EQ(0, change_event(false)); 408 ASSERT_EQ(0, self->check); 409 } 410 411 /* Waits up to 1 sec for enablement */ 412 static int clone_check(void *check) 413 { 414 int i; 415 416 for (i = 0; i < 10; ++i) { 417 usleep(100000); 418 419 if (*(int *)check) 420 return 0; 421 } 422 423 return 1; 424 } 425 426 TEST_F(user, clones) { 427 int i, stack_size = 4096; 428 void *stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, 429 MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, 430 -1, 0); 431 432 ASSERT_NE(MAP_FAILED, stack); 433 ASSERT_EQ(0, reg_enable(&self->check, sizeof(int), 0)); 434 ASSERT_EQ(0, self->check); 435 436 /* Shared VM should see enablements */ 437 ASSERT_NE(-1, clone(&clone_check, stack + stack_size, 438 CLONE_VM | SIGCHLD, &self->check)); 439 440 ASSERT_EQ(0, change_event(true)); 441 ASSERT_NE(-1, wait(&i)); 442 ASSERT_EQ(0, WEXITSTATUS(i)); 443 munmap(stack, stack_size); 444 ASSERT_EQ(0, change_event(false)); 445 } 446 447 int main(int argc, char **argv) 448 { 449 return test_harness_run(argc, argv); 450 } 451