1dfe537cfSAmit Daniel Kachhap // SPDX-License-Identifier: GPL-2.0
2dfe537cfSAmit Daniel Kachhap // Copyright (C) 2020 ARM Limited
3dfe537cfSAmit Daniel Kachhap 
4dfe537cfSAmit Daniel Kachhap #define _GNU_SOURCE
5dfe537cfSAmit Daniel Kachhap 
6dfe537cfSAmit Daniel Kachhap #include <errno.h>
7dfe537cfSAmit Daniel Kachhap #include <signal.h>
8dfe537cfSAmit Daniel Kachhap #include <stdio.h>
9dfe537cfSAmit Daniel Kachhap #include <stdlib.h>
10dfe537cfSAmit Daniel Kachhap #include <string.h>
11dfe537cfSAmit Daniel Kachhap #include <ucontext.h>
12dfe537cfSAmit Daniel Kachhap #include <sys/wait.h>
13dfe537cfSAmit Daniel Kachhap 
14dfe537cfSAmit Daniel Kachhap #include "kselftest.h"
15dfe537cfSAmit Daniel Kachhap #include "mte_common_util.h"
16dfe537cfSAmit Daniel Kachhap #include "mte_def.h"
17dfe537cfSAmit Daniel Kachhap 
18dfe537cfSAmit Daniel Kachhap #define BUFFER_SIZE		(5 * MT_GRANULE_SIZE)
19dfe537cfSAmit Daniel Kachhap #define RUNS			(MT_TAG_COUNT)
20dfe537cfSAmit Daniel Kachhap #define UNDERFLOW		MT_GRANULE_SIZE
21dfe537cfSAmit Daniel Kachhap #define OVERFLOW		MT_GRANULE_SIZE
22dfe537cfSAmit Daniel Kachhap 
23dfe537cfSAmit Daniel Kachhap static size_t page_size;
24dfe537cfSAmit Daniel Kachhap static int sizes[] = {
25dfe537cfSAmit Daniel Kachhap 	1, 537, 989, 1269, MT_GRANULE_SIZE - 1, MT_GRANULE_SIZE,
26dfe537cfSAmit Daniel Kachhap 	/* page size - 1*/ 0, /* page_size */ 0, /* page size + 1 */ 0
27dfe537cfSAmit Daniel Kachhap };
28dfe537cfSAmit Daniel Kachhap 
check_child_tag_inheritance(char * ptr,int size,int mode)29dfe537cfSAmit Daniel Kachhap static int check_child_tag_inheritance(char *ptr, int size, int mode)
30dfe537cfSAmit Daniel Kachhap {
31dfe537cfSAmit Daniel Kachhap 	int i, parent_tag, child_tag, fault, child_status;
32dfe537cfSAmit Daniel Kachhap 	pid_t child;
33dfe537cfSAmit Daniel Kachhap 
34dfe537cfSAmit Daniel Kachhap 	parent_tag = MT_FETCH_TAG((uintptr_t)ptr);
35dfe537cfSAmit Daniel Kachhap 	fault = 0;
36dfe537cfSAmit Daniel Kachhap 
37dfe537cfSAmit Daniel Kachhap 	child = fork();
38dfe537cfSAmit Daniel Kachhap 	if (child == -1) {
39dfe537cfSAmit Daniel Kachhap 		ksft_print_msg("FAIL: child process creation\n");
40dfe537cfSAmit Daniel Kachhap 		return KSFT_FAIL;
41dfe537cfSAmit Daniel Kachhap 	} else if (child == 0) {
42dfe537cfSAmit Daniel Kachhap 		mte_initialize_current_context(mode, (uintptr_t)ptr, size);
43dfe537cfSAmit Daniel Kachhap 		/* Do copy on write */
44dfe537cfSAmit Daniel Kachhap 		memset(ptr, '1', size);
45dfe537cfSAmit Daniel Kachhap 		mte_wait_after_trig();
46dfe537cfSAmit Daniel Kachhap 		if (cur_mte_cxt.fault_valid == true) {
47dfe537cfSAmit Daniel Kachhap 			fault = 1;
48dfe537cfSAmit Daniel Kachhap 			goto check_child_tag_inheritance_err;
49dfe537cfSAmit Daniel Kachhap 		}
50dfe537cfSAmit Daniel Kachhap 		for (i = 0 ; i < size ; i += MT_GRANULE_SIZE) {
51dfe537cfSAmit Daniel Kachhap 			child_tag = MT_FETCH_TAG((uintptr_t)(mte_get_tag_address(ptr + i)));
52dfe537cfSAmit Daniel Kachhap 			if (parent_tag != child_tag) {
53dfe537cfSAmit Daniel Kachhap 				ksft_print_msg("FAIL: child mte tag mismatch\n");
54dfe537cfSAmit Daniel Kachhap 				fault = 1;
55dfe537cfSAmit Daniel Kachhap 				goto check_child_tag_inheritance_err;
56dfe537cfSAmit Daniel Kachhap 			}
57dfe537cfSAmit Daniel Kachhap 		}
58dfe537cfSAmit Daniel Kachhap 		mte_initialize_current_context(mode, (uintptr_t)ptr, -UNDERFLOW);
59dfe537cfSAmit Daniel Kachhap 		memset(ptr - UNDERFLOW, '2', UNDERFLOW);
60dfe537cfSAmit Daniel Kachhap 		mte_wait_after_trig();
61dfe537cfSAmit Daniel Kachhap 		if (cur_mte_cxt.fault_valid == false) {
62dfe537cfSAmit Daniel Kachhap 			fault = 1;
63dfe537cfSAmit Daniel Kachhap 			goto check_child_tag_inheritance_err;
64dfe537cfSAmit Daniel Kachhap 		}
65dfe537cfSAmit Daniel Kachhap 		mte_initialize_current_context(mode, (uintptr_t)ptr, size + OVERFLOW);
66dfe537cfSAmit Daniel Kachhap 		memset(ptr + size, '3', OVERFLOW);
67dfe537cfSAmit Daniel Kachhap 		mte_wait_after_trig();
68dfe537cfSAmit Daniel Kachhap 		if (cur_mte_cxt.fault_valid == false) {
69dfe537cfSAmit Daniel Kachhap 			fault = 1;
70dfe537cfSAmit Daniel Kachhap 			goto check_child_tag_inheritance_err;
71dfe537cfSAmit Daniel Kachhap 		}
72dfe537cfSAmit Daniel Kachhap check_child_tag_inheritance_err:
73dfe537cfSAmit Daniel Kachhap 		_exit(fault);
74dfe537cfSAmit Daniel Kachhap 	}
75dfe537cfSAmit Daniel Kachhap 	/* Wait for child process to terminate */
76dfe537cfSAmit Daniel Kachhap 	wait(&child_status);
77dfe537cfSAmit Daniel Kachhap 	if (WIFEXITED(child_status))
78dfe537cfSAmit Daniel Kachhap 		fault = WEXITSTATUS(child_status);
79dfe537cfSAmit Daniel Kachhap 	else
80dfe537cfSAmit Daniel Kachhap 		fault = 1;
81dfe537cfSAmit Daniel Kachhap 	return (fault) ? KSFT_FAIL : KSFT_PASS;
82dfe537cfSAmit Daniel Kachhap }
83dfe537cfSAmit Daniel Kachhap 
check_child_memory_mapping(int mem_type,int mode,int mapping)84dfe537cfSAmit Daniel Kachhap static int check_child_memory_mapping(int mem_type, int mode, int mapping)
85dfe537cfSAmit Daniel Kachhap {
86dfe537cfSAmit Daniel Kachhap 	char *ptr;
87dfe537cfSAmit Daniel Kachhap 	int run, result;
88f82efe5bSGuo Zhengkui 	int item = ARRAY_SIZE(sizes);
89dfe537cfSAmit Daniel Kachhap 
90f82efe5bSGuo Zhengkui 	item = ARRAY_SIZE(sizes);
91dfe537cfSAmit Daniel Kachhap 	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
92dfe537cfSAmit Daniel Kachhap 	for (run = 0; run < item; run++) {
93dfe537cfSAmit Daniel Kachhap 		ptr = (char *)mte_allocate_memory_tag_range(sizes[run], mem_type, mapping,
94dfe537cfSAmit Daniel Kachhap 							    UNDERFLOW, OVERFLOW);
95dfe537cfSAmit Daniel Kachhap 		if (check_allocated_memory_range(ptr, sizes[run], mem_type,
96dfe537cfSAmit Daniel Kachhap 						 UNDERFLOW, OVERFLOW) != KSFT_PASS)
97dfe537cfSAmit Daniel Kachhap 			return KSFT_FAIL;
98dfe537cfSAmit Daniel Kachhap 		result = check_child_tag_inheritance(ptr, sizes[run], mode);
99dfe537cfSAmit Daniel Kachhap 		mte_free_memory_tag_range((void *)ptr, sizes[run], mem_type, UNDERFLOW, OVERFLOW);
100dfe537cfSAmit Daniel Kachhap 		if (result == KSFT_FAIL)
101dfe537cfSAmit Daniel Kachhap 			return result;
102dfe537cfSAmit Daniel Kachhap 	}
103dfe537cfSAmit Daniel Kachhap 	return KSFT_PASS;
104dfe537cfSAmit Daniel Kachhap }
105dfe537cfSAmit Daniel Kachhap 
check_child_file_mapping(int mem_type,int mode,int mapping)106dfe537cfSAmit Daniel Kachhap static int check_child_file_mapping(int mem_type, int mode, int mapping)
107dfe537cfSAmit Daniel Kachhap {
108dfe537cfSAmit Daniel Kachhap 	char *ptr, *map_ptr;
109dfe537cfSAmit Daniel Kachhap 	int run, fd, map_size, result = KSFT_PASS;
110f82efe5bSGuo Zhengkui 	int total = ARRAY_SIZE(sizes);
111dfe537cfSAmit Daniel Kachhap 
112dfe537cfSAmit Daniel Kachhap 	mte_switch_mode(mode, MTE_ALLOW_NON_ZERO_TAG);
113dfe537cfSAmit Daniel Kachhap 	for (run = 0; run < total; run++) {
114dfe537cfSAmit Daniel Kachhap 		fd = create_temp_file();
115dfe537cfSAmit Daniel Kachhap 		if (fd == -1)
116dfe537cfSAmit Daniel Kachhap 			return KSFT_FAIL;
117dfe537cfSAmit Daniel Kachhap 
118dfe537cfSAmit Daniel Kachhap 		map_size = sizes[run] + OVERFLOW + UNDERFLOW;
119dfe537cfSAmit Daniel Kachhap 		map_ptr = (char *)mte_allocate_file_memory(map_size, mem_type, mapping, false, fd);
120dfe537cfSAmit Daniel Kachhap 		if (check_allocated_memory(map_ptr, map_size, mem_type, false) != KSFT_PASS) {
121dfe537cfSAmit Daniel Kachhap 			close(fd);
122dfe537cfSAmit Daniel Kachhap 			return KSFT_FAIL;
123dfe537cfSAmit Daniel Kachhap 		}
124dfe537cfSAmit Daniel Kachhap 		ptr = map_ptr + UNDERFLOW;
125dfe537cfSAmit Daniel Kachhap 		mte_initialize_current_context(mode, (uintptr_t)ptr, sizes[run]);
126dfe537cfSAmit Daniel Kachhap 		/* Only mte enabled memory will allow tag insertion */
127dfe537cfSAmit Daniel Kachhap 		ptr = mte_insert_tags((void *)ptr, sizes[run]);
128dfe537cfSAmit Daniel Kachhap 		if (!ptr || cur_mte_cxt.fault_valid == true) {
129dfe537cfSAmit Daniel Kachhap 			ksft_print_msg("FAIL: Insert tags on file based memory\n");
130dfe537cfSAmit Daniel Kachhap 			munmap((void *)map_ptr, map_size);
131dfe537cfSAmit Daniel Kachhap 			close(fd);
132dfe537cfSAmit Daniel Kachhap 			return KSFT_FAIL;
133dfe537cfSAmit Daniel Kachhap 		}
134dfe537cfSAmit Daniel Kachhap 		result = check_child_tag_inheritance(ptr, sizes[run], mode);
135dfe537cfSAmit Daniel Kachhap 		mte_clear_tags((void *)ptr, sizes[run]);
136dfe537cfSAmit Daniel Kachhap 		munmap((void *)map_ptr, map_size);
137dfe537cfSAmit Daniel Kachhap 		close(fd);
138dfe537cfSAmit Daniel Kachhap 		if (result != KSFT_PASS)
139dfe537cfSAmit Daniel Kachhap 			return KSFT_FAIL;
140dfe537cfSAmit Daniel Kachhap 	}
141dfe537cfSAmit Daniel Kachhap 	return KSFT_PASS;
142dfe537cfSAmit Daniel Kachhap }
143dfe537cfSAmit Daniel Kachhap 
main(int argc,char * argv[])144dfe537cfSAmit Daniel Kachhap int main(int argc, char *argv[])
145dfe537cfSAmit Daniel Kachhap {
146dfe537cfSAmit Daniel Kachhap 	int err;
147f82efe5bSGuo Zhengkui 	int item = ARRAY_SIZE(sizes);
148dfe537cfSAmit Daniel Kachhap 
149dfe537cfSAmit Daniel Kachhap 	page_size = getpagesize();
150dfe537cfSAmit Daniel Kachhap 	if (!page_size) {
151dfe537cfSAmit Daniel Kachhap 		ksft_print_msg("ERR: Unable to get page size\n");
152dfe537cfSAmit Daniel Kachhap 		return KSFT_FAIL;
153dfe537cfSAmit Daniel Kachhap 	}
154dfe537cfSAmit Daniel Kachhap 	sizes[item - 3] = page_size - 1;
155dfe537cfSAmit Daniel Kachhap 	sizes[item - 2] = page_size;
156dfe537cfSAmit Daniel Kachhap 	sizes[item - 1] = page_size + 1;
157dfe537cfSAmit Daniel Kachhap 
158dfe537cfSAmit Daniel Kachhap 	err = mte_default_setup();
159dfe537cfSAmit Daniel Kachhap 	if (err)
160dfe537cfSAmit Daniel Kachhap 		return err;
161dfe537cfSAmit Daniel Kachhap 
162dfe537cfSAmit Daniel Kachhap 	/* Register SIGSEGV handler */
163dfe537cfSAmit Daniel Kachhap 	mte_register_signal(SIGSEGV, mte_default_handler);
164dfe537cfSAmit Daniel Kachhap 	mte_register_signal(SIGBUS, mte_default_handler);
165dfe537cfSAmit Daniel Kachhap 
166386cf789SVincenzo Frascino 	/* Set test plan */
167386cf789SVincenzo Frascino 	ksft_set_plan(12);
168386cf789SVincenzo Frascino 
169dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
170dfe537cfSAmit Daniel Kachhap 		"Check child anonymous memory with private mapping, precise mode and mmap memory\n");
171dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
172dfe537cfSAmit Daniel Kachhap 		"Check child anonymous memory with shared mapping, precise mode and mmap memory\n");
173dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE),
174dfe537cfSAmit Daniel Kachhap 		"Check child anonymous memory with private mapping, imprecise mode and mmap memory\n");
175dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED),
176dfe537cfSAmit Daniel Kachhap 		"Check child anonymous memory with shared mapping, imprecise mode and mmap memory\n");
177dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
178dfe537cfSAmit Daniel Kachhap 		"Check child anonymous memory with private mapping, precise mode and mmap/mprotect memory\n");
179dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED),
180dfe537cfSAmit Daniel Kachhap 		"Check child anonymous memory with shared mapping, precise mode and mmap/mprotect memory\n");
181dfe537cfSAmit Daniel Kachhap 
182dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_file_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_PRIVATE),
183dfe537cfSAmit Daniel Kachhap 		"Check child file memory with private mapping, precise mode and mmap memory\n");
184dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_file_mapping(USE_MMAP, MTE_SYNC_ERR, MAP_SHARED),
185dfe537cfSAmit Daniel Kachhap 		"Check child file memory with shared mapping, precise mode and mmap memory\n");
186dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_PRIVATE),
187dfe537cfSAmit Daniel Kachhap 		"Check child file memory with private mapping, imprecise mode and mmap memory\n");
188dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MMAP, MTE_ASYNC_ERR, MAP_SHARED),
189dfe537cfSAmit Daniel Kachhap 		"Check child file memory with shared mapping, imprecise mode and mmap memory\n");
190dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_PRIVATE),
191dfe537cfSAmit Daniel Kachhap 		"Check child file memory with private mapping, precise mode and mmap/mprotect memory\n");
192dfe537cfSAmit Daniel Kachhap 	evaluate_test(check_child_memory_mapping(USE_MPROTECT, MTE_SYNC_ERR, MAP_SHARED),
193dfe537cfSAmit Daniel Kachhap 		"Check child file memory with shared mapping, precise mode and mmap/mprotect memory\n");
194dfe537cfSAmit Daniel Kachhap 
195dfe537cfSAmit Daniel Kachhap 	mte_restore_setup();
196dfe537cfSAmit Daniel Kachhap 	ksft_print_cnts();
197dfe537cfSAmit Daniel Kachhap 	return ksft_get_fail_cnt() == 0 ? KSFT_PASS : KSFT_FAIL;
198dfe537cfSAmit Daniel Kachhap }
199