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