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;
88*f82efe5bSGuo Zhengkui int item = ARRAY_SIZE(sizes);
89dfe537cfSAmit Daniel Kachhap
90*f82efe5bSGuo 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;
110*f82efe5bSGuo 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;
147*f82efe5bSGuo 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