xref: /linux/tools/testing/selftests/arm64/mte/check_mmap_options.c (revision 3ae8cef210dd52ae95fd5a87f9bea0932bd4e470)
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 struct check_mmap_testcase {
39 	int check_type;
40 	int mem_type;
41 	int mte_sync;
42 	int mapping;
43 	int tag_check;
44 	int atag_check;
45 	bool enable_tco;
46 };
47 
48 static size_t page_size;
49 static int sizes[] = {
50 	1, 537, 989, 1269, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,
51 	/* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 0
52 };
53 
54 static int check_mte_memory(char *ptr, int size, int mode, int tag_check, int atag_check)
55 {
56 	if (!mtefar_support && atag_check == ATAG_CHECK_ON)
57 		return KSFT_SKIP;
58 
59 	if (atag_check == ATAG_CHECK_ON)
60 		ptr = mte_insert_atag(ptr);
61 
62 	mte_initialize_current_context(mode, (uintptr_t)ptr, size);
63 	memset(ptr, '1', size);
64 	mte_wait_after_trig();
65 	if (cur_mte_cxt.fault_valid == true)
66 		return KSFT_FAIL;
67 
68 	mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);
69 	memset(ptr - UNDERFLOW, '2', UNDERFLOW);
70 	mte_wait_after_trig();
71 	if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)
72 		return KSFT_FAIL;
73 	if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)
74 		return KSFT_FAIL;
75 
76 	mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);
77 	memset(ptr + size, '3', OVERFLOW);
78 	mte_wait_after_trig();
79 	if (cur_mte_cxt.fault_valid == false && tag_check == TAG_CHECK_ON)
80 		return KSFT_FAIL;
81 	if (cur_mte_cxt.fault_valid == true && tag_check == TAG_CHECK_OFF)
82 		return KSFT_FAIL;
83 
84 	return KSFT_PASS;
85 }
86 
87 static int check_anonymous_memory_mapping(int mem_type, int mode, int mapping, int tag_check, int atag_check)
88 {
89 	char *ptr, *map_ptr;
90 	int run, result, map_size;
91 	int item = ARRAY_SIZE(sizes);
92 
93 	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
94 	for (run = 0; run < item; run++) {
95 		map_size = sizes[run] + OVERFLOW + UNDERFLOW;
96 		map_ptr = (char *)mte_allocate_memory(map_size, mem_type, mapping, false);
97 		if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS)
98 			return KSFT_FAIL;
99 
100 		ptr = map_ptr + UNDERFLOW;
101 		mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
102 		/* Only mte enabled memory will allow tag insertion */
103 		ptr = mte_insert_tags((void *)ptr, sizes[run]);
104 		if (!ptr || cur_mte_cxt.fault_valid == true) {
105 			ksft_print_msg("FAIL: Insert tags on anonymous mmap memory\n");
106 			munmap((void *)map_ptr, map_size);
107 			return KSFT_FAIL;
108 		}
109 		result = check_mte_memory(ptr, sizes[run], mode, tag_check, atag_check);
110 		mte_clear_tags((void *)ptr, sizes[run]);
111 		mte_free_memory((void *)map_ptr, map_size, mem_type, false);
112 		if (result != KSFT_PASS)
113 			return result;
114 	}
115 	return KSFT_PASS;
116 }
117 
118 static int check_file_memory_mapping(int mem_type, int mode, int mapping, int tag_check, int atag_check)
119 {
120 	char *ptr, *map_ptr;
121 	int run, fd, map_size;
122 	int total = ARRAY_SIZE(sizes);
123 	int result = KSFT_PASS;
124 
125 	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
126 	for (run = 0; run < total; run++) {
127 		fd = create_temp_file();
128 		if (fd == -1)
129 			return KSFT_FAIL;
130 
131 		map_size = sizes[run] + UNDERFLOW + OVERFLOW;
132 		map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);
133 		if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {
134 			close(fd);
135 			return KSFT_FAIL;
136 		}
137 		ptr = map_ptr + UNDERFLOW;
138 		mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
139 		/* Only mte enabled memory will allow tag insertion */
140 		ptr = mte_insert_tags((void *)ptr, sizes[run]);
141 		if (!ptr || cur_mte_cxt.fault_valid == true) {
142 			ksft_print_msg("FAIL: Insert tags on file based memory\n");
143 			munmap((void *)map_ptr, map_size);
144 			close(fd);
145 			return KSFT_FAIL;
146 		}
147 		result = check_mte_memory(ptr, sizes[run], mode, tag_check, atag_check);
148 		mte_clear_tags((void *)ptr, sizes[run]);
149 		munmap((void *)map_ptr, map_size);
150 		close(fd);
151 		if (result != KSFT_PASS)
152 			return result;
153 	}
154 	return KSFT_PASS;
155 }
156 
157 static int check_clear_prot_mte_flag(int mem_type, int mode, int mapping, int atag_check)
158 {
159 	char *ptr, *map_ptr;
160 	int run, prot_flag, result, fd, map_size;
161 	int total = ARRAY_SIZE(sizes);
162 
163 	prot_flag = PROT_READ | PROT_WRITE;
164 	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
165 	for (run = 0; run < total; run++) {
166 		map_size = sizes[run] + OVERFLOW + UNDERFLOW;
167 		ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,
168 							    UNDERFLOW, OVERFLOW);
169 		if (check_allocated_memory_range(ptr, sizes[run], mem_type,
170 						 UNDERFLOW, OVERFLOW) != KSFT_PASS)
171 			return KSFT_FAIL;
172 		map_ptr = ptr - UNDERFLOW;
173 		/* Try to clear PROT_MTE property and verify it by tag checking */
174 		if (mprotect(map_ptr, map_size, prot_flag)) {
175 			mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
176 						  UNDERFLOW, OVERFLOW);
177 			ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
178 			return KSFT_FAIL;
179 		}
180 		result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON, atag_check);
181 		mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
182 		if (result != KSFT_PASS)
183 			return KSFT_FAIL;
184 
185 		fd = create_temp_file();
186 		if (fd == -1)
187 			return KSFT_FAIL;
188 		ptr = (char *)mte_allocate_file_memory_tag_range(sizes[run], mem_type, mapping,
189 								 UNDERFLOW, OVERFLOW, fd);
190 		if (check_allocated_memory_range(ptr, sizes[run], mem_type,
191 						 UNDERFLOW, OVERFLOW) != KSFT_PASS) {
192 			close(fd);
193 			return KSFT_FAIL;
194 		}
195 		map_ptr = ptr - UNDERFLOW;
196 		/* Try to clear PROT_MTE property and verify it by tag checking */
197 		if (mprotect(map_ptr, map_size, prot_flag)) {
198 			ksft_print_msg("FAIL: mprotect not ignoring clear PROT_MTE property\n");
199 			mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type,
200 						  UNDERFLOW, OVERFLOW);
201 			close(fd);
202 			return KSFT_FAIL;
203 		}
204 		result = check_mte_memory(ptr, sizes[run], mode, TAG_CHECK_ON, atag_check);
205 		mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
206 		close(fd);
207 		if (result != KSFT_PASS)
208 			return result;
209 	}
210 	return KSFT_PASS;
211 }
212 
213 const char *format_test_name(struct check_mmap_testcase *tc)
214 {
215 	static char test_name[TEST_NAME_MAX];
216 	const char *check_type_str;
217 	const char *mem_type_str;
218 	const char *sync_str;
219 	const char *mapping_str;
220 	const char *tag_check_str;
221 	const char *atag_check_str;
222 
223 	switch (tc->check_type) {
224 	case CHECK_ANON_MEM:
225 		check_type_str = "anonymous memory";
226 		break;
227 	case CHECK_FILE_MEM:
228 		check_type_str = "file memory";
229 		break;
230 	case CHECK_CLEAR_PROT_MTE:
231 		check_type_str = "clear PROT_MTE flags";
232 		break;
233 	default:
234 		assert(0);
235 		break;
236 	}
237 
238 	switch (tc->mem_type) {
239 	case USE_MMAP:
240 		mem_type_str = "mmap";
241 		break;
242 	case USE_MPROTECT:
243 		mem_type_str = "mmap/mprotect";
244 		break;
245 	default:
246 		assert(0);
247 		break;
248 	}
249 
250 	switch (tc->mte_sync) {
251 	case MTE_NONE_ERR:
252 		sync_str = "no error";
253 		break;
254 	case MTE_SYNC_ERR:
255 		sync_str = "sync error";
256 		break;
257 	case MTE_ASYNC_ERR:
258 		sync_str = "async error";
259 		break;
260 	default:
261 		assert(0);
262 		break;
263 	}
264 
265 	switch (tc->mapping) {
266 	case MAP_SHARED:
267 		mapping_str = "shared";
268 		break;
269 	case MAP_PRIVATE:
270 		mapping_str = "private";
271 		break;
272 	default:
273 		assert(0);
274 		break;
275 	}
276 
277 	switch (tc->tag_check) {
278 	case TAG_CHECK_ON:
279 		tag_check_str = "tag check on";
280 		break;
281 	case TAG_CHECK_OFF:
282 		tag_check_str = "tag check off";
283 		break;
284 	default:
285 		assert(0);
286 		break;
287 	}
288 
289 	switch (tc->atag_check) {
290 	case ATAG_CHECK_ON:
291 		atag_check_str = "with address tag [63:60]";
292 		break;
293 	case ATAG_CHECK_OFF:
294 		atag_check_str = "without address tag [63:60]";
295 		break;
296 	default:
297 		assert(0);
298 		break;
299 	}
300 
301 	snprintf(test_name, sizeof(test_name),
302 	         "Check %s with %s mapping, %s mode, %s memory and %s (%s)\n",
303 	         check_type_str, mapping_str, sync_str, mem_type_str,
304 	         tag_check_str, atag_check_str);
305 
306 	return test_name;
307 }
308 
309 int main(int argc, char *argv[])
310 {
311 	int err, i;
312 	int item = ARRAY_SIZE(sizes);
313 	struct check_mmap_testcase test_cases[]= {
314 		{
315 			.check_type = CHECK_ANON_MEM,
316 			.mem_type = USE_MMAP,
317 			.mte_sync = MTE_SYNC_ERR,
318 			.mapping = MAP_PRIVATE,
319 			.tag_check = TAG_CHECK_OFF,
320 			.atag_check = ATAG_CHECK_OFF,
321 			.enable_tco = true,
322 		},
323 		{
324 			.check_type = CHECK_FILE_MEM,
325 			.mem_type = USE_MPROTECT,
326 			.mte_sync = MTE_SYNC_ERR,
327 			.mapping = MAP_PRIVATE,
328 			.tag_check = TAG_CHECK_OFF,
329 			.atag_check = ATAG_CHECK_OFF,
330 			.enable_tco = true,
331 		},
332 		{
333 			.check_type = CHECK_ANON_MEM,
334 			.mem_type = USE_MMAP,
335 			.mte_sync = MTE_NONE_ERR,
336 			.mapping = MAP_PRIVATE,
337 			.tag_check = TAG_CHECK_OFF,
338 			.atag_check = ATAG_CHECK_OFF,
339 			.enable_tco = false,
340 		},
341 		{
342 			.check_type = CHECK_FILE_MEM,
343 			.mem_type = USE_MPROTECT,
344 			.mte_sync = MTE_NONE_ERR,
345 			.mapping = MAP_PRIVATE,
346 			.tag_check = TAG_CHECK_OFF,
347 			.atag_check = ATAG_CHECK_OFF,
348 			.enable_tco = false,
349 		},
350 		{
351 			.check_type = CHECK_ANON_MEM,
352 			.mem_type = USE_MMAP,
353 			.mte_sync = MTE_SYNC_ERR,
354 			.mapping = MAP_PRIVATE,
355 			.tag_check = TAG_CHECK_ON,
356 			.atag_check = ATAG_CHECK_OFF,
357 			.enable_tco = false,
358 		},
359 		{
360 			.check_type = CHECK_ANON_MEM,
361 			.mem_type = USE_MPROTECT,
362 			.mte_sync = MTE_SYNC_ERR,
363 			.mapping = MAP_PRIVATE,
364 			.tag_check = TAG_CHECK_ON,
365 			.atag_check = ATAG_CHECK_OFF,
366 			.enable_tco = false,
367 		},
368 		{
369 			.check_type = CHECK_ANON_MEM,
370 			.mem_type = USE_MMAP,
371 			.mte_sync = MTE_SYNC_ERR,
372 			.mapping = MAP_SHARED,
373 			.tag_check = TAG_CHECK_ON,
374 			.atag_check = ATAG_CHECK_OFF,
375 			.enable_tco = false,
376 		},
377 		{
378 			.check_type = CHECK_ANON_MEM,
379 			.mem_type = USE_MPROTECT,
380 			.mte_sync = MTE_SYNC_ERR,
381 			.mapping = MAP_SHARED,
382 			.tag_check = TAG_CHECK_ON,
383 			.atag_check = ATAG_CHECK_OFF,
384 			.enable_tco = false,
385 		},
386 		{
387 			.check_type = CHECK_ANON_MEM,
388 			.mem_type = USE_MMAP,
389 			.mte_sync = MTE_ASYNC_ERR,
390 			.mapping = MAP_PRIVATE,
391 			.tag_check = TAG_CHECK_ON,
392 			.atag_check = ATAG_CHECK_OFF,
393 			.enable_tco = false,
394 		},
395 		{
396 			.check_type = CHECK_ANON_MEM,
397 			.mem_type = USE_MPROTECT,
398 			.mte_sync = MTE_ASYNC_ERR,
399 			.mapping = MAP_PRIVATE,
400 			.tag_check = TAG_CHECK_ON,
401 			.atag_check = ATAG_CHECK_OFF,
402 			.enable_tco = false,
403 		},
404 		{
405 			.check_type = CHECK_ANON_MEM,
406 			.mem_type = USE_MMAP,
407 			.mte_sync = MTE_ASYNC_ERR,
408 			.mapping = MAP_SHARED,
409 			.tag_check = TAG_CHECK_ON,
410 			.atag_check = ATAG_CHECK_OFF,
411 			.enable_tco = false,
412 		},
413 		{
414 			.check_type = CHECK_ANON_MEM,
415 			.mem_type = USE_MPROTECT,
416 			.mte_sync = MTE_ASYNC_ERR,
417 			.mapping = MAP_SHARED,
418 			.tag_check = TAG_CHECK_ON,
419 			.atag_check = ATAG_CHECK_OFF,
420 			.enable_tco = false,
421 		},
422 		{
423 			.check_type = CHECK_FILE_MEM,
424 			.mem_type = USE_MMAP,
425 			.mte_sync = MTE_SYNC_ERR,
426 			.mapping = MAP_PRIVATE,
427 			.tag_check = TAG_CHECK_ON,
428 			.atag_check = ATAG_CHECK_OFF,
429 			.enable_tco = false,
430 		},
431 		{
432 			.check_type = CHECK_FILE_MEM,
433 			.mem_type = USE_MPROTECT,
434 			.mte_sync = MTE_SYNC_ERR,
435 			.mapping = MAP_PRIVATE,
436 			.tag_check = TAG_CHECK_ON,
437 			.atag_check = ATAG_CHECK_OFF,
438 			.enable_tco = false,
439 		},
440 		{
441 			.check_type = CHECK_FILE_MEM,
442 			.mem_type = USE_MMAP,
443 			.mte_sync = MTE_SYNC_ERR,
444 			.mapping = MAP_SHARED,
445 			.tag_check = TAG_CHECK_ON,
446 			.atag_check = ATAG_CHECK_OFF,
447 			.enable_tco = false,
448 		},
449 		{
450 			.check_type = CHECK_FILE_MEM,
451 			.mem_type = USE_MPROTECT,
452 			.mte_sync = MTE_SYNC_ERR,
453 			.mapping = MAP_SHARED,
454 			.tag_check = TAG_CHECK_ON,
455 			.atag_check = ATAG_CHECK_OFF,
456 			.enable_tco = false,
457 		},
458 		{
459 			.check_type = CHECK_FILE_MEM,
460 			.mem_type = USE_MMAP,
461 			.mte_sync = MTE_ASYNC_ERR,
462 			.mapping = MAP_PRIVATE,
463 			.tag_check = TAG_CHECK_ON,
464 			.atag_check = ATAG_CHECK_OFF,
465 			.enable_tco = false,
466 		},
467 		{
468 			.check_type = CHECK_FILE_MEM,
469 			.mem_type = USE_MPROTECT,
470 			.mte_sync = MTE_ASYNC_ERR,
471 			.mapping = MAP_PRIVATE,
472 			.tag_check = TAG_CHECK_ON,
473 			.atag_check = ATAG_CHECK_OFF,
474 			.enable_tco = false,
475 		},
476 		{
477 			.check_type = CHECK_FILE_MEM,
478 			.mem_type = USE_MMAP,
479 			.mte_sync = MTE_ASYNC_ERR,
480 			.mapping = MAP_SHARED,
481 			.tag_check = TAG_CHECK_ON,
482 			.atag_check = ATAG_CHECK_OFF,
483 			.enable_tco = false,
484 		},
485 		{
486 			.check_type = CHECK_FILE_MEM,
487 			.mem_type = USE_MPROTECT,
488 			.mte_sync = MTE_ASYNC_ERR,
489 			.mapping = MAP_SHARED,
490 			.tag_check = TAG_CHECK_ON,
491 			.atag_check = ATAG_CHECK_OFF,
492 			.enable_tco = false,
493 		},
494 		{
495 			.check_type = CHECK_CLEAR_PROT_MTE,
496 			.mem_type = USE_MMAP,
497 			.mte_sync = MTE_SYNC_ERR,
498 			.mapping = MAP_PRIVATE,
499 			.tag_check = TAG_CHECK_ON,
500 			.atag_check = ATAG_CHECK_OFF,
501 			.enable_tco = false,
502 		},
503 		{
504 			.check_type = CHECK_CLEAR_PROT_MTE,
505 			.mem_type = USE_MPROTECT,
506 			.mte_sync = MTE_SYNC_ERR,
507 			.mapping = MAP_PRIVATE,
508 			.tag_check = TAG_CHECK_ON,
509 			.atag_check = ATAG_CHECK_OFF,
510 			.enable_tco = false,
511 		},
512 		{
513 			.check_type = CHECK_ANON_MEM,
514 			.mem_type = USE_MMAP,
515 			.mte_sync = MTE_SYNC_ERR,
516 			.mapping = MAP_PRIVATE,
517 			.tag_check = TAG_CHECK_ON,
518 			.atag_check = ATAG_CHECK_ON,
519 			.enable_tco = false,
520 		},
521 		{
522 			.check_type = CHECK_ANON_MEM,
523 			.mem_type = USE_MPROTECT,
524 			.mte_sync = MTE_SYNC_ERR,
525 			.mapping = MAP_PRIVATE,
526 			.tag_check = TAG_CHECK_ON,
527 			.atag_check = ATAG_CHECK_ON,
528 			.enable_tco = false,
529 		},
530 		{
531 			.check_type = CHECK_ANON_MEM,
532 			.mem_type = USE_MMAP,
533 			.mte_sync = MTE_SYNC_ERR,
534 			.mapping = MAP_SHARED,
535 			.tag_check = TAG_CHECK_ON,
536 			.atag_check = ATAG_CHECK_ON,
537 			.enable_tco = false,
538 		},
539 		{
540 			.check_type = CHECK_ANON_MEM,
541 			.mem_type = USE_MPROTECT,
542 			.mte_sync = MTE_SYNC_ERR,
543 			.mapping = MAP_SHARED,
544 			.tag_check = TAG_CHECK_ON,
545 			.atag_check = ATAG_CHECK_ON,
546 			.enable_tco = false,
547 		},
548 		{
549 			.check_type = CHECK_FILE_MEM,
550 			.mem_type = USE_MMAP,
551 			.mte_sync = MTE_SYNC_ERR,
552 			.mapping = MAP_PRIVATE,
553 			.tag_check = TAG_CHECK_ON,
554 			.atag_check = ATAG_CHECK_ON,
555 			.enable_tco = false,
556 		},
557 		{
558 			.check_type = CHECK_FILE_MEM,
559 			.mem_type = USE_MPROTECT,
560 			.mte_sync = MTE_SYNC_ERR,
561 			.mapping = MAP_PRIVATE,
562 			.tag_check = TAG_CHECK_ON,
563 			.atag_check = ATAG_CHECK_ON,
564 			.enable_tco = false,
565 		},
566 		{
567 			.check_type = CHECK_FILE_MEM,
568 			.mem_type = USE_MMAP,
569 			.mte_sync = MTE_SYNC_ERR,
570 			.mapping = MAP_SHARED,
571 			.tag_check = TAG_CHECK_ON,
572 			.atag_check = ATAG_CHECK_ON,
573 			.enable_tco = false,
574 		},
575 		{
576 			.check_type = CHECK_FILE_MEM,
577 			.mem_type = USE_MPROTECT,
578 			.mte_sync = MTE_SYNC_ERR,
579 			.mapping = MAP_SHARED,
580 			.tag_check = TAG_CHECK_ON,
581 			.atag_check = ATAG_CHECK_ON,
582 			.enable_tco = false,
583 		},
584 		{
585 			.check_type = CHECK_FILE_MEM,
586 			.mem_type = USE_MMAP,
587 			.mte_sync = MTE_ASYNC_ERR,
588 			.mapping = MAP_PRIVATE,
589 			.tag_check = TAG_CHECK_ON,
590 			.atag_check = ATAG_CHECK_ON,
591 			.enable_tco = false,
592 		},
593 		{
594 			.check_type = CHECK_CLEAR_PROT_MTE,
595 			.mem_type = USE_MMAP,
596 			.mte_sync = MTE_SYNC_ERR,
597 			.mapping = MAP_PRIVATE,
598 			.tag_check = TAG_CHECK_ON,
599 			.atag_check = ATAG_CHECK_ON,
600 			.enable_tco = false,
601 		},
602 		{
603 			.check_type = CHECK_CLEAR_PROT_MTE,
604 			.mem_type = USE_MPROTECT,
605 			.mte_sync = MTE_SYNC_ERR,
606 			.mapping = MAP_PRIVATE,
607 			.tag_check = TAG_CHECK_ON,
608 			.atag_check = ATAG_CHECK_ON,
609 			.enable_tco = false,
610 		},
611 	};
612 
613 	err = mte_default_setup();
614 	if (err)
615 		return err;
616 	page_size = getpagesize();
617 	if (!page_size) {
618 		ksft_print_msg("ERR: Unable to get page size\n");
619 		return KSFT_FAIL;
620 	}
621 	sizes[item - 3] = page_size - 1;
622 	sizes[item - 2] = page_size;
623 	sizes[item - 1] = page_size + 1;
624 
625 	/* Set test plan */
626 	ksft_set_plan(ARRAY_SIZE(test_cases));
627 
628 	for (i = 0 ; i < ARRAY_SIZE(test_cases); i++) {
629 		/* Register signal handlers */
630 		mte_register_signal(SIGBUS, mte_default_handler,
631 				    test_cases[i].atag_check == ATAG_CHECK_ON);
632 		mte_register_signal(SIGSEGV, mte_default_handler,
633 				    test_cases[i].atag_check == ATAG_CHECK_ON);
634 
635 		if (test_cases[i].enable_tco)
636 			mte_enable_pstate_tco();
637 		else
638 			mte_disable_pstate_tco();
639 
640 		switch (test_cases[i].check_type) {
641 		case CHECK_ANON_MEM:
642 			evaluate_test(check_anonymous_memory_mapping(test_cases[i].mem_type,
643 								     test_cases[i].mte_sync,
644 								     test_cases[i].mapping,
645 								     test_cases[i].tag_check,
646 								     test_cases[i].atag_check),
647 				      format_test_name(&test_cases[i]));
648 			break;
649 		case CHECK_FILE_MEM:
650 			evaluate_test(check_file_memory_mapping(test_cases[i].mem_type,
651 							        test_cases[i].mte_sync,
652 							        test_cases[i].mapping,
653 							        test_cases[i].tag_check,
654 							        test_cases[i].atag_check),
655 				      format_test_name(&test_cases[i]));
656 			break;
657 		case CHECK_CLEAR_PROT_MTE:
658 			evaluate_test(check_clear_prot_mte_flag(test_cases[i].mem_type,
659 							        test_cases[i].mte_sync,
660 							        test_cases[i].mapping,
661 							        test_cases[i].atag_check),
662 				      format_test_name(&test_cases[i]));
663 			break;
664 		default:
665 			exit(KSFT_FAIL);
666 		}
667 	}
668 
669 	mte_restore_setup();
670 	ksft_print_cnts();
671 	return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
672 }
673