1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2020 ARM Limited
3
4 #define _GNU_SOURCE
5
6 #include <assert.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <ucontext.h>
14 #include <sys/mman.h>
15 #include <sys/stat.h>
16 #include <sys/types.h>
17
18 #include "kselftest.h"
19 #include "mte_common_util.h"
20 #include "mte_def.h"
21
22 #define RUNS (MT_TAG_COUNT)
23 #define UNDERFLOW MT_GRANULE_SIZE
24 #define OVERFLOW MT_GRANULE_SIZE
25 #define TAG_CHECK_ON 0
26 #define TAG_CHECK_OFF 1
27 #define ATAG_CHECK_ON 1
28 #define ATAG_CHECK_OFF 0
29
30 #define TEST_NAME_MAX 256
31
32 enum mte_mem_check_type {
33 CHECK_ANON_MEM = 0,
34 CHECK_FILE_MEM = 1,
35 CHECK_CLEAR_PROT_MTE = 2,
36 };
37
38 enum mte_tag_op_type {
39 TAG_OP_ALL = 0,
40 TAG_OP_STONLY = 1,
41 };
42
43 struct check_mmap_testcase {
44 int check_type;
45 int mem_type;
46 int mte_sync;
47 int mapping;
48 int tag_check;
49 int atag_check;
50 int tag_op;
51 bool enable_tco;
52 };
53
54 #define TAG_OP_ALL 0
55 #define TAG_OP_STONLY 1
56
57 static size_t page_size;
58 static int sizes[] = {
59 1, 537, 989, 1269, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,
60 /* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 0
61 };
62
check_mte_memory(char * ptr,int size,int mode,int tag_check,int atag_check,int tag_op)63 static int check_mte_memory(char *ptr, int size, int mode,
64 int tag_check,int atag_check, int tag_op)
65 {
66 char buf[MT_GRANULE_SIZE];
67
68 if (!mtefar_support && atag_check == ATAG_CHECK_ON)
69 return KSFT_SKIP;
70
71 if (atag_check == ATAG_CHECK_ON)
72 ptr = mte_insert_atag(ptr);
73
74 mte_initialize_current_context(mode, (uintptr_t)ptr, size);
75 memset(ptr, '1', size);
76 mte_wait_after_trig();
77 if (cur_mte_cxt.fault_valid == true)
78 return KSFT_FAIL;
79
80 mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);
81 memset(ptr - UNDERFLOW, '2', UNDERFLOW);
82 mte_wait_after_trig();
83 if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)
84 return KSFT_FAIL;
85 if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)
86 return KSFT_FAIL;
87
88 mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);
89 memset(ptr + size, '3', OVERFLOW);
90 mte_wait_after_trig();
91 if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)
92 return KSFT_FAIL;
93 if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)
94 return KSFT_FAIL;
95
96 if (tag_op == TAG_OP_STONLY) {
97 mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);
98 memcpy(buf, ptr - UNDERFLOW, MT_GRANULE_SIZE);
99 mte_wait_after_trig();
100 if (cur_mte_cxt.fault_valid == true)
101 return KSFT_FAIL;
102
103 mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);
104 memcpy(buf, ptr + size, MT_GRANULE_SIZE);
105 mte_wait_after_trig();
106 if (cur_mte_cxt.fault_valid == true)
107 return KSFT_FAIL;
108 }
109
110 return KSFT_PASS;
111 }
112
check_anonymous_memory_mapping(int mem_type,int mode,int mapping,int tag_check,int atag_check,int tag_op)113 static int check_anonymous_memory_mapping(int mem_type, int mode, int mapping,
114 int tag_check, int atag_check, int tag_op)
115 {
116 char *ptr, *map_ptr;
117 int run, result, map_size;
118 int item = ARRAY_SIZE(sizes);
119
120 if (tag_op == TAG_OP_STONLY && !mtestonly_support)
121 return KSFT_SKIP;
122
123 mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, tag_op);
124 for (run = 0; run < item; run++) {
125 map_size = sizes[run] + OVERFLOW + UNDERFLOW;
126 map_ptr = (char *)mte_allocate_memory(map_size, mem_type, mapping, false);
127 if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS)
128 return KSFT_FAIL;
129
130 ptr = map_ptr + UNDERFLOW;
131 mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
132 /* Only mte enabled memory will allow tag insertion */
133 ptr = mte_insert_tags((void *)ptr, sizes[run]);
134 if (!ptr || cur_mte_cxt.fault_valid == true) {
135 ksft_print_msg("FAIL: Insert tags on anonymous mmap memory\n");
136 munmap((void *)map_ptr, map_size);
137 return KSFT_FAIL;
138 }
139 result = check_mte_memory(ptr, sizes[run], mode, tag_check, atag_check, tag_op);
140 mte_clear_tags((void *)ptr, sizes[run]);
141 mte_free_memory((void *)map_ptr, map_size, mem_type, false);
142 if (result != KSFT_PASS)
143 return result;
144 }
145 return KSFT_PASS;
146 }
147
check_file_memory_mapping(int mem_type,int mode,int mapping,int tag_check,int atag_check,int tag_op)148 static int check_file_memory_mapping(int mem_type, int mode, int mapping,
149 int tag_check, int atag_check, int tag_op)
150 {
151 char *ptr, *map_ptr;
152 int run, fd, map_size;
153 int total = ARRAY_SIZE(sizes);
154 int result = KSFT_PASS;
155
156 if (tag_op == TAG_OP_STONLY && !mtestonly_support)
157 return KSFT_SKIP;
158
159 mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, tag_op);
160 for (run = 0; run < total; run++) {
161 fd = create_temp_file();
162 if (fd == -1)
163 return KSFT_FAIL;
164
165 map_size = sizes[run] + UNDERFLOW + OVERFLOW;
166 map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);
167 if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {
168 close(fd);
169 return KSFT_FAIL;
170 }
171 ptr = map_ptr + UNDERFLOW;
172 mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
173 /* Only mte enabled memory will allow tag insertion */
174 ptr = mte_insert_tags((void *)ptr, sizes[run]);
175 if (!ptr || cur_mte_cxt.fault_valid == true) {
176 ksft_print_msg("FAIL: Insert tags on file based memory\n");
177 munmap((void *)map_ptr, map_size);
178 close(fd);
179 return KSFT_FAIL;
180 }
181 result = check_mte_memory(ptr, sizes[run], mode, tag_check, atag_check, tag_op);
182 mte_clear_tags((void *)ptr, sizes[run]);
183 munmap((void *)map_ptr, map_size);
184 close(fd);
185 if (result != KSFT_PASS)
186 return result;
187 }
188 return KSFT_PASS;
189 }
190
check_clear_prot_mte_flag(int mem_type,int mode,int mapping,int atag_check)191 static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping, int atag_check)
192 {
193 char *ptr, *map_ptr;
194 int run, prot_flag, result, fd, map_size;
195 int total = ARRAY_SIZE(sizes);
196
197 prot_flag = PROT_READ | PROT_WRITE;
198 mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG, false);
199 for (run = 0; run < total; run++) {
200 map_size = sizes[run] + OVERFLOW + UNDERFLOW;
201 ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,
202 UNDERFLOW, OVERFLOW);
203 if (check_allocated_memory_range(ptr, sizes[run], mem_type,
204 UNDERFLOW, OVERFLOW) != KSFT_PASS)
205 return KSFT_FAIL;
206 map_ptr = ptr - UNDERFLOW;
207 /* Try to clear PROT_MTE property and verify it by tag checking */
208 if (mprotect(map_ptr, map_size, prot_flag)) {
209 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
210 UNDERFLOW, OVERFLOW);
211 ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
212 return KSFT_FAIL;
213 }
214 result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON, atag_check, TAG_OP_ALL);
215 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
216 if (result != KSFT_PASS)
217 return result;
218
219 fd = create_temp_file();
220 if (fd == -1)
221 return KSFT_FAIL;
222 ptr = (char *)mte_allocate_file_memory_tag_range(sizes[run], mem_type, mapping,
223 UNDERFLOW, OVERFLOW, fd);
224 if (check_allocated_memory_range(ptr, sizes[run], mem_type,
225 UNDERFLOW, OVERFLOW) != KSFT_PASS) {
226 close(fd);
227 return KSFT_FAIL;
228 }
229 map_ptr = ptr - UNDERFLOW;
230 /* Try to clear PROT_MTE property and verify it by tag checking */
231 if (mprotect(map_ptr, map_size, prot_flag)) {
232 ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
233 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
234 UNDERFLOW, OVERFLOW);
235 close(fd);
236 return KSFT_FAIL;
237 }
238 result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON, atag_check, TAG_OP_ALL);
239 mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
240 close(fd);
241 if (result != KSFT_PASS)
242 return result;
243 }
244 return KSFT_PASS;
245 }
246
format_test_name(struct check_mmap_testcase * tc)247 const char *format_test_name(struct check_mmap_testcase *tc)
248 {
249 static char test_name[TEST_NAME_MAX];
250 const char *check_type_str;
251 const char *mem_type_str;
252 const char *sync_str;
253 const char *mapping_str;
254 const char *tag_check_str;
255 const char *atag_check_str;
256 const char *tag_op_str;
257
258 switch (tc->check_type) {
259 case CHECK_ANON_MEM:
260 check_type_str = "anonymous memory";
261 break;
262 case CHECK_FILE_MEM:
263 check_type_str = "file memory";
264 break;
265 case CHECK_CLEAR_PROT_MTE:
266 check_type_str = "clear PROT_MTE flags";
267 break;
268 default:
269 assert(0);
270 break;
271 }
272
273 switch (tc->mem_type) {
274 case USE_MMAP:
275 mem_type_str = "mmap";
276 break;
277 case USE_MPROTECT:
278 mem_type_str = "mmap/mprotect";
279 break;
280 default:
281 assert(0);
282 break;
283 }
284
285 switch (tc->mte_sync) {
286 case MTE_NONE_ERR:
287 sync_str = "no error";
288 break;
289 case MTE_SYNC_ERR:
290 sync_str = "sync error";
291 break;
292 case MTE_ASYNC_ERR:
293 sync_str = "async error";
294 break;
295 default:
296 assert(0);
297 break;
298 }
299
300 switch (tc->mapping) {
301 case MAP_SHARED:
302 mapping_str = "shared";
303 break;
304 case MAP_PRIVATE:
305 mapping_str = "private";
306 break;
307 default:
308 assert(0);
309 break;
310 }
311
312 switch (tc->tag_check) {
313 case TAG_CHECK_ON:
314 tag_check_str = "tag check on";
315 break;
316 case TAG_CHECK_OFF:
317 tag_check_str = "tag check off";
318 break;
319 default:
320 assert(0);
321 break;
322 }
323
324 switch (tc->atag_check) {
325 case ATAG_CHECK_ON:
326 atag_check_str = "with address tag [63:60]";
327 break;
328 case ATAG_CHECK_OFF:
329 atag_check_str = "without address tag [63:60]";
330 break;
331 default:
332 assert(0);
333 break;
334 }
335
336 snprintf(test_name, sizeof(test_name),
337 "Check %s with %s mapping, %s mode, %s memory and %s (%s)\n",
338 check_type_str, mapping_str, sync_str, mem_type_str,
339 tag_check_str, atag_check_str);
340
341 switch (tc->tag_op) {
342 case TAG_OP_ALL:
343 tag_op_str = "";
344 break;
345 case TAG_OP_STONLY:
346 tag_op_str = " / store-only";
347 break;
348 default:
349 assert(0);
350 break;
351 }
352
353 snprintf(test_name, TEST_NAME_MAX,
354 "Check %s with %s mapping, %s mode, %s memory and %s (%s%s)\n",
355 check_type_str, mapping_str, sync_str, mem_type_str,
356 tag_check_str, atag_check_str, tag_op_str);
357
358 return test_name;
359 }
360
main(int argc,char * argv[])361 int main(int argc, char *argv[])
362 {
363 int err, i;
364 int item = ARRAY_SIZE(sizes);
365 struct check_mmap_testcase test_cases[]= {
366 {
367 .check_type = CHECK_ANON_MEM,
368 .mem_type = USE_MMAP,
369 .mte_sync = MTE_SYNC_ERR,
370 .mapping = MAP_PRIVATE,
371 .tag_check = TAG_CHECK_OFF,
372 .atag_check = ATAG_CHECK_OFF,
373 .tag_op = TAG_OP_ALL,
374 .enable_tco = true,
375 },
376 {
377 .check_type = CHECK_FILE_MEM,
378 .mem_type = USE_MPROTECT,
379 .mte_sync = MTE_SYNC_ERR,
380 .mapping = MAP_PRIVATE,
381 .tag_check = TAG_CHECK_OFF,
382 .atag_check = ATAG_CHECK_OFF,
383 .tag_op = TAG_OP_ALL,
384 .enable_tco = true,
385 },
386 {
387 .check_type = CHECK_ANON_MEM,
388 .mem_type = USE_MMAP,
389 .mte_sync = MTE_NONE_ERR,
390 .mapping = MAP_PRIVATE,
391 .tag_check = TAG_CHECK_OFF,
392 .atag_check = ATAG_CHECK_OFF,
393 .tag_op = TAG_OP_ALL,
394 .enable_tco = false,
395 },
396 {
397 .check_type = CHECK_FILE_MEM,
398 .mem_type = USE_MPROTECT,
399 .mte_sync = MTE_NONE_ERR,
400 .mapping = MAP_PRIVATE,
401 .tag_check = TAG_CHECK_OFF,
402 .atag_check = ATAG_CHECK_OFF,
403 .tag_op = TAG_OP_ALL,
404 .enable_tco = false,
405 },
406 {
407 .check_type = CHECK_ANON_MEM,
408 .mem_type = USE_MMAP,
409 .mte_sync = MTE_SYNC_ERR,
410 .mapping = MAP_PRIVATE,
411 .tag_check = TAG_CHECK_ON,
412 .atag_check = ATAG_CHECK_OFF,
413 .tag_op = TAG_OP_ALL,
414 .enable_tco = false,
415 },
416 {
417 .check_type = CHECK_ANON_MEM,
418 .mem_type = USE_MPROTECT,
419 .mte_sync = MTE_SYNC_ERR,
420 .mapping = MAP_PRIVATE,
421 .tag_check = TAG_CHECK_ON,
422 .atag_check = ATAG_CHECK_OFF,
423 .tag_op = TAG_OP_ALL,
424 .enable_tco = false,
425 },
426 {
427 .check_type = CHECK_ANON_MEM,
428 .mem_type = USE_MMAP,
429 .mte_sync = MTE_SYNC_ERR,
430 .mapping = MAP_SHARED,
431 .tag_check = TAG_CHECK_ON,
432 .atag_check = ATAG_CHECK_OFF,
433 .tag_op = TAG_OP_ALL,
434 .enable_tco = false,
435 },
436 {
437 .check_type = CHECK_ANON_MEM,
438 .mem_type = USE_MPROTECT,
439 .mte_sync = MTE_SYNC_ERR,
440 .mapping = MAP_SHARED,
441 .tag_check = TAG_CHECK_ON,
442 .atag_check = ATAG_CHECK_OFF,
443 .tag_op = TAG_OP_ALL,
444 .enable_tco = false,
445 },
446 {
447 .check_type = CHECK_ANON_MEM,
448 .mem_type = USE_MMAP,
449 .mte_sync = MTE_ASYNC_ERR,
450 .mapping = MAP_PRIVATE,
451 .tag_check = TAG_CHECK_ON,
452 .atag_check = ATAG_CHECK_OFF,
453 .tag_op = TAG_OP_ALL,
454 .enable_tco = false,
455 },
456 {
457 .check_type = CHECK_ANON_MEM,
458 .mem_type = USE_MPROTECT,
459 .mte_sync = MTE_ASYNC_ERR,
460 .mapping = MAP_PRIVATE,
461 .tag_check = TAG_CHECK_ON,
462 .atag_check = ATAG_CHECK_OFF,
463 .tag_op = TAG_OP_ALL,
464 .enable_tco = false,
465 },
466 {
467 .check_type = CHECK_ANON_MEM,
468 .mem_type = USE_MMAP,
469 .mte_sync = MTE_ASYNC_ERR,
470 .mapping = MAP_SHARED,
471 .tag_check = TAG_CHECK_ON,
472 .atag_check = ATAG_CHECK_OFF,
473 .tag_op = TAG_OP_ALL,
474 .enable_tco = false,
475 },
476 {
477 .check_type = CHECK_ANON_MEM,
478 .mem_type = USE_MPROTECT,
479 .mte_sync = MTE_ASYNC_ERR,
480 .mapping = MAP_SHARED,
481 .tag_check = TAG_CHECK_ON,
482 .atag_check = ATAG_CHECK_OFF,
483 .tag_op = TAG_OP_ALL,
484 .enable_tco = false,
485 },
486 {
487 .check_type = CHECK_FILE_MEM,
488 .mem_type = USE_MMAP,
489 .mte_sync = MTE_SYNC_ERR,
490 .mapping = MAP_PRIVATE,
491 .tag_check = TAG_CHECK_ON,
492 .atag_check = ATAG_CHECK_OFF,
493 .tag_op = TAG_OP_ALL,
494 .enable_tco = false,
495 },
496 {
497 .check_type = CHECK_FILE_MEM,
498 .mem_type = USE_MPROTECT,
499 .mte_sync = MTE_SYNC_ERR,
500 .mapping = MAP_PRIVATE,
501 .tag_check = TAG_CHECK_ON,
502 .atag_check = ATAG_CHECK_OFF,
503 .tag_op = TAG_OP_ALL,
504 .enable_tco = false,
505 },
506 {
507 .check_type = CHECK_FILE_MEM,
508 .mem_type = USE_MMAP,
509 .mte_sync = MTE_SYNC_ERR,
510 .mapping = MAP_SHARED,
511 .tag_check = TAG_CHECK_ON,
512 .atag_check = ATAG_CHECK_OFF,
513 .tag_op = TAG_OP_ALL,
514 .enable_tco = false,
515 },
516 {
517 .check_type = CHECK_FILE_MEM,
518 .mem_type = USE_MPROTECT,
519 .mte_sync = MTE_SYNC_ERR,
520 .mapping = MAP_SHARED,
521 .tag_check = TAG_CHECK_ON,
522 .atag_check = ATAG_CHECK_OFF,
523 .tag_op = TAG_OP_ALL,
524 .enable_tco = false,
525 },
526 {
527 .check_type = CHECK_FILE_MEM,
528 .mem_type = USE_MMAP,
529 .mte_sync = MTE_ASYNC_ERR,
530 .mapping = MAP_PRIVATE,
531 .tag_check = TAG_CHECK_ON,
532 .atag_check = ATAG_CHECK_OFF,
533 .tag_op = TAG_OP_ALL,
534 .enable_tco = false,
535 },
536 {
537 .check_type = CHECK_FILE_MEM,
538 .mem_type = USE_MPROTECT,
539 .mte_sync = MTE_ASYNC_ERR,
540 .mapping = MAP_PRIVATE,
541 .tag_check = TAG_CHECK_ON,
542 .atag_check = ATAG_CHECK_OFF,
543 .tag_op = TAG_OP_ALL,
544 .enable_tco = false,
545 },
546 {
547 .check_type = CHECK_FILE_MEM,
548 .mem_type = USE_MMAP,
549 .mte_sync = MTE_ASYNC_ERR,
550 .mapping = MAP_SHARED,
551 .tag_check = TAG_CHECK_ON,
552 .atag_check = ATAG_CHECK_OFF,
553 .tag_op = TAG_OP_ALL,
554 .enable_tco = false,
555 },
556 {
557 .check_type = CHECK_FILE_MEM,
558 .mem_type = USE_MPROTECT,
559 .mte_sync = MTE_ASYNC_ERR,
560 .mapping = MAP_SHARED,
561 .tag_check = TAG_CHECK_ON,
562 .atag_check = ATAG_CHECK_OFF,
563 .tag_op = TAG_OP_ALL,
564 .enable_tco = false,
565 },
566 {
567 .check_type = CHECK_CLEAR_PROT_MTE,
568 .mem_type = USE_MMAP,
569 .mte_sync = MTE_SYNC_ERR,
570 .mapping = MAP_PRIVATE,
571 .tag_check = TAG_CHECK_ON,
572 .atag_check = ATAG_CHECK_OFF,
573 .tag_op = TAG_OP_ALL,
574 .enable_tco = false,
575 },
576 {
577 .check_type = CHECK_CLEAR_PROT_MTE,
578 .mem_type = USE_MPROTECT,
579 .mte_sync = MTE_SYNC_ERR,
580 .mapping = MAP_PRIVATE,
581 .tag_check = TAG_CHECK_ON,
582 .atag_check = ATAG_CHECK_OFF,
583 .tag_op = TAG_OP_ALL,
584 .enable_tco = false,
585 },
586 {
587 .check_type = CHECK_ANON_MEM,
588 .mem_type = USE_MMAP,
589 .mte_sync = MTE_SYNC_ERR,
590 .mapping = MAP_PRIVATE,
591 .tag_check = TAG_CHECK_ON,
592 .atag_check = ATAG_CHECK_ON,
593 .tag_op = TAG_OP_ALL,
594 .enable_tco = false,
595 },
596 {
597 .check_type = CHECK_ANON_MEM,
598 .mem_type = USE_MPROTECT,
599 .mte_sync = MTE_SYNC_ERR,
600 .mapping = MAP_PRIVATE,
601 .tag_check = TAG_CHECK_ON,
602 .atag_check = ATAG_CHECK_ON,
603 .tag_op = TAG_OP_ALL,
604 .enable_tco = false,
605 },
606 {
607 .check_type = CHECK_ANON_MEM,
608 .mem_type = USE_MMAP,
609 .mte_sync = MTE_SYNC_ERR,
610 .mapping = MAP_SHARED,
611 .tag_check = TAG_CHECK_ON,
612 .atag_check = ATAG_CHECK_ON,
613 .tag_op = TAG_OP_ALL,
614 .enable_tco = false,
615 },
616 {
617 .check_type = CHECK_ANON_MEM,
618 .mem_type = USE_MPROTECT,
619 .mte_sync = MTE_SYNC_ERR,
620 .mapping = MAP_SHARED,
621 .tag_check = TAG_CHECK_ON,
622 .atag_check = ATAG_CHECK_ON,
623 .tag_op = TAG_OP_ALL,
624 .enable_tco = false,
625 },
626 {
627 .check_type = CHECK_FILE_MEM,
628 .mem_type = USE_MMAP,
629 .mte_sync = MTE_SYNC_ERR,
630 .mapping = MAP_PRIVATE,
631 .tag_check = TAG_CHECK_ON,
632 .atag_check = ATAG_CHECK_ON,
633 .tag_op = TAG_OP_ALL,
634 .enable_tco = false,
635 },
636 {
637 .check_type = CHECK_FILE_MEM,
638 .mem_type = USE_MPROTECT,
639 .mte_sync = MTE_SYNC_ERR,
640 .mapping = MAP_PRIVATE,
641 .tag_check = TAG_CHECK_ON,
642 .atag_check = ATAG_CHECK_ON,
643 .tag_op = TAG_OP_ALL,
644 .enable_tco = false,
645 },
646 {
647 .check_type = CHECK_FILE_MEM,
648 .mem_type = USE_MMAP,
649 .mte_sync = MTE_SYNC_ERR,
650 .mapping = MAP_SHARED,
651 .tag_check = TAG_CHECK_ON,
652 .atag_check = ATAG_CHECK_ON,
653 .tag_op = TAG_OP_ALL,
654 .enable_tco = false,
655 },
656 {
657 .check_type = CHECK_FILE_MEM,
658 .mem_type = USE_MPROTECT,
659 .mte_sync = MTE_SYNC_ERR,
660 .mapping = MAP_SHARED,
661 .tag_check = TAG_CHECK_ON,
662 .atag_check = ATAG_CHECK_ON,
663 .tag_op = TAG_OP_ALL,
664 .enable_tco = false,
665 },
666 {
667 .check_type = CHECK_FILE_MEM,
668 .mem_type = USE_MMAP,
669 .mte_sync = MTE_ASYNC_ERR,
670 .mapping = MAP_PRIVATE,
671 .tag_check = TAG_CHECK_ON,
672 .atag_check = ATAG_CHECK_ON,
673 .tag_op = TAG_OP_ALL,
674 .enable_tco = false,
675 },
676 {
677 .check_type = CHECK_ANON_MEM,
678 .mem_type = USE_MMAP,
679 .mte_sync = MTE_SYNC_ERR,
680 .mapping = MAP_PRIVATE,
681 .tag_check = TAG_CHECK_ON,
682 .atag_check = ATAG_CHECK_OFF,
683 .tag_op = TAG_OP_STONLY,
684 .enable_tco = false,
685 },
686 {
687 .check_type = CHECK_ANON_MEM,
688 .mem_type = USE_MPROTECT,
689 .mte_sync = MTE_SYNC_ERR,
690 .mapping = MAP_PRIVATE,
691 .tag_check = TAG_CHECK_ON,
692 .atag_check = ATAG_CHECK_OFF,
693 .tag_op = TAG_OP_STONLY,
694 .enable_tco = false,
695 },
696 {
697 .check_type = CHECK_ANON_MEM,
698 .mem_type = USE_MMAP,
699 .mte_sync = MTE_SYNC_ERR,
700 .mapping = MAP_SHARED,
701 .tag_check = TAG_CHECK_ON,
702 .atag_check = ATAG_CHECK_OFF,
703 .tag_op = TAG_OP_STONLY,
704 .enable_tco = false,
705 },
706 {
707 .check_type = CHECK_ANON_MEM,
708 .mem_type = USE_MPROTECT,
709 .mte_sync = MTE_SYNC_ERR,
710 .mapping = MAP_SHARED,
711 .tag_check = TAG_CHECK_ON,
712 .atag_check = ATAG_CHECK_OFF,
713 .tag_op = TAG_OP_STONLY,
714 .enable_tco = false,
715 },
716 {
717 .check_type = CHECK_ANON_MEM,
718 .mem_type = USE_MMAP,
719 .mte_sync = MTE_ASYNC_ERR,
720 .mapping = MAP_PRIVATE,
721 .tag_check = TAG_CHECK_ON,
722 .atag_check = ATAG_CHECK_OFF,
723 .tag_op = TAG_OP_STONLY,
724 .enable_tco = false,
725 },
726 {
727 .check_type = CHECK_ANON_MEM,
728 .mem_type = USE_MPROTECT,
729 .mte_sync = MTE_ASYNC_ERR,
730 .mapping = MAP_PRIVATE,
731 .tag_check = TAG_CHECK_ON,
732 .atag_check = ATAG_CHECK_OFF,
733 .tag_op = TAG_OP_STONLY,
734 .enable_tco = false,
735 },
736 {
737 .check_type = CHECK_ANON_MEM,
738 .mem_type = USE_MMAP,
739 .mte_sync = MTE_ASYNC_ERR,
740 .mapping = MAP_SHARED,
741 .tag_check = TAG_CHECK_ON,
742 .atag_check = ATAG_CHECK_OFF,
743 .tag_op = TAG_OP_STONLY,
744 .enable_tco = false,
745 },
746 {
747 .check_type = CHECK_ANON_MEM,
748 .mem_type = USE_MPROTECT,
749 .mte_sync = MTE_ASYNC_ERR,
750 .mapping = MAP_SHARED,
751 .tag_check = TAG_CHECK_ON,
752 .atag_check = ATAG_CHECK_OFF,
753 .tag_op = TAG_OP_STONLY,
754 .enable_tco = false,
755 },
756 {
757 .check_type = CHECK_FILE_MEM,
758 .mem_type = USE_MMAP,
759 .mte_sync = MTE_SYNC_ERR,
760 .mapping = MAP_PRIVATE,
761 .tag_check = TAG_CHECK_ON,
762 .atag_check = ATAG_CHECK_OFF,
763 .tag_op = TAG_OP_STONLY,
764 .enable_tco = false,
765 },
766 {
767 .check_type = CHECK_FILE_MEM,
768 .mem_type = USE_MPROTECT,
769 .mte_sync = MTE_SYNC_ERR,
770 .mapping = MAP_PRIVATE,
771 .tag_check = TAG_CHECK_ON,
772 .atag_check = ATAG_CHECK_OFF,
773 .tag_op = TAG_OP_STONLY,
774 .enable_tco = false,
775 },
776 {
777 .check_type = CHECK_FILE_MEM,
778 .mem_type = USE_MMAP,
779 .mte_sync = MTE_SYNC_ERR,
780 .mapping = MAP_SHARED,
781 .tag_check = TAG_CHECK_ON,
782 .atag_check = ATAG_CHECK_OFF,
783 .tag_op = TAG_OP_STONLY,
784 .enable_tco = false,
785 },
786 {
787 .check_type = CHECK_FILE_MEM,
788 .mem_type = USE_MPROTECT,
789 .mte_sync = MTE_SYNC_ERR,
790 .mapping = MAP_SHARED,
791 .tag_check = TAG_CHECK_ON,
792 .atag_check = ATAG_CHECK_OFF,
793 .tag_op = TAG_OP_STONLY,
794 .enable_tco = false,
795 },
796 {
797 .check_type = CHECK_FILE_MEM,
798 .mem_type = USE_MMAP,
799 .mte_sync = MTE_ASYNC_ERR,
800 .mapping = MAP_PRIVATE,
801 .tag_check = TAG_CHECK_ON,
802 .atag_check = ATAG_CHECK_OFF,
803 .tag_op = TAG_OP_STONLY,
804 .enable_tco = false,
805 },
806 {
807 .check_type = CHECK_FILE_MEM,
808 .mem_type = USE_MPROTECT,
809 .mte_sync = MTE_ASYNC_ERR,
810 .mapping = MAP_PRIVATE,
811 .tag_check = TAG_CHECK_ON,
812 .atag_check = ATAG_CHECK_OFF,
813 .tag_op = TAG_OP_STONLY,
814 .enable_tco = false,
815 },
816 {
817 .check_type = CHECK_FILE_MEM,
818 .mem_type = USE_MMAP,
819 .mte_sync = MTE_ASYNC_ERR,
820 .mapping = MAP_SHARED,
821 .tag_check = TAG_CHECK_ON,
822 .atag_check = ATAG_CHECK_OFF,
823 .tag_op = TAG_OP_STONLY,
824 .enable_tco = false,
825 },
826 {
827 .check_type = CHECK_FILE_MEM,
828 .mem_type = USE_MPROTECT,
829 .mte_sync = MTE_ASYNC_ERR,
830 .mapping = MAP_SHARED,
831 .tag_check = TAG_CHECK_ON,
832 .atag_check = ATAG_CHECK_OFF,
833 .tag_op = TAG_OP_STONLY,
834 .enable_tco = false,
835 },
836 {
837 .check_type = CHECK_ANON_MEM,
838 .mem_type = USE_MMAP,
839 .mte_sync = MTE_SYNC_ERR,
840 .mapping = MAP_PRIVATE,
841 .tag_check = TAG_CHECK_ON,
842 .atag_check = ATAG_CHECK_ON,
843 .tag_op = TAG_OP_STONLY,
844 .enable_tco = false,
845 },
846 {
847 .check_type = CHECK_ANON_MEM,
848 .mem_type = USE_MPROTECT,
849 .mte_sync = MTE_SYNC_ERR,
850 .mapping = MAP_PRIVATE,
851 .tag_check = TAG_CHECK_ON,
852 .atag_check = ATAG_CHECK_ON,
853 .tag_op = TAG_OP_STONLY,
854 .enable_tco = false,
855 },
856 {
857 .check_type = CHECK_ANON_MEM,
858 .mem_type = USE_MMAP,
859 .mte_sync = MTE_SYNC_ERR,
860 .mapping = MAP_SHARED,
861 .tag_check = TAG_CHECK_ON,
862 .atag_check = ATAG_CHECK_ON,
863 .tag_op = TAG_OP_STONLY,
864 .enable_tco = false,
865 },
866 {
867 .check_type = CHECK_ANON_MEM,
868 .mem_type = USE_MPROTECT,
869 .mte_sync = MTE_SYNC_ERR,
870 .mapping = MAP_SHARED,
871 .tag_check = TAG_CHECK_ON,
872 .atag_check = ATAG_CHECK_ON,
873 .tag_op = TAG_OP_STONLY,
874 .enable_tco = false,
875 },
876 {
877 .check_type = CHECK_FILE_MEM,
878 .mem_type = USE_MMAP,
879 .mte_sync = MTE_SYNC_ERR,
880 .mapping = MAP_PRIVATE,
881 .tag_check = TAG_CHECK_ON,
882 .atag_check = ATAG_CHECK_ON,
883 .tag_op = TAG_OP_STONLY,
884 .enable_tco = false,
885 },
886 {
887 .check_type = CHECK_FILE_MEM,
888 .mem_type = USE_MPROTECT,
889 .mte_sync = MTE_SYNC_ERR,
890 .mapping = MAP_PRIVATE,
891 .tag_check = TAG_CHECK_ON,
892 .atag_check = ATAG_CHECK_ON,
893 .tag_op = TAG_OP_STONLY,
894 .enable_tco = false,
895 },
896 {
897 .check_type = CHECK_FILE_MEM,
898 .mem_type = USE_MMAP,
899 .mte_sync = MTE_SYNC_ERR,
900 .mapping = MAP_SHARED,
901 .tag_check = TAG_CHECK_ON,
902 .atag_check = ATAG_CHECK_ON,
903 .tag_op = TAG_OP_STONLY,
904 .enable_tco = false,
905 },
906 {
907 .check_type = CHECK_FILE_MEM,
908 .mem_type = USE_MPROTECT,
909 .mte_sync = MTE_SYNC_ERR,
910 .mapping = MAP_SHARED,
911 .tag_check = TAG_CHECK_ON,
912 .atag_check = ATAG_CHECK_ON,
913 .tag_op = TAG_OP_STONLY,
914 .enable_tco = false,
915 },
916 {
917 .check_type = CHECK_FILE_MEM,
918 .mem_type = USE_MMAP,
919 .mte_sync = MTE_ASYNC_ERR,
920 .mapping = MAP_PRIVATE,
921 .tag_check = TAG_CHECK_ON,
922 .atag_check = ATAG_CHECK_ON,
923 .tag_op = TAG_OP_STONLY,
924 .enable_tco = false,
925 },
926 {
927 .check_type = CHECK_CLEAR_PROT_MTE,
928 .mem_type = USE_MMAP,
929 .mte_sync = MTE_SYNC_ERR,
930 .mapping = MAP_PRIVATE,
931 .tag_check = TAG_CHECK_ON,
932 .atag_check = ATAG_CHECK_ON,
933 .tag_op = TAG_OP_ALL,
934 .enable_tco = false,
935 },
936 {
937 .check_type = CHECK_CLEAR_PROT_MTE,
938 .mem_type = USE_MPROTECT,
939 .mte_sync = MTE_SYNC_ERR,
940 .mapping = MAP_PRIVATE,
941 .tag_check = TAG_CHECK_ON,
942 .atag_check = ATAG_CHECK_ON,
943 .tag_op = TAG_OP_ALL,
944 .enable_tco = false,
945 },
946 };
947
948 err = mte_default_setup();
949 if (err)
950 return err;
951 page_size = getpagesize();
952 if (!page_size) {
953 ksft_print_msg("ERR: Unable to get page size\n");
954 return KSFT_FAIL;
955 }
956 sizes[item - 3] = page_size - 1;
957 sizes[item - 2] = page_size;
958 sizes[item - 1] = page_size + 1;
959
960 /* Set test plan */
961 ksft_set_plan(ARRAY_SIZE(test_cases));
962
963 for (i = 0 ; i < ARRAY_SIZE(test_cases); i++) {
964 /* Register signal handlers */
965 mte_register_signal(SIGBUS, mte_default_handler,
966 test_cases[i].atag_check == ATAG_CHECK_ON);
967 mte_register_signal(SIGSEGV, mte_default_handler,
968 test_cases[i].atag_check == ATAG_CHECK_ON);
969
970 if (test_cases[i].enable_tco)
971 mte_enable_pstate_tco();
972 else
973 mte_disable_pstate_tco();
974
975 switch (test_cases[i].check_type) {
976 case CHECK_ANON_MEM:
977 evaluate_test(check_anonymous_memory_mapping(test_cases[i].mem_type,
978 test_cases[i].mte_sync,
979 test_cases[i].mapping,
980 test_cases[i].tag_check,
981 test_cases[i].atag_check,
982 test_cases[i].tag_op),
983 format_test_name(&test_cases[i]));
984 break;
985 case CHECK_FILE_MEM:
986 evaluate_test(check_file_memory_mapping(test_cases[i].mem_type,
987 test_cases[i].mte_sync,
988 test_cases[i].mapping,
989 test_cases[i].tag_check,
990 test_cases[i].atag_check,
991 test_cases[i].tag_op),
992 format_test_name(&test_cases[i]));
993 break;
994 case CHECK_CLEAR_PROT_MTE:
995 evaluate_test(check_clear_prot_mte_flag(test_cases[i].mem_type,
996 test_cases[i].mte_sync,
997 test_cases[i].mapping,
998 test_cases[i].atag_check),
999 format_test_name(&test_cases[i]));
1000 break;
1001 default:
1002 exit(KSFT_FAIL);
1003 }
1004 }
1005
1006 mte_restore_setup();
1007 ksft_print_cnts();
1008 return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
1009 }
1010