check_buffer_fill.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2020 ARM Limited
  3. #define _GNU_SOURCE
  4. #include <stddef.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #include "kselftest.h"
  8. #include "mte_common_util.h"
  9. #include "mte_def.h"
  10. #define OVERFLOW_RANGE MT_GRANULE_SIZE
  11. static int sizes[] = {
  12. 1, 555, 1033, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,
  13. /* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 0
  14. };
  15. enum mte_block_test_alloc {
  16. UNTAGGED_TAGGED,
  17. TAGGED_UNTAGGED,
  18. TAGGED_TAGGED,
  19. BLOCK_ALLOC_MAX,
  20. };
  21. static int check_buffer_by_byte(int mem_type, int mode)
  22. {
  23. char *ptr;
  24. int i, j, item;
  25. bool err;
  26. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);
  27. item = ARRAY_SIZE(sizes);
  28. for (i = 0; i < item; i++) {
  29. ptr = (char *)mte_allocate_memory(sizes[i], mem_type, 0, true);
  30. if (check_allocated_memory(ptr, sizes[i], mem_type, true) != KSFT_PASS)
  31. return KSFT_FAIL;
  32. mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[i]);
  33. /* Set some value in tagged memory */
  34. for (j = 0; j < sizes[i]; j++)
  35. ptr[j] = '1';
  36. mte_wait_after_trig();
  37. err = cur_mte_cxt.fault_valid;
  38. /* Check the buffer whether it is filled. */
  39. for (j = 0; j < sizes[i] && !err; j++) {
  40. if (ptr[j] != '1')
  41. err = true;
  42. }
  43. mte_free_memory((void *)ptr, sizes[i], mem_type, true);
  44. if (err)
  45. break;
  46. }
  47. if (!err)
  48. return KSFT_PASS;
  49. else
  50. return KSFT_FAIL;
  51. }
  52. static int check_buffer_underflow_by_byte(int mem_type, int mode,
  53. int underflow_range)
  54. {
  55. char *ptr;
  56. int i, j, item, last_index;
  57. bool err;
  58. char *und_ptr = NULL;
  59. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);
  60. item = ARRAY_SIZE(sizes);
  61. for (i = 0; i < item; i++) {
  62. ptr = (char *)mte_allocate_memory_tag_range(sizes[i], mem_type, 0,
  63. underflow_range, 0);
  64. if (check_allocated_memory_range(ptr, sizes[i], mem_type,
  65. underflow_range, 0) != KSFT_PASS)
  66. return KSFT_FAIL;
  67. mte_initialize_current_context(mode, (uintptr_t)ptr, -underflow_range);
  68. last_index = 0;
  69. /* Set some value in tagged memory and make the buffer underflow */
  70. for (j = sizes[i] - 1; (j >= -underflow_range) &&
  71. (!cur_mte_cxt.fault_valid); j--) {
  72. ptr[j] = '1';
  73. last_index = j;
  74. }
  75. mte_wait_after_trig();
  76. err = false;
  77. /* Check whether the buffer is filled */
  78. for (j = 0; j < sizes[i]; j++) {
  79. if (ptr[j] != '1') {
  80. err = true;
  81. ksft_print_msg("Buffer is not filled at index:%d of ptr:0x%p\n",
  82. j, ptr);
  83. break;
  84. }
  85. }
  86. if (err)
  87. goto check_buffer_underflow_by_byte_err;
  88. switch (mode) {
  89. case MTE_NONE_ERR:
  90. if (cur_mte_cxt.fault_valid == true || last_index != -underflow_range) {
  91. err = true;
  92. break;
  93. }
  94. /* There were no fault so the underflow area should be filled */
  95. und_ptr = (char *) MT_CLEAR_TAG((size_t) ptr - underflow_range);
  96. for (j = 0 ; j < underflow_range; j++) {
  97. if (und_ptr[j] != '1') {
  98. err = true;
  99. break;
  100. }
  101. }
  102. break;
  103. case MTE_ASYNC_ERR:
  104. /* Imprecise fault should occur otherwise return error */
  105. if (cur_mte_cxt.fault_valid == false) {
  106. err = true;
  107. break;
  108. }
  109. /*
  110. * The imprecise fault is checked after the write to the buffer,
  111. * so the underflow area before the fault should be filled.
  112. */
  113. und_ptr = (char *) MT_CLEAR_TAG((size_t) ptr);
  114. for (j = last_index ; j < 0 ; j++) {
  115. if (und_ptr[j] != '1') {
  116. err = true;
  117. break;
  118. }
  119. }
  120. break;
  121. case MTE_SYNC_ERR:
  122. /* Precise fault should occur otherwise return error */
  123. if (!cur_mte_cxt.fault_valid || (last_index != (-1))) {
  124. err = true;
  125. break;
  126. }
  127. /* Underflow area should not be filled */
  128. und_ptr = (char *) MT_CLEAR_TAG((size_t) ptr);
  129. if (und_ptr[-1] == '1')
  130. err = true;
  131. break;
  132. default:
  133. err = true;
  134. break;
  135. }
  136. check_buffer_underflow_by_byte_err:
  137. mte_free_memory_tag_range((void *)ptr, sizes[i], mem_type, underflow_range, 0);
  138. if (err)
  139. break;
  140. }
  141. return (err ? KSFT_FAIL : KSFT_PASS);
  142. }
  143. static int check_buffer_overflow_by_byte(int mem_type, int mode,
  144. int overflow_range)
  145. {
  146. char *ptr;
  147. int i, j, item, last_index;
  148. bool err;
  149. size_t tagged_size, overflow_size;
  150. char *over_ptr = NULL;
  151. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);
  152. item = ARRAY_SIZE(sizes);
  153. for (i = 0; i < item; i++) {
  154. ptr = (char *)mte_allocate_memory_tag_range(sizes[i], mem_type, 0,
  155. 0, overflow_range);
  156. if (check_allocated_memory_range(ptr, sizes[i], mem_type,
  157. 0, overflow_range) != KSFT_PASS)
  158. return KSFT_FAIL;
  159. tagged_size = MT_ALIGN_UP(sizes[i]);
  160. mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[i] + overflow_range);
  161. /* Set some value in tagged memory and make the buffer underflow */
  162. for (j = 0, last_index = 0 ; (j < (sizes[i] + overflow_range)) &&
  163. (cur_mte_cxt.fault_valid == false); j++) {
  164. ptr[j] = '1';
  165. last_index = j;
  166. }
  167. mte_wait_after_trig();
  168. err = false;
  169. /* Check whether the buffer is filled */
  170. for (j = 0; j < sizes[i]; j++) {
  171. if (ptr[j] != '1') {
  172. err = true;
  173. ksft_print_msg("Buffer is not filled at index:%d of ptr:0x%p\n",
  174. j, ptr);
  175. break;
  176. }
  177. }
  178. if (err)
  179. goto check_buffer_overflow_by_byte_err;
  180. overflow_size = overflow_range - (tagged_size - sizes[i]);
  181. switch (mode) {
  182. case MTE_NONE_ERR:
  183. if ((cur_mte_cxt.fault_valid == true) ||
  184. (last_index != (sizes[i] + overflow_range - 1))) {
  185. err = true;
  186. break;
  187. }
  188. /* There were no fault so the overflow area should be filled */
  189. over_ptr = (char *) MT_CLEAR_TAG((size_t) ptr + tagged_size);
  190. for (j = 0 ; j < overflow_size; j++) {
  191. if (over_ptr[j] != '1') {
  192. err = true;
  193. break;
  194. }
  195. }
  196. break;
  197. case MTE_ASYNC_ERR:
  198. /* Imprecise fault should occur otherwise return error */
  199. if (cur_mte_cxt.fault_valid == false) {
  200. err = true;
  201. break;
  202. }
  203. /*
  204. * The imprecise fault is checked after the write to the buffer,
  205. * so the overflow area should be filled before the fault.
  206. */
  207. over_ptr = (char *) MT_CLEAR_TAG((size_t) ptr);
  208. for (j = tagged_size ; j < last_index; j++) {
  209. if (over_ptr[j] != '1') {
  210. err = true;
  211. break;
  212. }
  213. }
  214. break;
  215. case MTE_SYNC_ERR:
  216. /* Precise fault should occur otherwise return error */
  217. if (!cur_mte_cxt.fault_valid || (last_index != tagged_size)) {
  218. err = true;
  219. break;
  220. }
  221. /* Underflow area should not be filled */
  222. over_ptr = (char *) MT_CLEAR_TAG((size_t) ptr + tagged_size);
  223. for (j = 0 ; j < overflow_size; j++) {
  224. if (over_ptr[j] == '1')
  225. err = true;
  226. }
  227. break;
  228. default:
  229. err = true;
  230. break;
  231. }
  232. check_buffer_overflow_by_byte_err:
  233. mte_free_memory_tag_range((void *)ptr, sizes[i], mem_type, 0, overflow_range);
  234. if (err)
  235. break;
  236. }
  237. return (err ? KSFT_FAIL : KSFT_PASS);
  238. }
  239. static int check_buffer_by_block_iterate(int mem_type, int mode, size_t size)
  240. {
  241. char *src, *dst;
  242. int j, result = KSFT_PASS;
  243. enum mte_block_test_alloc alloc_type = UNTAGGED_TAGGED;
  244. for (alloc_type = UNTAGGED_TAGGED; alloc_type < (int) BLOCK_ALLOC_MAX; alloc_type++) {
  245. switch (alloc_type) {
  246. case UNTAGGED_TAGGED:
  247. src = (char *)mte_allocate_memory(size, mem_type, 0, false);
  248. if (check_allocated_memory(src, size, mem_type, false) != KSFT_PASS)
  249. return KSFT_FAIL;
  250. dst = (char *)mte_allocate_memory(size, mem_type, 0, true);
  251. if (check_allocated_memory(dst, size, mem_type, true) != KSFT_PASS) {
  252. mte_free_memory((void *)src, size, mem_type, false);
  253. return KSFT_FAIL;
  254. }
  255. break;
  256. case TAGGED_UNTAGGED:
  257. dst = (char *)mte_allocate_memory(size, mem_type, 0, false);
  258. if (check_allocated_memory(dst, size, mem_type, false) != KSFT_PASS)
  259. return KSFT_FAIL;
  260. src = (char *)mte_allocate_memory(size, mem_type, 0, true);
  261. if (check_allocated_memory(src, size, mem_type, true) != KSFT_PASS) {
  262. mte_free_memory((void *)dst, size, mem_type, false);
  263. return KSFT_FAIL;
  264. }
  265. break;
  266. case TAGGED_TAGGED:
  267. src = (char *)mte_allocate_memory(size, mem_type, 0, true);
  268. if (check_allocated_memory(src, size, mem_type, true) != KSFT_PASS)
  269. return KSFT_FAIL;
  270. dst = (char *)mte_allocate_memory(size, mem_type, 0, true);
  271. if (check_allocated_memory(dst, size, mem_type, true) != KSFT_PASS) {
  272. mte_free_memory((void *)src, size, mem_type, true);
  273. return KSFT_FAIL;
  274. }
  275. break;
  276. default:
  277. return KSFT_FAIL;
  278. }
  279. cur_mte_cxt.fault_valid = false;
  280. result = KSFT_PASS;
  281. mte_initialize_current_context(mode, (uintptr_t)dst, size);
  282. /* Set some value in memory and copy*/
  283. memset((void *)src, (int)'1', size);
  284. memcpy((void *)dst, (void *)src, size);
  285. mte_wait_after_trig();
  286. if (cur_mte_cxt.fault_valid) {
  287. result = KSFT_FAIL;
  288. goto check_buffer_by_block_err;
  289. }
  290. /* Check the buffer whether it is filled. */
  291. for (j = 0; j < size; j++) {
  292. if (src[j] != dst[j] || src[j] != '1') {
  293. result = KSFT_FAIL;
  294. break;
  295. }
  296. }
  297. check_buffer_by_block_err:
  298. mte_free_memory((void *)src, size, mem_type,
  299. MT_FETCH_TAG((uintptr_t)src) ? true : false);
  300. mte_free_memory((void *)dst, size, mem_type,
  301. MT_FETCH_TAG((uintptr_t)dst) ? true : false);
  302. if (result != KSFT_PASS)
  303. return result;
  304. }
  305. return result;
  306. }
  307. static int check_buffer_by_block(int mem_type, int mode)
  308. {
  309. int i, item, result = KSFT_PASS;
  310. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);
  311. item = ARRAY_SIZE(sizes);
  312. cur_mte_cxt.fault_valid = false;
  313. for (i = 0; i < item; i++) {
  314. result = check_buffer_by_block_iterate(mem_type, mode, sizes[i]);
  315. if (result != KSFT_PASS)
  316. break;
  317. }
  318. return result;
  319. }
  320. static int compare_memory_tags(char *ptr, size_t size, int tag)
  321. {
  322. int i, new_tag;
  323. for (i = 0 ; i < size ; i += MT_GRANULE_SIZE) {
  324. new_tag = MT_FETCH_TAG((uintptr_t)(mte_get_tag_address(ptr + i)));
  325. if (tag != new_tag) {
  326. ksft_print_msg("FAIL: child mte tag mismatch\n");
  327. return KSFT_FAIL;
  328. }
  329. }
  330. return KSFT_PASS;
  331. }
  332. static int check_memory_initial_tags(int mem_type, int mode, int mapping)
  333. {
  334. char *ptr;
  335. int run, fd;
  336. int total = ARRAY_SIZE(sizes);
  337. mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);
  338. for (run = 0; run < total; run++) {
  339. /* check initial tags for anonymous mmap */
  340. ptr = (char *)mte_allocate_memory(sizes[run], mem_type, mapping, false);
  341. if (check_allocated_memory(ptr, sizes[run], mem_type, false) != KSFT_PASS)
  342. return KSFT_FAIL;
  343. if (compare_memory_tags(ptr, sizes[run], 0) != KSFT_PASS) {
  344. mte_free_memory((void *)ptr, sizes[run], mem_type, false);
  345. return KSFT_FAIL;
  346. }
  347. mte_free_memory((void *)ptr, sizes[run], mem_type, false);
  348. /* check initial tags for file mmap */
  349. fd = create_temp_file();
  350. if (fd == -1)
  351. return KSFT_FAIL;
  352. ptr = (char *)mte_allocate_file_memory(sizes[run], mem_type, mapping, false, fd);
  353. if (check_allocated_memory(ptr, sizes[run], mem_type, false) != KSFT_PASS) {
  354. close(fd);
  355. return KSFT_FAIL;
  356. }
  357. if (compare_memory_tags(ptr, sizes[run], 0) != KSFT_PASS) {
  358. mte_free_memory((void *)ptr, sizes[run], mem_type, false);
  359. close(fd);
  360. return KSFT_FAIL;
  361. }
  362. mte_free_memory((void *)ptr, sizes[run], mem_type, false);
  363. close(fd);
  364. }
  365. return KSFT_PASS;
  366. }
  367. int main(int argc, char *argv[])
  368. {
  369. int err;
  370. size_t page_size = getpagesize();
  371. int item = ARRAY_SIZE(sizes);
  372. sizes[item - 3] = page_size - 1;
  373. sizes[item - 2] = page_size;
  374. sizes[item - 1] = page_size + 1;
  375. err = mte_default_setup();
  376. if (err)
  377. return err;
  378. /* Register SIGSEGV handler */
  379. mte_register_signal(SIGSEGV, mte_default_handler, false);
  380. /* Set test plan */
  381. ksft_set_plan(20);
  382. /* Buffer by byte tests */
  383. evaluate_test(check_buffer_by_byte(USE_MMAP, MTE_SYNC_ERR),
  384. "Check buffer correctness by byte with sync err mode and mmap memory\n");
  385. evaluate_test(check_buffer_by_byte(USE_MMAP, MTE_ASYNC_ERR),
  386. "Check buffer correctness by byte with async err mode and mmap memory\n");
  387. evaluate_test(check_buffer_by_byte(USE_MPROTECT, MTE_SYNC_ERR),
  388. "Check buffer correctness by byte with sync err mode and mmap/mprotect memory\n");
  389. evaluate_test(check_buffer_by_byte(USE_MPROTECT, MTE_ASYNC_ERR),
  390. "Check buffer correctness by byte with async err mode and mmap/mprotect memory\n");
  391. /* Check buffer underflow with underflow size as 16 */
  392. evaluate_test(check_buffer_underflow_by_byte(USE_MMAP, MTE_SYNC_ERR, MT_GRANULE_SIZE),
  393. "Check buffer write underflow by byte with sync mode and mmap memory\n");
  394. evaluate_test(check_buffer_underflow_by_byte(USE_MMAP, MTE_ASYNC_ERR, MT_GRANULE_SIZE),
  395. "Check buffer write underflow by byte with async mode and mmap memory\n");
  396. evaluate_test(check_buffer_underflow_by_byte(USE_MMAP, MTE_NONE_ERR, MT_GRANULE_SIZE),
  397. "Check buffer write underflow by byte with tag check fault ignore and mmap memory\n");
  398. /* Check buffer underflow with underflow size as page size */
  399. evaluate_test(check_buffer_underflow_by_byte(USE_MMAP, MTE_SYNC_ERR, page_size),
  400. "Check buffer write underflow by byte with sync mode and mmap memory\n");
  401. evaluate_test(check_buffer_underflow_by_byte(USE_MMAP, MTE_ASYNC_ERR, page_size),
  402. "Check buffer write underflow by byte with async mode and mmap memory\n");
  403. evaluate_test(check_buffer_underflow_by_byte(USE_MMAP, MTE_NONE_ERR, page_size),
  404. "Check buffer write underflow by byte with tag check fault ignore and mmap memory\n");
  405. /* Check buffer overflow with overflow size as 16 */
  406. evaluate_test(check_buffer_overflow_by_byte(USE_MMAP, MTE_SYNC_ERR, MT_GRANULE_SIZE),
  407. "Check buffer write overflow by byte with sync mode and mmap memory\n");
  408. evaluate_test(check_buffer_overflow_by_byte(USE_MMAP, MTE_ASYNC_ERR, MT_GRANULE_SIZE),
  409. "Check buffer write overflow by byte with async mode and mmap memory\n");
  410. evaluate_test(check_buffer_overflow_by_byte(USE_MMAP, MTE_NONE_ERR, MT_GRANULE_SIZE),
  411. "Check buffer write overflow by byte with tag fault ignore mode and mmap memory\n");
  412. /* Buffer by block tests */
  413. evaluate_test(check_buffer_by_block(USE_MMAP, MTE_SYNC_ERR),
  414. "Check buffer write correctness by block with sync mode and mmap memory\n");
  415. evaluate_test(check_buffer_by_block(USE_MMAP, MTE_ASYNC_ERR),
  416. "Check buffer write correctness by block with async mode and mmap memory\n");
  417. evaluate_test(check_buffer_by_block(USE_MMAP, MTE_NONE_ERR),
  418. "Check buffer write correctness by block with tag fault ignore and mmap memory\n");
  419. /* Initial tags are supposed to be 0 */
  420. evaluate_test(check_memory_initial_tags(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
  421. "Check initial tags with private mapping, sync error mode and mmap memory\n");
  422. evaluate_test(check_memory_initial_tags(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
  423. "Check initial tags with private mapping, sync error mode and mmap/mprotect memory\n");
  424. evaluate_test(check_memory_initial_tags(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
  425. "Check initial tags with shared mapping, sync error mode and mmap memory\n");
  426. evaluate_test(check_memory_initial_tags(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED),
  427. "Check initial tags with shared mapping, sync error mode and mmap/mprotect memory\n");
  428. mte_restore_setup();
  429. ksft_print_cnts();
  430. return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
  431. }