check_user_mem.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2020 ARM Limited
  3. #define _GNU_SOURCE
  4. #include <assert.h>
  5. #include <errno.h>
  6. #include <fcntl.h>
  7. #include <signal.h>
  8. #include <stdlib.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <ucontext.h>
  12. #include <unistd.h>
  13. #include <sys/uio.h>
  14. #include <sys/mman.h>
  15. #include "kselftest.h"
  16. #include "mte_common_util.h"
  17. #include "mte_def.h"
  18. static size_t page_sz;
  19. #define TEST_NAME_MAX 100
  20. enum test_type {
  21. READ_TEST,
  22. WRITE_TEST,
  23. READV_TEST,
  24. WRITEV_TEST,
  25. LAST_TEST,
  26. };
  27. static int check_usermem_access_fault(int mem_type, int mode, int mapping,
  28. int tag_offset, int tag_len,
  29. enum test_type test_type)
  30. {
  31. int fd, i, err;
  32. char val = 'A';
  33. ssize_t len, syscall_len;
  34. void *ptr, *ptr_next;
  35. int fileoff, ptroff, size;
  36. int sizes[] = {1, 2, 3, 8, 16, 32, 4096, page_sz};
  37. err = KSFT_PASS;
  38. len = 2 * page_sz;
  39. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
  40. fd = create_temp_file();
  41. if (fd == -1)
  42. return KSFT_FAIL;
  43. for (i = 0; i < len; i++)
  44. if (write(fd, &val, sizeof(val)) != sizeof(val))
  45. return KSFT_FAIL;
  46. lseek(fd, 0, 0);
  47. ptr = mte_allocate_memory(len, mem_type, mapping, true);
  48. if (check_allocated_memory(ptr, len, mem_type, true) != KSFT_PASS) {
  49. close(fd);
  50. return KSFT_FAIL;
  51. }
  52. mte_initialize_current_context(mode, (uintptr_t)ptr, len);
  53. /* Copy from file into buffer with valid tag */
  54. syscall_len = read(fd, ptr, len);
  55. mte_wait_after_trig();
  56. if (cur_mte_cxt.fault_valid || syscall_len < len)
  57. goto usermem_acc_err;
  58. /* Verify same pattern is read */
  59. for (i = 0; i < len; i++)
  60. if (*(char *)(ptr + i) != val)
  61. break;
  62. if (i < len)
  63. goto usermem_acc_err;
  64. if (!tag_len)
  65. tag_len = len - tag_offset;
  66. /* Tag a part of memory with different value */
  67. ptr_next = (void *)((unsigned long)ptr + tag_offset);
  68. ptr_next = mte_insert_new_tag(ptr_next);
  69. mte_set_tag_address_range(ptr_next, tag_len);
  70. for (fileoff = 0; fileoff < 16; fileoff++) {
  71. for (ptroff = 0; ptroff < 16; ptroff++) {
  72. for (i = 0; i < ARRAY_SIZE(sizes); i++) {
  73. size = sizes[i];
  74. lseek(fd, 0, 0);
  75. /* perform file operation on buffer with invalid tag */
  76. switch (test_type) {
  77. case READ_TEST:
  78. syscall_len = read(fd, ptr + ptroff, size);
  79. break;
  80. case WRITE_TEST:
  81. syscall_len = write(fd, ptr + ptroff, size);
  82. break;
  83. case READV_TEST: {
  84. struct iovec iov[1];
  85. iov[0].iov_base = ptr + ptroff;
  86. iov[0].iov_len = size;
  87. syscall_len = readv(fd, iov, 1);
  88. break;
  89. }
  90. case WRITEV_TEST: {
  91. struct iovec iov[1];
  92. iov[0].iov_base = ptr + ptroff;
  93. iov[0].iov_len = size;
  94. syscall_len = writev(fd, iov, 1);
  95. break;
  96. }
  97. case LAST_TEST:
  98. goto usermem_acc_err;
  99. }
  100. mte_wait_after_trig();
  101. /*
  102. * Accessing user memory in kernel with invalid tag should fail in sync
  103. * mode without fault but may not fail in async mode as per the
  104. * implemented MTE userspace support in Arm64 kernel.
  105. */
  106. if (cur_mte_cxt.fault_valid) {
  107. goto usermem_acc_err;
  108. }
  109. if (mode == MTE_SYNC_ERR && syscall_len < len) {
  110. /* test passed */
  111. } else if (mode == MTE_ASYNC_ERR && syscall_len == size) {
  112. /* test passed */
  113. } else {
  114. goto usermem_acc_err;
  115. }
  116. }
  117. }
  118. }
  119. goto exit;
  120. usermem_acc_err:
  121. err = KSFT_FAIL;
  122. exit:
  123. mte_free_memory((void *)ptr, len, mem_type, true);
  124. close(fd);
  125. return err;
  126. }
  127. void format_test_name(char* name, int name_len, int type, int sync, int map, int len, int offset) {
  128. const char* test_type;
  129. const char* mte_type;
  130. const char* map_type;
  131. switch (type) {
  132. case READ_TEST:
  133. test_type = "read";
  134. break;
  135. case WRITE_TEST:
  136. test_type = "write";
  137. break;
  138. case READV_TEST:
  139. test_type = "readv";
  140. break;
  141. case WRITEV_TEST:
  142. test_type = "writev";
  143. break;
  144. default:
  145. assert(0);
  146. break;
  147. }
  148. switch (sync) {
  149. case MTE_SYNC_ERR:
  150. mte_type = "MTE_SYNC_ERR";
  151. break;
  152. case MTE_ASYNC_ERR:
  153. mte_type = "MTE_ASYNC_ERR";
  154. break;
  155. default:
  156. assert(0);
  157. break;
  158. }
  159. switch (map) {
  160. case MAP_SHARED:
  161. map_type = "MAP_SHARED";
  162. break;
  163. case MAP_PRIVATE:
  164. map_type = "MAP_PRIVATE";
  165. break;
  166. default:
  167. assert(0);
  168. break;
  169. }
  170. snprintf(name, name_len,
  171. "test type: %s, %s, %s, tag len: %d, tag offset: %d\n",
  172. test_type, mte_type, map_type, len, offset);
  173. }
  174. int main(int argc, char *argv[])
  175. {
  176. int err;
  177. int t, s, m, l, o;
  178. int mte_sync[] = {MTE_SYNC_ERR, MTE_ASYNC_ERR};
  179. int maps[] = {MAP_SHARED, MAP_PRIVATE};
  180. int tag_lens[] = {0, MT_GRANULE_SIZE};
  181. int tag_offsets[] = {page_sz, MT_GRANULE_SIZE};
  182. char test_name[TEST_NAME_MAX];
  183. page_sz = getpagesize();
  184. if (!page_sz) {
  185. ksft_print_msg("ERR: Unable to get page size\n");
  186. return KSFT_FAIL;
  187. }
  188. err = mte_default_setup();
  189. if (err)
  190. return err;
  191. /* Register signal handlers */
  192. mte_register_signal(SIGSEGV, mte_default_handler);
  193. /* Set test plan */
  194. ksft_set_plan(64);
  195. for (t = 0; t < LAST_TEST; t++) {
  196. for (s = 0; s < ARRAY_SIZE(mte_sync); s++) {
  197. for (m = 0; m < ARRAY_SIZE(maps); m++) {
  198. for (l = 0; l < ARRAY_SIZE(tag_lens); l++) {
  199. for (o = 0; o < ARRAY_SIZE(tag_offsets); o++) {
  200. int sync = mte_sync[s];
  201. int map = maps[m];
  202. int offset = tag_offsets[o];
  203. int tag_len = tag_lens[l];
  204. int res = check_usermem_access_fault(USE_MMAP, sync,
  205. map, offset,
  206. tag_len, t);
  207. format_test_name(test_name, TEST_NAME_MAX,
  208. t, sync, map, tag_len, offset);
  209. evaluate_test(res, test_name);
  210. }
  211. }
  212. }
  213. }
  214. }
  215. mte_restore_setup();
  216. ksft_print_cnts();
  217. return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
  218. }