map_fixed_noreplace.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Test that MAP_FIXED_NOREPLACE works.
  4. *
  5. * Copyright 2018, Jann Horn <jannh@google.com>
  6. * Copyright 2018, Michael Ellerman, IBM Corporation.
  7. */
  8. #include <sys/mman.h>
  9. #include <errno.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <unistd.h>
  13. #include "kselftest.h"
  14. static void dump_maps(void)
  15. {
  16. char cmd[32];
  17. snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
  18. system(cmd);
  19. }
  20. static unsigned long find_base_addr(unsigned long size)
  21. {
  22. void *addr;
  23. unsigned long flags;
  24. flags = MAP_PRIVATE | MAP_ANONYMOUS;
  25. addr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
  26. if (addr == MAP_FAILED)
  27. ksft_exit_fail_msg("Error: couldn't map the space we need for the test\n");
  28. if (munmap(addr, size) != 0)
  29. ksft_exit_fail_msg("Error: munmap failed\n");
  30. return (unsigned long)addr;
  31. }
  32. int main(void)
  33. {
  34. unsigned long base_addr;
  35. unsigned long flags, addr, size, page_size;
  36. char *p;
  37. ksft_print_header();
  38. ksft_set_plan(9);
  39. page_size = sysconf(_SC_PAGE_SIZE);
  40. /* let's find a base addr that is free before we start the tests */
  41. size = 5 * page_size;
  42. base_addr = find_base_addr(size);
  43. flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE;
  44. /* Check we can map all the areas we need below */
  45. addr = base_addr;
  46. size = 5 * page_size;
  47. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  48. if (p == MAP_FAILED) {
  49. dump_maps();
  50. ksft_exit_fail_msg("Error: couldn't map the space we need for the test\n");
  51. }
  52. if (munmap((void *)addr, 5 * page_size) != 0) {
  53. dump_maps();
  54. ksft_exit_fail_msg("Error: munmap failed!?\n");
  55. }
  56. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  57. ksft_test_result_pass("mmap() 5*PAGE_SIZE at base\n");
  58. addr = base_addr + page_size;
  59. size = 3 * page_size;
  60. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  61. if (p == MAP_FAILED) {
  62. dump_maps();
  63. ksft_exit_fail_msg("Error: first mmap() failed unexpectedly\n");
  64. }
  65. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  66. ksft_test_result_pass("mmap() 3*PAGE_SIZE at base+PAGE_SIZE\n");
  67. /*
  68. * Exact same mapping again:
  69. * base | free | new
  70. * +1 | mapped | new
  71. * +2 | mapped | new
  72. * +3 | mapped | new
  73. * +4 | free | new
  74. */
  75. addr = base_addr;
  76. size = 5 * page_size;
  77. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  78. if (p != MAP_FAILED) {
  79. dump_maps();
  80. ksft_exit_fail_msg("Error:1: mmap() succeeded when it shouldn't have\n");
  81. }
  82. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  83. ksft_test_result_pass("Second mmap() 5*PAGE_SIZE at base\n");
  84. /*
  85. * Second mapping contained within first:
  86. *
  87. * base | free |
  88. * +1 | mapped |
  89. * +2 | mapped | new
  90. * +3 | mapped |
  91. * +4 | free |
  92. */
  93. addr = base_addr + (2 * page_size);
  94. size = page_size;
  95. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  96. if (p != MAP_FAILED) {
  97. dump_maps();
  98. ksft_exit_fail_msg("Error:2: mmap() succeeded when it shouldn't have\n");
  99. }
  100. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  101. ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+PAGE_SIZE\n");
  102. /*
  103. * Overlap end of existing mapping:
  104. * base | free |
  105. * +1 | mapped |
  106. * +2 | mapped |
  107. * +3 | mapped | new
  108. * +4 | free | new
  109. */
  110. addr = base_addr + (3 * page_size);
  111. size = 2 * page_size;
  112. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  113. if (p != MAP_FAILED) {
  114. dump_maps();
  115. ksft_exit_fail_msg("Error:3: mmap() succeeded when it shouldn't have\n");
  116. }
  117. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  118. ksft_test_result_pass("mmap() 2*PAGE_SIZE at base+(3*PAGE_SIZE)\n");
  119. /*
  120. * Overlap start of existing mapping:
  121. * base | free | new
  122. * +1 | mapped | new
  123. * +2 | mapped |
  124. * +3 | mapped |
  125. * +4 | free |
  126. */
  127. addr = base_addr;
  128. size = 2 * page_size;
  129. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  130. if (p != MAP_FAILED) {
  131. dump_maps();
  132. ksft_exit_fail_msg("Error:4: mmap() succeeded when it shouldn't have\n");
  133. }
  134. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  135. ksft_test_result_pass("mmap() 2*PAGE_SIZE bytes at base\n");
  136. /*
  137. * Adjacent to start of existing mapping:
  138. * base | free | new
  139. * +1 | mapped |
  140. * +2 | mapped |
  141. * +3 | mapped |
  142. * +4 | free |
  143. */
  144. addr = base_addr;
  145. size = page_size;
  146. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  147. if (p == MAP_FAILED) {
  148. dump_maps();
  149. ksft_exit_fail_msg("Error:5: mmap() failed when it shouldn't have\n");
  150. }
  151. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  152. ksft_test_result_pass("mmap() PAGE_SIZE at base\n");
  153. /*
  154. * Adjacent to end of existing mapping:
  155. * base | free |
  156. * +1 | mapped |
  157. * +2 | mapped |
  158. * +3 | mapped |
  159. * +4 | free | new
  160. */
  161. addr = base_addr + (4 * page_size);
  162. size = page_size;
  163. p = mmap((void *)addr, size, PROT_NONE, flags, -1, 0);
  164. if (p == MAP_FAILED) {
  165. dump_maps();
  166. ksft_exit_fail_msg("Error:6: mmap() failed when it shouldn't have\n");
  167. }
  168. ksft_print_msg("mmap() @ 0x%lx-0x%lx p=%p result=%m\n", addr, addr + size, p);
  169. ksft_test_result_pass("mmap() PAGE_SIZE at base+(4*PAGE_SIZE)\n");
  170. addr = base_addr;
  171. size = 5 * page_size;
  172. if (munmap((void *)addr, size) != 0) {
  173. dump_maps();
  174. ksft_exit_fail_msg("Error: munmap failed!?\n");
  175. }
  176. ksft_test_result_pass("Base Address unmap() successful\n");
  177. ksft_finished();
  178. }