1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2021-2022, NVIDIA CORPORATION & AFFILIATES 3 * 4 * These tests are "kernel integrity" tests. They are looking for kernel 5 * WARN/OOPS/kasn/etc splats triggered by kernel sanitizers & debugging 6 * features. It does not attempt to verify that the system calls are doing what 7 * they are supposed to do. 8 * 9 * The basic philosophy is to run a sequence of calls that will succeed and then 10 * sweep every failure injection point on that call chain to look for 11 * interesting things in error handling. 12 * 13 * This test is best run with: 14 * echo 1 > /proc/sys/kernel/panic_on_warn 15 * If something is actually going wrong. 16 */ 17 #include <fcntl.h> 18 #include <dirent.h> 19 20 #define __EXPORTED_HEADERS__ 21 #include <linux/vfio.h> 22 23 #include "iommufd_utils.h" 24 25 static bool have_fault_injection; 26 27 static int writeat(int dfd, const char *fn, const char *val) 28 { 29 size_t val_len = strlen(val); 30 ssize_t res; 31 int fd; 32 33 fd = openat(dfd, fn, O_WRONLY); 34 if (fd == -1) 35 return -1; 36 res = write(fd, val, val_len); 37 assert(res == val_len); 38 close(fd); 39 return 0; 40 } 41 42 static __attribute__((constructor)) void setup_buffer(void) 43 { 44 PAGE_SIZE = sysconf(_SC_PAGE_SIZE); 45 46 BUFFER_SIZE = 2*1024*1024; 47 48 buffer = mmap(0, BUFFER_SIZE, PROT_READ | PROT_WRITE, 49 MAP_SHARED | MAP_ANONYMOUS, -1, 0); 50 } 51 52 /* 53 * This sets up fail_injection in a way that is useful for this test. 54 * It does not attempt to restore things back to how they were. 55 */ 56 static __attribute__((constructor)) void setup_fault_injection(void) 57 { 58 DIR *debugfs = opendir("/sys/kernel/debug/"); 59 struct dirent *dent; 60 61 if (!debugfs) 62 return; 63 64 /* Allow any allocation call to be fault injected */ 65 if (writeat(dirfd(debugfs), "failslab/ignore-gfp-wait", "N")) 66 return; 67 writeat(dirfd(debugfs), "fail_page_alloc/ignore-gfp-wait", "N"); 68 writeat(dirfd(debugfs), "fail_page_alloc/ignore-gfp-highmem", "N"); 69 70 while ((dent = readdir(debugfs))) { 71 char fn[300]; 72 73 if (strncmp(dent->d_name, "fail", 4) != 0) 74 continue; 75 76 /* We are looking for kernel splats, quiet down the log */ 77 snprintf(fn, sizeof(fn), "%s/verbose", dent->d_name); 78 writeat(dirfd(debugfs), fn, ""); 79 } 80 closedir(debugfs); 81 have_fault_injection = true; 82 } 83 84 struct fail_nth_state { 85 int proc_fd; 86 unsigned int iteration; 87 }; 88 89 static void fail_nth_first(struct __test_metadata *_metadata, 90 struct fail_nth_state *nth_state) 91 { 92 char buf[300]; 93 94 snprintf(buf, sizeof(buf), "/proc/self/task/%u/fail-nth", getpid()); 95 nth_state->proc_fd = open(buf, O_RDWR); 96 ASSERT_NE(-1, nth_state->proc_fd); 97 } 98 99 static bool fail_nth_next(struct __test_metadata *_metadata, 100 struct fail_nth_state *nth_state, 101 int test_result) 102 { 103 static const char disable_nth[] = ""; 104 char buf[300]; 105 106 /* 107 * This is just an arbitrary limit based on the current kernel 108 * situation. Changes in the kernel can dramatically change the number of 109 * required fault injection sites, so if this hits it doesn't 110 * necessarily mean a test failure, just that the limit has to be made 111 * bigger. 112 */ 113 ASSERT_GT(400, nth_state->iteration); 114 if (nth_state->iteration != 0) { 115 ssize_t res; 116 ssize_t res2; 117 118 buf[0] = 0; 119 /* 120 * Annoyingly disabling the nth can also fail. This means 121 * the test passed without triggering failure 122 */ 123 res = pread(nth_state->proc_fd, buf, sizeof(buf), 0); 124 if (res == -1 && errno == EFAULT) { 125 buf[0] = '1'; 126 buf[1] = '\n'; 127 res = 2; 128 } 129 130 res2 = pwrite(nth_state->proc_fd, disable_nth, 131 ARRAY_SIZE(disable_nth) - 1, 0); 132 if (res2 == -1 && errno == EFAULT) { 133 res2 = pwrite(nth_state->proc_fd, disable_nth, 134 ARRAY_SIZE(disable_nth) - 1, 0); 135 buf[0] = '1'; 136 buf[1] = '\n'; 137 } 138 ASSERT_EQ(ARRAY_SIZE(disable_nth) - 1, res2); 139 140 /* printf(" nth %u result=%d nth=%u\n", nth_state->iteration, 141 test_result, atoi(buf)); */ 142 fflush(stdout); 143 ASSERT_LT(1, res); 144 if (res != 2 || buf[0] != '' || buf[1] != '\n') 145 return false; 146 } else { 147 /* printf(" nth %u result=%d\n", nth_state->iteration, 148 test_result); */ 149 } 150 nth_state->iteration++; 151 return true; 152 } 153 154 /* 155 * This is called during the test to start failure injection. It allows the test 156 * to do some setup that has already been swept and thus reduce the required 157 * iterations. 158 */ 159 void __fail_nth_enable(struct __test_metadata *_metadata, 160 struct fail_nth_state *nth_state) 161 { 162 char buf[300]; 163 size_t len; 164 165 if (!nth_state->iteration) 166 return; 167 168 len = snprintf(buf, sizeof(buf), "%u", nth_state->iteration); 169 ASSERT_EQ(len, pwrite(nth_state->proc_fd, buf, len, 0)); 170 } 171 #define fail_nth_enable() __fail_nth_enable(_metadata, _nth_state) 172 173 #define TEST_FAIL_NTH(fixture_name, name) \ 174 static int test_nth_##name(struct __test_metadata *_metadata, \ 175 FIXTURE_DATA(fixture_name) *self, \ 176 const FIXTURE_VARIANT(fixture_name) \ 177 *variant, \ 178 struct fail_nth_state *_nth_state); \ 179 TEST_F(fixture_name, name) \ 180 { \ 181 struct fail_nth_state nth_state = {}; \ 182 int test_result = 0; \ 183 \ 184 if (!have_fault_injection) \ 185 SKIP(return, \ 186 "fault injection is not enabled in the kernel"); \ 187 fail_nth_first(_metadata, &nth_state); \ 188 ASSERT_EQ(0, test_nth_##name(_metadata, self, variant, \ 189 &nth_state)); \ 190 while (fail_nth_next(_metadata, &nth_state, test_result)) { \ 191 fixture_name##_teardown(_metadata, self, variant); \ 192 fixture_name##_setup(_metadata, self, variant); \ 193 test_result = test_nth_##name(_metadata, self, \ 194 variant, &nth_state); \ 195 }; \ 196 ASSERT_EQ(0, test_result); \ 197 } \ 198 static int test_nth_##name( \ 199 struct __test_metadata __attribute__((unused)) *_metadata, \ 200 FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \ 201 const FIXTURE_VARIANT(fixture_name) __attribute__((unused)) \ 202 *variant, \ 203 struct fail_nth_state *_nth_state) 204 205 FIXTURE(basic_fail_nth) 206 { 207 int fd; 208 uint32_t access_id; 209 }; 210 211 FIXTURE_SETUP(basic_fail_nth) 212 { 213 self->fd = -1; 214 self->access_id = 0; 215 } 216 217 FIXTURE_TEARDOWN(basic_fail_nth) 218 { 219 int rc; 220 221 if (self->access_id) { 222 /* The access FD holds the iommufd open until it closes */ 223 rc = _test_cmd_destroy_access(self->access_id); 224 assert(rc == 0); 225 } 226 teardown_iommufd(self->fd, _metadata); 227 } 228 229 /* Cover ioas.c */ 230 TEST_FAIL_NTH(basic_fail_nth, basic) 231 { 232 struct iommu_iova_range ranges[10]; 233 uint32_t ioas_id; 234 __u64 iova; 235 236 fail_nth_enable(); 237 238 self->fd = open("/dev/iommu", O_RDWR); 239 if (self->fd == -1) 240 return -1; 241 242 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 243 return -1; 244 245 { 246 struct iommu_ioas_iova_ranges ranges_cmd = { 247 .size = sizeof(ranges_cmd), 248 .num_iovas = ARRAY_SIZE(ranges), 249 .ioas_id = ioas_id, 250 .allowed_iovas = (uintptr_t)ranges, 251 }; 252 if (ioctl(self->fd, IOMMU_IOAS_IOVA_RANGES, &ranges_cmd)) 253 return -1; 254 } 255 256 { 257 struct iommu_ioas_allow_iovas allow_cmd = { 258 .size = sizeof(allow_cmd), 259 .ioas_id = ioas_id, 260 .num_iovas = 1, 261 .allowed_iovas = (uintptr_t)ranges, 262 }; 263 264 ranges[0].start = 16*1024; 265 ranges[0].last = BUFFER_SIZE + 16 * 1024 * 600 - 1; 266 if (ioctl(self->fd, IOMMU_IOAS_ALLOW_IOVAS, &allow_cmd)) 267 return -1; 268 } 269 270 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, BUFFER_SIZE, &iova, 271 IOMMU_IOAS_MAP_WRITEABLE | 272 IOMMU_IOAS_MAP_READABLE)) 273 return -1; 274 275 { 276 struct iommu_ioas_copy copy_cmd = { 277 .size = sizeof(copy_cmd), 278 .flags = IOMMU_IOAS_MAP_WRITEABLE | 279 IOMMU_IOAS_MAP_READABLE, 280 .dst_ioas_id = ioas_id, 281 .src_ioas_id = ioas_id, 282 .src_iova = iova, 283 .length = sizeof(ranges), 284 }; 285 286 if (ioctl(self->fd, IOMMU_IOAS_COPY, ©_cmd)) 287 return -1; 288 } 289 290 if (_test_ioctl_ioas_unmap(self->fd, ioas_id, iova, BUFFER_SIZE, 291 NULL)) 292 return -1; 293 /* Failure path of no IOVA to unmap */ 294 _test_ioctl_ioas_unmap(self->fd, ioas_id, iova, BUFFER_SIZE, NULL); 295 return 0; 296 } 297 298 /* iopt_area_fill_domains() and iopt_area_fill_domain() */ 299 TEST_FAIL_NTH(basic_fail_nth, map_domain) 300 { 301 uint32_t ioas_id; 302 __u32 stdev_id; 303 __u32 hwpt_id; 304 __u64 iova; 305 306 self->fd = open("/dev/iommu", O_RDWR); 307 if (self->fd == -1) 308 return -1; 309 310 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 311 return -1; 312 313 if (_test_ioctl_set_temp_memory_limit(self->fd, 32)) 314 return -1; 315 316 fail_nth_enable(); 317 318 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id, &hwpt_id, NULL)) 319 return -1; 320 321 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, 262144, &iova, 322 IOMMU_IOAS_MAP_WRITEABLE | 323 IOMMU_IOAS_MAP_READABLE)) 324 return -1; 325 326 if (_test_ioctl_destroy(self->fd, stdev_id)) 327 return -1; 328 329 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id, &hwpt_id, NULL)) 330 return -1; 331 return 0; 332 } 333 334 TEST_FAIL_NTH(basic_fail_nth, map_two_domains) 335 { 336 uint32_t ioas_id; 337 __u32 stdev_id2; 338 __u32 stdev_id; 339 __u32 hwpt_id2; 340 __u32 hwpt_id; 341 __u64 iova; 342 343 self->fd = open("/dev/iommu", O_RDWR); 344 if (self->fd == -1) 345 return -1; 346 347 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 348 return -1; 349 350 if (_test_ioctl_set_temp_memory_limit(self->fd, 32)) 351 return -1; 352 353 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id, &hwpt_id, NULL)) 354 return -1; 355 356 fail_nth_enable(); 357 358 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id2, &hwpt_id2, 359 NULL)) 360 return -1; 361 362 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, 262144, &iova, 363 IOMMU_IOAS_MAP_WRITEABLE | 364 IOMMU_IOAS_MAP_READABLE)) 365 return -1; 366 367 if (_test_ioctl_destroy(self->fd, stdev_id)) 368 return -1; 369 370 if (_test_ioctl_destroy(self->fd, stdev_id2)) 371 return -1; 372 373 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id, &hwpt_id, NULL)) 374 return -1; 375 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id2, &hwpt_id2, 376 NULL)) 377 return -1; 378 return 0; 379 } 380 381 TEST_FAIL_NTH(basic_fail_nth, access_rw) 382 { 383 uint64_t tmp_big[4096]; 384 uint32_t ioas_id; 385 uint16_t tmp[32]; 386 __u64 iova; 387 388 self->fd = open("/dev/iommu", O_RDWR); 389 if (self->fd == -1) 390 return -1; 391 392 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 393 return -1; 394 395 if (_test_ioctl_set_temp_memory_limit(self->fd, 32)) 396 return -1; 397 398 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, 262144, &iova, 399 IOMMU_IOAS_MAP_WRITEABLE | 400 IOMMU_IOAS_MAP_READABLE)) 401 return -1; 402 403 fail_nth_enable(); 404 405 if (_test_cmd_create_access(self->fd, ioas_id, &self->access_id, 0)) 406 return -1; 407 408 { 409 struct iommu_test_cmd access_cmd = { 410 .size = sizeof(access_cmd), 411 .op = IOMMU_TEST_OP_ACCESS_RW, 412 .id = self->access_id, 413 .access_rw = { .iova = iova, 414 .length = sizeof(tmp), 415 .uptr = (uintptr_t)tmp }, 416 }; 417 418 // READ 419 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 420 &access_cmd)) 421 return -1; 422 423 access_cmd.access_rw.flags = MOCK_ACCESS_RW_WRITE; 424 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 425 &access_cmd)) 426 return -1; 427 428 access_cmd.access_rw.flags = MOCK_ACCESS_RW_SLOW_PATH; 429 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 430 &access_cmd)) 431 return -1; 432 access_cmd.access_rw.flags = MOCK_ACCESS_RW_SLOW_PATH | 433 MOCK_ACCESS_RW_WRITE; 434 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 435 &access_cmd)) 436 return -1; 437 } 438 439 { 440 struct iommu_test_cmd access_cmd = { 441 .size = sizeof(access_cmd), 442 .op = IOMMU_TEST_OP_ACCESS_RW, 443 .id = self->access_id, 444 .access_rw = { .iova = iova, 445 .flags = MOCK_ACCESS_RW_SLOW_PATH, 446 .length = sizeof(tmp_big), 447 .uptr = (uintptr_t)tmp_big }, 448 }; 449 450 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 451 &access_cmd)) 452 return -1; 453 } 454 if (_test_cmd_destroy_access(self->access_id)) 455 return -1; 456 self->access_id = 0; 457 return 0; 458 } 459 460 /* pages.c access functions */ 461 TEST_FAIL_NTH(basic_fail_nth, access_pin) 462 { 463 uint32_t access_pages_id; 464 uint32_t ioas_id; 465 __u64 iova; 466 467 self->fd = open("/dev/iommu", O_RDWR); 468 if (self->fd == -1) 469 return -1; 470 471 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 472 return -1; 473 474 if (_test_ioctl_set_temp_memory_limit(self->fd, 32)) 475 return -1; 476 477 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, BUFFER_SIZE, &iova, 478 IOMMU_IOAS_MAP_WRITEABLE | 479 IOMMU_IOAS_MAP_READABLE)) 480 return -1; 481 482 if (_test_cmd_create_access(self->fd, ioas_id, &self->access_id, 483 MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES)) 484 return -1; 485 486 fail_nth_enable(); 487 488 { 489 struct iommu_test_cmd access_cmd = { 490 .size = sizeof(access_cmd), 491 .op = IOMMU_TEST_OP_ACCESS_PAGES, 492 .id = self->access_id, 493 .access_pages = { .iova = iova, 494 .length = BUFFER_SIZE, 495 .uptr = (uintptr_t)buffer }, 496 }; 497 498 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 499 &access_cmd)) 500 return -1; 501 access_pages_id = access_cmd.access_pages.out_access_pages_id; 502 } 503 504 if (_test_cmd_destroy_access_pages(self->fd, self->access_id, 505 access_pages_id)) 506 return -1; 507 508 if (_test_cmd_destroy_access(self->access_id)) 509 return -1; 510 self->access_id = 0; 511 return 0; 512 } 513 514 /* iopt_pages_fill_xarray() */ 515 TEST_FAIL_NTH(basic_fail_nth, access_pin_domain) 516 { 517 uint32_t access_pages_id; 518 uint32_t ioas_id; 519 __u32 stdev_id; 520 __u32 hwpt_id; 521 __u64 iova; 522 523 self->fd = open("/dev/iommu", O_RDWR); 524 if (self->fd == -1) 525 return -1; 526 527 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 528 return -1; 529 530 if (_test_ioctl_set_temp_memory_limit(self->fd, 32)) 531 return -1; 532 533 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id, &hwpt_id, NULL)) 534 return -1; 535 536 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, BUFFER_SIZE, &iova, 537 IOMMU_IOAS_MAP_WRITEABLE | 538 IOMMU_IOAS_MAP_READABLE)) 539 return -1; 540 541 if (_test_cmd_create_access(self->fd, ioas_id, &self->access_id, 542 MOCK_FLAGS_ACCESS_CREATE_NEEDS_PIN_PAGES)) 543 return -1; 544 545 fail_nth_enable(); 546 547 { 548 struct iommu_test_cmd access_cmd = { 549 .size = sizeof(access_cmd), 550 .op = IOMMU_TEST_OP_ACCESS_PAGES, 551 .id = self->access_id, 552 .access_pages = { .iova = iova, 553 .length = BUFFER_SIZE, 554 .uptr = (uintptr_t)buffer }, 555 }; 556 557 if (ioctl(self->fd, _IOMMU_TEST_CMD(IOMMU_TEST_OP_ACCESS_RW), 558 &access_cmd)) 559 return -1; 560 access_pages_id = access_cmd.access_pages.out_access_pages_id; 561 } 562 563 if (_test_cmd_destroy_access_pages(self->fd, self->access_id, 564 access_pages_id)) 565 return -1; 566 567 if (_test_cmd_destroy_access(self->access_id)) 568 return -1; 569 self->access_id = 0; 570 571 if (_test_ioctl_destroy(self->fd, stdev_id)) 572 return -1; 573 return 0; 574 } 575 576 /* device.c */ 577 TEST_FAIL_NTH(basic_fail_nth, device) 578 { 579 struct iommu_test_hw_info info; 580 uint32_t ioas_id; 581 uint32_t ioas_id2; 582 uint32_t stdev_id; 583 uint32_t idev_id; 584 uint32_t hwpt_id; 585 __u64 iova; 586 587 self->fd = open("/dev/iommu", O_RDWR); 588 if (self->fd == -1) 589 return -1; 590 591 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id)) 592 return -1; 593 594 if (_test_ioctl_ioas_alloc(self->fd, &ioas_id2)) 595 return -1; 596 597 iova = MOCK_APERTURE_START; 598 if (_test_ioctl_ioas_map(self->fd, ioas_id, buffer, PAGE_SIZE, &iova, 599 IOMMU_IOAS_MAP_FIXED_IOVA | 600 IOMMU_IOAS_MAP_WRITEABLE | 601 IOMMU_IOAS_MAP_READABLE)) 602 return -1; 603 if (_test_ioctl_ioas_map(self->fd, ioas_id2, buffer, PAGE_SIZE, &iova, 604 IOMMU_IOAS_MAP_FIXED_IOVA | 605 IOMMU_IOAS_MAP_WRITEABLE | 606 IOMMU_IOAS_MAP_READABLE)) 607 return -1; 608 609 fail_nth_enable(); 610 611 if (_test_cmd_mock_domain(self->fd, ioas_id, &stdev_id, NULL, 612 &idev_id)) 613 return -1; 614 615 if (_test_cmd_get_hw_info(self->fd, idev_id, &info, sizeof(info), NULL)) 616 return -1; 617 618 if (_test_cmd_hwpt_alloc(self->fd, idev_id, ioas_id, 0, 0, &hwpt_id, 619 IOMMU_HWPT_DATA_NONE, 0, 0)) 620 return -1; 621 622 if (_test_cmd_mock_domain_replace(self->fd, stdev_id, ioas_id2, NULL)) 623 return -1; 624 625 if (_test_cmd_mock_domain_replace(self->fd, stdev_id, hwpt_id, NULL)) 626 return -1; 627 return 0; 628 } 629 630 TEST_HARNESS_MAIN 631
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.