~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/testing/selftests/arm64/signal/testcases/testcases.c

Version: ~ [ linux-6.11-rc3 ] ~ [ linux-6.10.4 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.45 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.104 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.164 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.223 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.281 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.319 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php