1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * User Events FTrace 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 <sys/uio.h> 16 #include <unistd.h> 17 18 #include "../kselftest_harness.h" 19 20 const char *data_file = "/sys/kernel/tracing/user_events_data"; 21 const char *status_file = "/sys/kernel/tracing/user_events_status"; 22 const char *enable_file = "/sys/kernel/tracing/events/user_events/__test_event/enable"; 23 const char *trace_file = "/sys/kernel/tracing/trace"; 24 const char *fmt_file = "/sys/kernel/tracing/events/user_events/__test_event/format"; 25 26 static int trace_bytes(void) 27 { 28 int fd = open(trace_file, O_RDONLY); 29 char buf[256]; 30 int bytes = 0, got; 31 32 if (fd == -1) 33 return -1; 34 35 while (true) { 36 got = read(fd, buf, sizeof(buf)); 37 38 if (got == -1) 39 return -1; 40 41 if (got == 0) 42 break; 43 44 bytes += got; 45 } 46 47 close(fd); 48 49 return bytes; 50 } 51 52 static int skip_until_empty_line(FILE *fp) 53 { 54 int c, last = 0; 55 56 while (true) { 57 c = getc(fp); 58 59 if (c == EOF) 60 break; 61 62 if (last == '\n' && c == '\n') 63 return 0; 64 65 last = c; 66 } 67 68 return -1; 69 } 70 71 static int get_print_fmt(char *buffer, int len) 72 { 73 FILE *fp = fopen(fmt_file, "r"); 74 char *newline; 75 76 if (!fp) 77 return -1; 78 79 /* Read until empty line (Skip Common) */ 80 if (skip_until_empty_line(fp) < 0) 81 goto err; 82 83 /* Read until empty line (Skip Properties) */ 84 if (skip_until_empty_line(fp) < 0) 85 goto err; 86 87 /* Read in print_fmt: */ 88 if (fgets(buffer, len, fp) == NULL) 89 goto err; 90 91 newline = strchr(buffer, '\n'); 92 93 if (newline) 94 *newline = '\0'; 95 96 fclose(fp); 97 98 return 0; 99 err: 100 fclose(fp); 101 102 return -1; 103 } 104 105 static int clear(int *check) 106 { 107 struct user_unreg unreg = {0}; 108 109 unreg.size = sizeof(unreg); 110 unreg.disable_bit = 31; 111 unreg.disable_addr = (__u64)check; 112 113 int fd = open(data_file, O_RDWR); 114 115 if (fd == -1) 116 return -1; 117 118 if (ioctl(fd, DIAG_IOCSUNREG, &unreg) == -1) 119 if (errno != ENOENT) 120 return -1; 121 122 if (ioctl(fd, DIAG_IOCSDEL, "__test_event") == -1) 123 if (errno != ENOENT) 124 return -1; 125 126 close(fd); 127 128 return 0; 129 } 130 131 static int check_print_fmt(const char *event, const char *expected, int *check) 132 { 133 struct user_reg reg = {0}; 134 char print_fmt[256]; 135 int ret; 136 int fd; 137 138 /* Ensure cleared */ 139 ret = clear(check); 140 141 if (ret != 0) 142 return ret; 143 144 fd = open(data_file, O_RDWR); 145 146 if (fd == -1) 147 return fd; 148 149 reg.size = sizeof(reg); 150 reg.name_args = (__u64)event; 151 reg.enable_bit = 31; 152 reg.enable_addr = (__u64)check; 153 reg.enable_size = sizeof(*check); 154 155 /* Register should work */ 156 ret = ioctl(fd, DIAG_IOCSREG, ®); 157 158 close(fd); 159 160 if (ret != 0) { 161 printf("Reg failed in fmt\n"); 162 return ret; 163 } 164 165 /* Ensure correct print_fmt */ 166 ret = get_print_fmt(print_fmt, sizeof(print_fmt)); 167 168 if (ret != 0) 169 return ret; 170 171 return strcmp(print_fmt, expected); 172 } 173 174 FIXTURE(user) { 175 int status_fd; 176 int data_fd; 177 int enable_fd; 178 int check; 179 }; 180 181 FIXTURE_SETUP(user) { 182 self->status_fd = open(status_file, O_RDONLY); 183 ASSERT_NE(-1, self->status_fd); 184 185 self->data_fd = open(data_file, O_RDWR); 186 ASSERT_NE(-1, self->data_fd); 187 188 self->enable_fd = -1; 189 } 190 191 FIXTURE_TEARDOWN(user) { 192 close(self->status_fd); 193 close(self->data_fd); 194 195 if (self->enable_fd != -1) { 196 write(self->enable_fd, "0", sizeof("0")); 197 close(self->enable_fd); 198 } 199 200 if (clear(&self->check) != 0) 201 printf("WARNING: Clear didn't work!\n"); 202 } 203 204 TEST_F(user, register_events) { 205 struct user_reg reg = {0}; 206 struct user_unreg unreg = {0}; 207 208 reg.size = sizeof(reg); 209 reg.name_args = (__u64)"__test_event u32 field1; u32 field2"; 210 reg.enable_bit = 31; 211 reg.enable_addr = (__u64)&self->check; 212 reg.enable_size = sizeof(self->check); 213 214 unreg.size = sizeof(unreg); 215 unreg.disable_bit = 31; 216 unreg.disable_addr = (__u64)&self->check; 217 218 /* Register should work */ 219 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®)); 220 ASSERT_EQ(0, reg.write_index); 221 222 /* Multiple registers to the same addr + bit should fail */ 223 ASSERT_EQ(-1, ioctl(self->data_fd, DIAG_IOCSREG, ®)); 224 ASSERT_EQ(EADDRINUSE, errno); 225 226 /* Multiple registers to same name should result in same index */ 227 reg.enable_bit = 30; 228 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®)); 229 ASSERT_EQ(0, reg.write_index); 230 231 /* Ensure disabled */ 232 self->enable_fd = open(enable_file, O_RDWR); 233 ASSERT_NE(-1, self->enable_fd); 234 ASSERT_NE(-1, write(self->enable_fd, "0", sizeof("0"))) 235 236 /* Enable event and ensure bits updated in status */ 237 ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1"))) 238 ASSERT_EQ(1 << reg.enable_bit, self->check); 239 240 /* Disable event and ensure bits updated in status */ 241 ASSERT_NE(-1, write(self->enable_fd, "0", sizeof("0"))) 242 ASSERT_EQ(0, self->check); 243 244 /* File still open should return -EBUSY for delete */ 245 ASSERT_EQ(-1, ioctl(self->data_fd, DIAG_IOCSDEL, "__test_event")); 246 ASSERT_EQ(EBUSY, errno); 247 248 /* Unregister */ 249 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg)); 250 unreg.disable_bit = 30; 251 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSUNREG, &unreg)); 252 253 /* Delete should work only after close and unregister */ 254 close(self->data_fd); 255 self->data_fd = open(data_file, O_RDWR); 256 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSDEL, "__test_event")); 257 } 258 259 TEST_F(user, write_events) { 260 struct user_reg reg = {0}; 261 struct iovec io[3]; 262 __u32 field1, field2; 263 int before = 0, after = 0; 264 265 reg.size = sizeof(reg); 266 reg.name_args = (__u64)"__test_event u32 field1; u32 field2"; 267 reg.enable_bit = 31; 268 reg.enable_addr = (__u64)&self->check; 269 reg.enable_size = sizeof(self->check); 270 271 field1 = 1; 272 field2 = 2; 273 274 io[0].iov_base = ®.write_index; 275 io[0].iov_len = sizeof(reg.write_index); 276 io[1].iov_base = &field1; 277 io[1].iov_len = sizeof(field1); 278 io[2].iov_base = &field2; 279 io[2].iov_len = sizeof(field2); 280 281 /* Register should work */ 282 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®)); 283 ASSERT_EQ(0, reg.write_index); 284 ASSERT_EQ(0, self->check); 285 286 /* Write should fail on invalid slot with ENOENT */ 287 io[0].iov_base = &field2; 288 io[0].iov_len = sizeof(field2); 289 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 290 ASSERT_EQ(ENOENT, errno); 291 io[0].iov_base = ®.write_index; 292 io[0].iov_len = sizeof(reg.write_index); 293 294 /* Enable event */ 295 self->enable_fd = open(enable_file, O_RDWR); 296 ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1"))) 297 298 /* Event should now be enabled */ 299 ASSERT_NE(1 << reg.enable_bit, self->check); 300 301 /* Write should make it out to ftrace buffers */ 302 before = trace_bytes(); 303 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 304 after = trace_bytes(); 305 ASSERT_GT(after, before); 306 307 /* Negative index should fail with EINVAL */ 308 reg.write_index = -1; 309 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 310 ASSERT_EQ(EINVAL, errno); 311 } 312 313 TEST_F(user, write_fault) { 314 struct user_reg reg = {0}; 315 struct iovec io[2]; 316 int l = sizeof(__u64); 317 void *anon; 318 319 reg.size = sizeof(reg); 320 reg.name_args = (__u64)"__test_event u64 anon"; 321 reg.enable_bit = 31; 322 reg.enable_addr = (__u64)&self->check; 323 reg.enable_size = sizeof(self->check); 324 325 anon = mmap(NULL, l, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 326 ASSERT_NE(MAP_FAILED, anon); 327 328 io[0].iov_base = ®.write_index; 329 io[0].iov_len = sizeof(reg.write_index); 330 io[1].iov_base = anon; 331 io[1].iov_len = l; 332 333 /* Register should work */ 334 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®)); 335 ASSERT_EQ(0, reg.write_index); 336 337 /* Write should work normally */ 338 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 2)); 339 340 /* Faulted data should zero fill and work */ 341 ASSERT_EQ(0, madvise(anon, l, MADV_DONTNEED)); 342 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 2)); 343 ASSERT_EQ(0, munmap(anon, l)); 344 } 345 346 TEST_F(user, write_validator) { 347 struct user_reg reg = {0}; 348 struct iovec io[3]; 349 int loc, bytes; 350 char data[8]; 351 int before = 0, after = 0; 352 353 reg.size = sizeof(reg); 354 reg.name_args = (__u64)"__test_event __rel_loc char[] data"; 355 reg.enable_bit = 31; 356 reg.enable_addr = (__u64)&self->check; 357 reg.enable_size = sizeof(self->check); 358 359 /* Register should work */ 360 ASSERT_EQ(0, ioctl(self->data_fd, DIAG_IOCSREG, ®)); 361 ASSERT_EQ(0, reg.write_index); 362 ASSERT_EQ(0, self->check); 363 364 io[0].iov_base = ®.write_index; 365 io[0].iov_len = sizeof(reg.write_index); 366 io[1].iov_base = &loc; 367 io[1].iov_len = sizeof(loc); 368 io[2].iov_base = data; 369 bytes = snprintf(data, sizeof(data), "Test") + 1; 370 io[2].iov_len = bytes; 371 372 /* Undersized write should fail */ 373 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 1)); 374 ASSERT_EQ(EINVAL, errno); 375 376 /* Enable event */ 377 self->enable_fd = open(enable_file, O_RDWR); 378 ASSERT_NE(-1, write(self->enable_fd, "1", sizeof("1"))) 379 380 /* Event should now be enabled */ 381 ASSERT_EQ(1 << reg.enable_bit, self->check); 382 383 /* Full in-bounds write should work */ 384 before = trace_bytes(); 385 loc = DYN_LOC(0, bytes); 386 ASSERT_NE(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 387 after = trace_bytes(); 388 ASSERT_GT(after, before); 389 390 /* Out of bounds write should fault (offset way out) */ 391 loc = DYN_LOC(1024, bytes); 392 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 393 ASSERT_EQ(EFAULT, errno); 394 395 /* Out of bounds write should fault (offset 1 byte out) */ 396 loc = DYN_LOC(1, bytes); 397 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 398 ASSERT_EQ(EFAULT, errno); 399 400 /* Out of bounds write should fault (size way out) */ 401 loc = DYN_LOC(0, bytes + 1024); 402 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 403 ASSERT_EQ(EFAULT, errno); 404 405 /* Out of bounds write should fault (size 1 byte out) */ 406 loc = DYN_LOC(0, bytes + 1); 407 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 408 ASSERT_EQ(EFAULT, errno); 409 410 /* Non-Null should fault */ 411 memset(data, 'A', sizeof(data)); 412 loc = DYN_LOC(0, bytes); 413 ASSERT_EQ(-1, writev(self->data_fd, (const struct iovec *)io, 3)); 414 ASSERT_EQ(EFAULT, errno); 415 } 416 417 TEST_F(user, print_fmt) { 418 int ret; 419 420 ret = check_print_fmt("__test_event __rel_loc char[] data", 421 "print fmt: \"data=%s\", __get_rel_str(data)", 422 &self->check); 423 ASSERT_EQ(0, ret); 424 425 ret = check_print_fmt("__test_event __data_loc char[] data", 426 "print fmt: \"data=%s\", __get_str(data)", 427 &self->check); 428 ASSERT_EQ(0, ret); 429 430 ret = check_print_fmt("__test_event s64 data", 431 "print fmt: \"data=%lld\", REC->data", 432 &self->check); 433 ASSERT_EQ(0, ret); 434 435 ret = check_print_fmt("__test_event u64 data", 436 "print fmt: \"data=%llu\", REC->data", 437 &self->check); 438 ASSERT_EQ(0, ret); 439 440 ret = check_print_fmt("__test_event s32 data", 441 "print fmt: \"data=%d\", REC->data", 442 &self->check); 443 ASSERT_EQ(0, ret); 444 445 ret = check_print_fmt("__test_event u32 data", 446 "print fmt: \"data=%u\", REC->data", 447 &self->check); 448 ASSERT_EQ(0, ret); 449 450 ret = check_print_fmt("__test_event int data", 451 "print fmt: \"data=%d\", REC->data", 452 &self->check); 453 ASSERT_EQ(0, ret); 454 455 ret = check_print_fmt("__test_event unsigned int data", 456 "print fmt: \"data=%u\", REC->data", 457 &self->check); 458 ASSERT_EQ(0, ret); 459 460 ret = check_print_fmt("__test_event s16 data", 461 "print fmt: \"data=%d\", REC->data", 462 &self->check); 463 ASSERT_EQ(0, ret); 464 465 ret = check_print_fmt("__test_event u16 data", 466 "print fmt: \"data=%u\", REC->data", 467 &self->check); 468 ASSERT_EQ(0, ret); 469 470 ret = check_print_fmt("__test_event short data", 471 "print fmt: \"data=%d\", REC->data", 472 &self->check); 473 ASSERT_EQ(0, ret); 474 475 ret = check_print_fmt("__test_event unsigned short data", 476 "print fmt: \"data=%u\", REC->data", 477 &self->check); 478 ASSERT_EQ(0, ret); 479 480 ret = check_print_fmt("__test_event s8 data", 481 "print fmt: \"data=%d\", REC->data", 482 &self->check); 483 ASSERT_EQ(0, ret); 484 485 ret = check_print_fmt("__test_event u8 data", 486 "print fmt: \"data=%u\", REC->data", 487 &self->check); 488 ASSERT_EQ(0, ret); 489 490 ret = check_print_fmt("__test_event char data", 491 "print fmt: \"data=%d\", REC->data", 492 &self->check); 493 ASSERT_EQ(0, ret); 494 495 ret = check_print_fmt("__test_event unsigned char data", 496 "print fmt: \"data=%u\", REC->data", 497 &self->check); 498 ASSERT_EQ(0, ret); 499 500 ret = check_print_fmt("__test_event char[4] data", 501 "print fmt: \"data=%s\", REC->data", 502 &self->check); 503 ASSERT_EQ(0, ret); 504 } 505 506 int main(int argc, char **argv) 507 { 508 return test_harness_run(argc, argv); 509 } 510