1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2019 ARM Limited */
3
4 #include <ctype.h>
5 #include <string.h>
6
7 #include "testcases.h"
8
validate_extra_context(struct extra_context * extra,char ** err,void ** extra_data,size_t * extra_size)9 bool validate_extra_context(struct extra_context *extra, char **err,
10 void **extra_data, size_t *extra_size)
11 {
12 struct _aarch64_ctx *term;
13
14 if (!extra || !err)
15 return false;
16
17 fprintf(stderr, "Validating EXTRA...\n");
18 term = GET_RESV_NEXT_HEAD(&extra->head);
19 if (!term || term->magic || term->size) {
20 *err = "Missing terminator after EXTRA context";
21 return false;
22 }
23 if (extra->datap & 0x0fUL)
24 *err = "Extra DATAP misaligned";
25 else if (extra->size & 0x0fUL)
26 *err = "Extra SIZE misaligned";
27 else if (extra->datap != (uint64_t)term + 0x10UL)
28 *err = "Extra DATAP misplaced (not contiguous)";
29 if (*err)
30 return false;
31
32 *extra_data = (void *)extra->datap;
33 *extra_size = extra->size;
34
35 return true;
36 }
37
validate_sve_context(struct sve_context * sve,char ** err)38 bool validate_sve_context(struct sve_context *sve, char **err)
39 {
40 /* Size will be rounded up to a multiple of 16 bytes */
41 size_t regs_size
42 = ((SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(sve->vl)) + 15) / 16) * 16;
43
44 if (!sve || !err)
45 return false;
46
47 /* Either a bare sve_context or a sve_context followed by regs data */
48 if ((sve->head.size != sizeof(struct sve_context)) &&
49 (sve->head.size != regs_size)) {
50 *err = "bad size for SVE context";
51 return false;
52 }
53
54 if (!sve_vl_valid(sve->vl)) {
55 *err = "SVE VL invalid";
56
57 return false;
58 }
59
60 return true;
61 }
62
validate_za_context(struct za_context * za,char ** err)63 bool validate_za_context(struct za_context *za, char **err)
64 {
65 /* Size will be rounded up to a multiple of 16 bytes */
66 size_t regs_size
67 = ((ZA_SIG_CONTEXT_SIZE(sve_vq_from_vl(za->vl)) + 15) / 16) * 16;
68
69 if (!za || !err)
70 return false;
71
72 /* Either a bare za_context or a za_context followed by regs data */
73 if ((za->head.size != sizeof(struct za_context)) &&
74 (za->head.size != regs_size)) {
75 *err = "bad size for ZA context";
76 return false;
77 }
78
79 if (!sve_vl_valid(za->vl)) {
80 *err = "SME VL in ZA context invalid";
81
82 return false;
83 }
84
85 return true;
86 }
87
validate_zt_context(struct zt_context * zt,char ** err)88 bool validate_zt_context(struct zt_context *zt, char **err)
89 {
90 if (!zt || !err)
91 return false;
92
93 /* If the context is present there should be at least one register */
94 if (zt->nregs == 0) {
95 *err = "no registers";
96 return false;
97 }
98
99 /* Size should agree with the number of registers */
100 if (zt->head.size != ZT_SIG_CONTEXT_SIZE(zt->nregs)) {
101 *err = "register count does not match size";
102 return false;
103 }
104
105 return true;
106 }
107
validate_reserved(ucontext_t * uc,size_t resv_sz,char ** err)108 bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
109 {
110 bool terminated = false;
111 size_t offs = 0;
112 int flags = 0;
113 int new_flags, i;
114 struct extra_context *extra = NULL;
115 struct sve_context *sve = NULL;
116 struct za_context *za = NULL;
117 struct zt_context *zt = NULL;
118 struct _aarch64_ctx *head =
119 (struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
120 void *extra_data = NULL;
121 size_t extra_sz = 0;
122 char magic[4];
123
124 if (!err)
125 return false;
126 /* Walk till the end terminator verifying __reserved contents */
127 while (head && !terminated && offs < resv_sz) {
128 if ((uint64_t)head & 0x0fUL) {
129 *err = "Misaligned HEAD";
130 return false;
131 }
132
133 new_flags = 0;
134
135 switch (head->magic) {
136 case 0:
137 if (head->size) {
138 *err = "Bad size for terminator";
139 } else if (extra_data) {
140 /* End of main data, walking the extra data */
141 head = extra_data;
142 resv_sz = extra_sz;
143 offs = 0;
144
145 extra_data = NULL;
146 extra_sz = 0;
147 continue;
148 } else {
149 terminated = true;
150 }
151 break;
152 case FPSIMD_MAGIC:
153 if (flags & FPSIMD_CTX)
154 *err = "Multiple FPSIMD_MAGIC";
155 else if (head->size !=
156 sizeof(struct fpsimd_context))
157 *err = "Bad size for fpsimd_context";
158 new_flags |= FPSIMD_CTX;
159 break;
160 case ESR_MAGIC:
161 if (head->size != sizeof(struct esr_context))
162 *err = "Bad size for esr_context";
163 break;
164 case POE_MAGIC:
165 if (head->size != sizeof(struct poe_context))
166 *err = "Bad size for poe_context";
167 break;
168 case TPIDR2_MAGIC:
169 if (head->size != sizeof(struct tpidr2_context))
170 *err = "Bad size for tpidr2_context";
171 break;
172 case SVE_MAGIC:
173 if (flags & SVE_CTX)
174 *err = "Multiple SVE_MAGIC";
175 /* Size is validated in validate_sve_context() */
176 sve = (struct sve_context *)head;
177 new_flags |= SVE_CTX;
178 break;
179 case ZA_MAGIC:
180 if (flags & ZA_CTX)
181 *err = "Multiple ZA_MAGIC";
182 /* Size is validated in validate_za_context() */
183 za = (struct za_context *)head;
184 new_flags |= ZA_CTX;
185 break;
186 case ZT_MAGIC:
187 if (flags & ZT_CTX)
188 *err = "Multiple ZT_MAGIC";
189 /* Size is validated in validate_za_context() */
190 zt = (struct zt_context *)head;
191 new_flags |= ZT_CTX;
192 break;
193 case FPMR_MAGIC:
194 if (flags & FPMR_CTX)
195 *err = "Multiple FPMR_MAGIC";
196 else if (head->size !=
197 sizeof(struct fpmr_context))
198 *err = "Bad size for fpmr_context";
199 new_flags |= FPMR_CTX;
200 break;
201 case GCS_MAGIC:
202 if (flags & GCS_CTX)
203 *err = "Multiple GCS_MAGIC";
204 if (head->size != sizeof(struct gcs_context))
205 *err = "Bad size for gcs_context";
206 new_flags |= GCS_CTX;
207 break;
208 case EXTRA_MAGIC:
209 if (flags & EXTRA_CTX)
210 *err = "Multiple EXTRA_MAGIC";
211 else if (head->size !=
212 sizeof(struct extra_context))
213 *err = "Bad size for extra_context";
214 new_flags |= EXTRA_CTX;
215 extra = (struct extra_context *)head;
216 break;
217 case KSFT_BAD_MAGIC:
218 /*
219 * This is a BAD magic header defined
220 * artificially by a testcase and surely
221 * unknown to the Kernel parse_user_sigframe().
222 * It MUST cause a Kernel induced SEGV
223 */
224 *err = "BAD MAGIC !";
225 break;
226 default:
227 /*
228 * A still unknown Magic: potentially freshly added
229 * to the Kernel code and still unknown to the
230 * tests. Magic numbers are supposed to be allocated
231 * as somewhat meaningful ASCII strings so try to
232 * print as such as well as the raw number.
233 */
234 memcpy(magic, &head->magic, sizeof(magic));
235 for (i = 0; i < sizeof(magic); i++)
236 if (!isalnum(magic[i]))
237 magic[i] = '?';
238
239 fprintf(stdout,
240 "SKIP Unknown MAGIC: 0x%X (%c%c%c%c) - Is KSFT arm64/signal up to date ?\n",
241 head->magic,
242 magic[3], magic[2], magic[1], magic[0]);
243 break;
244 }
245
246 if (*err)
247 return false;
248
249 offs += head->size;
250 if (resv_sz < offs + sizeof(*head)) {
251 *err = "HEAD Overrun";
252 return false;
253 }
254
255 if (new_flags & EXTRA_CTX)
256 if (!validate_extra_context(extra, err,
257 &extra_data, &extra_sz))
258 return false;
259 if (new_flags & SVE_CTX)
260 if (!validate_sve_context(sve, err))
261 return false;
262 if (new_flags & ZA_CTX)
263 if (!validate_za_context(za, err))
264 return false;
265 if (new_flags & ZT_CTX)
266 if (!validate_zt_context(zt, err))
267 return false;
268
269 flags |= new_flags;
270
271 head = GET_RESV_NEXT_HEAD(head);
272 }
273
274 if (terminated && !(flags & FPSIMD_CTX)) {
275 *err = "Missing FPSIMD";
276 return false;
277 }
278
279 if (terminated && (flags & ZT_CTX) && !(flags & ZA_CTX)) {
280 *err = "ZT context but no ZA context";
281 return false;
282 }
283
284 return true;
285 }
286
287 /*
288 * This function walks through the records inside the provided reserved area
289 * trying to find enough space to fit @need_sz bytes: if not enough space is
290 * available and an extra_context record is present, it throws away the
291 * extra_context record.
292 *
293 * It returns a pointer to a new header where it is possible to start storing
294 * our need_sz bytes.
295 *
296 * @shead: points to the start of reserved area
297 * @need_sz: needed bytes
298 * @resv_sz: reserved area size in bytes
299 * @offset: if not null, this will be filled with the offset of the return
300 * head pointer from @shead
301 *
302 * @return: pointer to a new head where to start storing need_sz bytes, or
303 * NULL if space could not be made available.
304 */
get_starting_head(struct _aarch64_ctx * shead,size_t need_sz,size_t resv_sz,size_t * offset)305 struct _aarch64_ctx *get_starting_head(struct _aarch64_ctx *shead,
306 size_t need_sz, size_t resv_sz,
307 size_t *offset)
308 {
309 size_t offs = 0;
310 struct _aarch64_ctx *head;
311
312 head = get_terminator(shead, resv_sz, &offs);
313 /* not found a terminator...no need to update offset if any */
314 if (!head)
315 return head;
316 if (resv_sz - offs < need_sz) {
317 fprintf(stderr, "Low on space:%zd. Discarding extra_context.\n",
318 resv_sz - offs);
319 head = get_header(shead, EXTRA_MAGIC, resv_sz, &offs);
320 if (!head || resv_sz - offs < need_sz) {
321 fprintf(stderr,
322 "Failed to reclaim space on sigframe.\n");
323 return NULL;
324 }
325 }
326
327 fprintf(stderr, "Available space:%zd\n", resv_sz - offs);
328 if (offset)
329 *offset = offs;
330 return head;
331 }
332