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