TestEFault.cpp 5.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, Andrew Kaster <akaster@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Assertions.h>
  8. #include <AK/Format.h>
  9. #include <AK/Types.h>
  10. #include <LibTest/TestCase.h>
  11. #include <errno.h>
  12. #include <fcntl.h>
  13. #include <stdio.h>
  14. #include <sys/mman.h>
  15. #include <unistd.h>
  16. #define EXPECT_OK(syscall, address, size) \
  17. do { \
  18. rc = syscall(fd, (void*)(address), (size_t)(size)); \
  19. EXPECT(rc >= 0); \
  20. if (rc < 0) { \
  21. warnln("Expected success: " #syscall "({:p}, {}), got rc={}, errno={}", (void*)(address), (size_t)(size), rc, errno); \
  22. } \
  23. } while (0)
  24. #define EXPECT_EFAULT(syscall, address, size) \
  25. do { \
  26. rc = syscall(fd, (void*)(address), (size_t)(size)); \
  27. EXPECT(rc < 0); \
  28. EXPECT_EQ(errno, EFAULT); \
  29. if (rc >= 0 || errno != EFAULT) { \
  30. warnln("Expected EFAULT: " #syscall "({:p}, {}), got rc={}, errno={}", (void*)(address), (size_t)(size), rc, errno); \
  31. } \
  32. } while (0)
  33. #define EXPECT_EFAULT_NO_FD(syscall, address, size) \
  34. do { \
  35. rc = syscall((address), (size_t)(size)); \
  36. EXPECT(rc < 0); \
  37. EXPECT_EQ(errno, EFAULT); \
  38. if (rc >= 0 || errno != EFAULT) { \
  39. warnln("Expected EFAULT: " #syscall "({:p}, {}), got rc={}, errno={}", (void*)(address), (size_t)(size), rc, errno); \
  40. } \
  41. } while (0)
  42. TEST_CASE(test_efault)
  43. {
  44. int fd = open("/dev/zero", O_RDONLY);
  45. int rc = -1;
  46. // Test a one-page mapping (4KB)
  47. u8* one_page = (u8*)mmap(nullptr, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  48. VERIFY(one_page);
  49. EXPECT_OK(read, one_page, 4096);
  50. EXPECT_EFAULT(read, one_page, 4097);
  51. EXPECT_EFAULT(read, one_page - 1, 4096);
  52. // Test a two-page mapping (8KB)
  53. u8* two_page = (u8*)mmap(nullptr, 8192, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
  54. VERIFY(two_page);
  55. EXPECT_OK(read, two_page, 4096);
  56. EXPECT_OK(read, two_page + 4096, 4096);
  57. EXPECT_OK(read, two_page, 8192);
  58. EXPECT_OK(read, two_page + 4095, 4097);
  59. EXPECT_OK(read, two_page + 1, 8191);
  60. EXPECT_EFAULT(read, two_page, 8193);
  61. EXPECT_EFAULT(read, two_page - 1, 1);
  62. // Check validation of pages between the first and last address.
  63. ptrdiff_t distance = two_page - one_page;
  64. EXPECT_EFAULT(read, one_page, (u32)distance + 1024);
  65. constexpr auto user_range_ceiling = (sizeof(void*) == 4 ? 0xbe000000u : 0x1ffe000000);
  66. u8* jerk_page = nullptr;
  67. // Test every kernel page just because.
  68. constexpr auto kernel_range_ceiling = (sizeof(void*) == 4 ? 0xffffffffu : 0x203fffffff);
  69. for (u64 kernel_address = user_range_ceiling; kernel_address <= kernel_range_ceiling; kernel_address += PAGE_SIZE) {
  70. jerk_page = (u8*)mmap((void*)kernel_address, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, 0, 0);
  71. EXPECT_EQ(jerk_page, MAP_FAILED);
  72. EXPECT_EQ(errno, EFAULT);
  73. }
  74. // Test the page just below where the user VM ends.
  75. jerk_page = (u8*)mmap((void*)(user_range_ceiling - PAGE_SIZE), PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, 0, 0);
  76. EXPECT_EQ(jerk_page, (u8*)(user_range_ceiling - PAGE_SIZE));
  77. EXPECT_OK(read, jerk_page, PAGE_SIZE);
  78. EXPECT_EFAULT(read, jerk_page, PAGE_SIZE + 1);
  79. // Test something that would wrap around the 2^32 mark.
  80. EXPECT_EFAULT(read, jerk_page, 0x50000000);
  81. }