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