check_mmap_options.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2020 ARM Limited
  3. #define _GNU_SOURCE
  4. #include <errno.h>
  5. #include <fcntl.h>
  6. #include <signal.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <ucontext.h>
  11. #include <sys/mman.h>
  12. #include <sys/stat.h>
  13. #include <sys/types.h>
  14. #include "kselftest.h"
  15. #include "mte_common_util.h"
  16. #include "mte_def.h"
  17. #define RUNS (MT_TAG_COUNT)
  18. #define UNDERFLOW MT_GRANULE_SIZE
  19. #define OVERFLOW MT_GRANULE_SIZE
  20. #define TAG_CHECK_ON 0
  21. #define TAG_CHECK_OFF 1
  22. static size_t page_size;
  23. static int sizes[] = {
  24. 1, 537, 989, 1269, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,
  25. /* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 0
  26. };
  27. static int check_mte_memory(char *ptr, int size, int mode, int tag_check)
  28. {
  29. mte_initialize_current_context(mode, (uintptr_t)ptr, size);
  30. memset(ptr, '1', size);
  31. mte_wait_after_trig();
  32. if (cur_mte_cxt.fault_valid == true)
  33. return KSFT_FAIL;
  34. mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);
  35. memset(ptr - UNDERFLOW, '2', UNDERFLOW);
  36. mte_wait_after_trig();
  37. if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)
  38. return KSFT_FAIL;
  39. if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)
  40. return KSFT_FAIL;
  41. mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);
  42. memset(ptr + size, '3', OVERFLOW);
  43. mte_wait_after_trig();
  44. if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)
  45. return KSFT_FAIL;
  46. if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)
  47. return KSFT_FAIL;
  48. return KSFT_PASS;
  49. }
  50. static int check_anonymous_memory_mapping(int mem_type, int mode, int mapping, int tag_check)
  51. {
  52. char *ptr, *map_ptr;
  53. int run, result, map_size;
  54. int item = ARRAY_SIZE(sizes);
  55. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
  56. for (run = 0; run < item; run++) {
  57. map_size = sizes[run] + OVERFLOW + UNDERFLOW;
  58. map_ptr = (char *)mte_allocate_memory(map_size, mem_type, mapping, false);
  59. if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS)
  60. return KSFT_FAIL;
  61. ptr = map_ptr + UNDERFLOW;
  62. mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
  63. /* Only mte enabled memory will allow tag insertion */
  64. ptr = mte_insert_tags((void *)ptr, sizes[run]);
  65. if (!ptr || cur_mte_cxt.fault_valid == true) {
  66. ksft_print_msg("FAIL: Insert tags on anonymous mmap memory\n");
  67. munmap((void *)map_ptr, map_size);
  68. return KSFT_FAIL;
  69. }
  70. result = check_mte_memory(ptr, sizes[run], mode, tag_check);
  71. mte_clear_tags((void *)ptr, sizes[run]);
  72. mte_free_memory((void *)map_ptr, map_size, mem_type, false);
  73. if (result == KSFT_FAIL)
  74. return KSFT_FAIL;
  75. }
  76. return KSFT_PASS;
  77. }
  78. static int check_file_memory_mapping(int mem_type, int mode, int mapping, int tag_check)
  79. {
  80. char *ptr, *map_ptr;
  81. int run, fd, map_size;
  82. int total = ARRAY_SIZE(sizes);
  83. int result = KSFT_PASS;
  84. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
  85. for (run = 0; run < total; run++) {
  86. fd = create_temp_file();
  87. if (fd == -1)
  88. return KSFT_FAIL;
  89. map_size = sizes[run] + UNDERFLOW + OVERFLOW;
  90. map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);
  91. if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {
  92. close(fd);
  93. return KSFT_FAIL;
  94. }
  95. ptr = map_ptr + UNDERFLOW;
  96. mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
  97. /* Only mte enabled memory will allow tag insertion */
  98. ptr = mte_insert_tags((void *)ptr, sizes[run]);
  99. if (!ptr || cur_mte_cxt.fault_valid == true) {
  100. ksft_print_msg("FAIL: Insert tags on file based memory\n");
  101. munmap((void *)map_ptr, map_size);
  102. close(fd);
  103. return KSFT_FAIL;
  104. }
  105. result = check_mte_memory(ptr, sizes[run], mode, tag_check);
  106. mte_clear_tags((void *)ptr, sizes[run]);
  107. munmap((void *)map_ptr, map_size);
  108. close(fd);
  109. if (result == KSFT_FAIL)
  110. break;
  111. }
  112. return result;
  113. }
  114. static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping)
  115. {
  116. char *ptr, *map_ptr;
  117. int run, prot_flag, result, fd, map_size;
  118. int total = ARRAY_SIZE(sizes);
  119. prot_flag = PROT_READ | PROT_WRITE;
  120. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
  121. for (run = 0; run < total; run++) {
  122. map_size = sizes[run] + OVERFLOW + UNDERFLOW;
  123. ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,
  124. UNDERFLOW, OVERFLOW);
  125. if (check_allocated_memory_range(ptr, sizes[run], mem_type,
  126. UNDERFLOW, OVERFLOW) != KSFT_PASS)
  127. return KSFT_FAIL;
  128. map_ptr = ptr - UNDERFLOW;
  129. /* Try to clear PROT_MTE property and verify it by tag checking */
  130. if (mprotect(map_ptr, map_size, prot_flag)) {
  131. mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
  132. UNDERFLOW, OVERFLOW);
  133. ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
  134. return KSFT_FAIL;
  135. }
  136. result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON);
  137. mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
  138. if (result != KSFT_PASS)
  139. return KSFT_FAIL;
  140. fd = create_temp_file();
  141. if (fd == -1)
  142. return KSFT_FAIL;
  143. ptr = (char *)mte_allocate_file_memory_tag_range(sizes[run], mem_type, mapping,
  144. UNDERFLOW, OVERFLOW, fd);
  145. if (check_allocated_memory_range(ptr, sizes[run], mem_type,
  146. UNDERFLOW, OVERFLOW) != KSFT_PASS) {
  147. close(fd);
  148. return KSFT_FAIL;
  149. }
  150. map_ptr = ptr - UNDERFLOW;
  151. /* Try to clear PROT_MTE property and verify it by tag checking */
  152. if (mprotect(map_ptr, map_size, prot_flag)) {
  153. ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
  154. mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
  155. UNDERFLOW, OVERFLOW);
  156. close(fd);
  157. return KSFT_FAIL;
  158. }
  159. result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON);
  160. mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
  161. close(fd);
  162. if (result != KSFT_PASS)
  163. return KSFT_FAIL;
  164. }
  165. return KSFT_PASS;
  166. }
  167. int main(int argc, char *argv[])
  168. {
  169. int err;
  170. int item = ARRAY_SIZE(sizes);
  171. err = mte_default_setup();
  172. if (err)
  173. return err;
  174. page_size = getpagesize();
  175. if (!page_size) {
  176. ksft_print_msg("ERR: Unable to get page size\n");
  177. return KSFT_FAIL;
  178. }
  179. sizes[item - 3] = page_size - 1;
  180. sizes[item - 2] = page_size;
  181. sizes[item - 1] = page_size + 1;
  182. /* Register signal handlers */
  183. mte_register_signal(SIGBUS, mte_default_handler);
  184. mte_register_signal(SIGSEGV, mte_default_handler);
  185. /* Set test plan */
  186. ksft_set_plan(22);
  187. mte_enable_pstate_tco();
  188. evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
  189. "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check off\n");
  190. evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
  191. "Check file memory with private mapping, sync error mode, mmap/mprotect memory and tag check off\n");
  192. mte_disable_pstate_tco();
  193. evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_NONE_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
  194. "Check anonymous memory with private mapping, no error mode, mmap memory and tag check off\n");
  195. evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_NONE_ERR, MAP_PRIVATE, TAG_CHECK_OFF),
  196. "Check file memory with private mapping, no error mode, mmap/mprotect memory and tag check off\n");
  197. evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  198. "Check anonymous memory with private mapping, sync error mode, mmap memory and tag check on\n");
  199. evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  200. "Check anonymous memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n");
  201. evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  202. "Check anonymous memory with shared mapping, sync error mode, mmap memory and tag check on\n");
  203. evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  204. "Check anonymous memory with shared mapping, sync error mode, mmap/mprotect memory and tag check on\n");
  205. evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  206. "Check anonymous memory with private mapping, async error mode, mmap memory and tag check on\n");
  207. evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  208. "Check anonymous memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n");
  209. evaluate_test(check_anonymous_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  210. "Check anonymous memory with shared mapping, async error mode, mmap memory and tag check on\n");
  211. evaluate_test(check_anonymous_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  212. "Check anonymous memory with shared mapping, async error mode, mmap/mprotect memory and tag check on\n");
  213. evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  214. "Check file memory with private mapping, sync error mode, mmap memory and tag check on\n");
  215. evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  216. "Check file memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n");
  217. evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  218. "Check file memory with shared mapping, sync error mode, mmap memory and tag check on\n");
  219. evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  220. "Check file memory with shared mapping, sync error mode, mmap/mprotect memory and tag check on\n");
  221. evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  222. "Check file memory with private mapping, async error mode, mmap memory and tag check on\n");
  223. evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_PRIVATE, TAG_CHECK_ON),
  224. "Check file memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n");
  225. evaluate_test(check_file_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  226. "Check file memory with shared mapping, async error mode, mmap memory and tag check on\n");
  227. evaluate_test(check_file_memory_mapping(USE_MPROTECT, MTE_ASYNC_ERR, MAP_SHARED, TAG_CHECK_ON),
  228. "Check file memory with shared mapping, async error mode, mmap/mprotect memory and tag check on\n");
  229. evaluate_test(check_clear_prot_mte_flag(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
  230. "Check clear PROT_MTE flags with private mapping, sync error mode and mmap memory\n");
  231. evaluate_test(check_clear_prot_mte_flag(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
  232. "Check clear PROT_MTE flags with private mapping and sync error mode and mmap/mprotect memory\n");
  233. mte_restore_setup();
  234. ksft_print_cnts();
  235. return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
  236. }