1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (C) 2020 ARM Limited */
3
4 #ifndef _MTE_COMMON_UTIL_H
5 #define _MTE_COMMON_UTIL_H
6
7 #include <signal.h>
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <sys/auxv.h>
11 #include <sys/mman.h>
12 #include <sys/prctl.h>
13 #include "mte_def.h"
14 #include "kselftest.h"
15
16 enum mte_mem_type {
17 USE_MALLOC,
18 USE_MMAP,
19 USE_MPROTECT,
20 };
21
22 enum mte_mode {
23 MTE_NONE_ERR,
24 MTE_SYNC_ERR,
25 MTE_ASYNC_ERR,
26 };
27
28 struct mte_fault_cxt {
29 /* Address start which triggers mte tag fault */
30 unsigned long trig_addr;
31 /* Address range for mte tag fault and negative value means underflow */
32 ssize_t trig_range;
33 /* siginfo si code */
34 unsigned long trig_si_code;
35 /* Flag to denote if correct fault caught */
36 bool fault_valid;
37 };
38
39 extern struct mte_fault_cxt cur_mte_cxt;
40 extern bool mtefar_support;
41 extern bool mtestonly_support;
42
43 /* MTE utility functions */
44 void mte_default_handler(int signum, siginfo_t *si, void *uc);
45 void mte_register_signal(int signal, void (*handler)(int, siginfo_t *, void *),
46 bool export_tags);
47 void mte_wait_after_trig(void);
48 void *mte_allocate_memory(size_t size, int mem_type, int mapping, bool tags);
49 void *mte_allocate_memory_tag_range(size_t size, int mem_type, int mapping,
50 size_t range_before, size_t range_after);
51 void *mte_allocate_file_memory(size_t size, int mem_type, int mapping,
52 bool tags, int fd);
53 void *mte_allocate_file_memory_tag_range(size_t size, int mem_type, int mapping,
54 size_t range_before, size_t range_after, int fd);
55 void mte_free_memory(void *ptr, size_t size, int mem_type, bool tags);
56 void mte_free_memory_tag_range(void *ptr, size_t size, int mem_type,
57 size_t range_before, size_t range_after);
58 void *mte_insert_tags(void *ptr, size_t size);
59 void mte_clear_tags(void *ptr, size_t size);
60 void *mte_insert_atag(void *ptr);
61 void *mte_clear_atag(void *ptr);
62 int mte_default_setup(void);
63 void mte_restore_setup(void);
64 int mte_switch_mode(int mte_option, unsigned long incl_mask, bool stonly);
65 void mte_initialize_current_context(int mode, uintptr_t ptr, ssize_t range);
66
67 /* Safe memory access functions */
68 void *memset_safe(void *s, int c, size_t n);
69 void *memcpy_safe(void *dest, const void *src, size_t n);
70
71 /* Common utility functions */
72 int create_temp_file(void);
73
74 /* Assembly MTE utility functions */
75 void *mte_insert_random_tag(void *ptr);
76 void *mte_insert_new_tag(void *ptr);
77 void *mte_get_tag_address(void *ptr);
78 void mte_set_tag_address_range(void *ptr, int range);
79 void mte_clear_tag_address_range(void *ptr, int range);
80 void mte_disable_pstate_tco(void);
81 void mte_enable_pstate_tco(void);
82 unsigned int mte_get_pstate_tco(void);
83
84 /* Test framework static inline functions/macros */
evaluate_test(int err,const char * msg)85 static inline void evaluate_test(int err, const char *msg)
86 {
87 switch (err) {
88 case KSFT_PASS:
89 ksft_test_result_pass("%s", msg);
90 break;
91 case KSFT_FAIL:
92 ksft_test_result_fail("%s", msg);
93 break;
94 case KSFT_SKIP:
95 ksft_test_result_skip("%s", msg);
96 break;
97 default:
98 ksft_test_result_error("Unknown return code %d from %s",
99 err, msg);
100 break;
101 }
102 }
103
check_allocated_memory(void * ptr,size_t size,int mem_type,bool tags)104 static inline int check_allocated_memory(void *ptr, size_t size,
105 int mem_type, bool tags)
106 {
107 if (ptr == NULL) {
108 ksft_print_msg("FAIL: memory allocation\n");
109 return KSFT_FAIL;
110 }
111
112 if (tags && !MT_FETCH_TAG((uintptr_t)ptr)) {
113 ksft_print_msg("FAIL: tag not found at addr(%p)\n", ptr);
114 mte_free_memory((void *)ptr, size, mem_type, false);
115 return KSFT_FAIL;
116 }
117
118 return KSFT_PASS;
119 }
120
check_allocated_memory_range(void * ptr,size_t size,int mem_type,size_t range_before,size_t range_after)121 static inline int check_allocated_memory_range(void *ptr, size_t size, int mem_type,
122 size_t range_before, size_t range_after)
123 {
124 if (ptr == NULL) {
125 ksft_print_msg("FAIL: memory allocation\n");
126 return KSFT_FAIL;
127 }
128
129 if (!MT_FETCH_TAG((uintptr_t)ptr)) {
130 ksft_print_msg("FAIL: tag not found at addr(%p)\n", ptr);
131 mte_free_memory_tag_range((void *)ptr, size, mem_type, range_before,
132 range_after);
133 return KSFT_FAIL;
134 }
135 return KSFT_PASS;
136 }
137
138 #endif /* _MTE_COMMON_UTIL_H */
139