Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright (C) 2019 ARM Limited */
0003 #include "testcases.h"
0004 
0005 struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
0006                 size_t resv_sz, size_t *offset)
0007 {
0008     size_t offs = 0;
0009     struct _aarch64_ctx *found = NULL;
0010 
0011     if (!head || resv_sz < HDR_SZ)
0012         return found;
0013 
0014     while (offs <= resv_sz - HDR_SZ &&
0015            head->magic != magic && head->magic) {
0016         offs += head->size;
0017         head = GET_RESV_NEXT_HEAD(head);
0018     }
0019     if (head->magic == magic) {
0020         found = head;
0021         if (offset)
0022             *offset = offs;
0023     }
0024 
0025     return found;
0026 }
0027 
0028 bool validate_extra_context(struct extra_context *extra, char **err)
0029 {
0030     struct _aarch64_ctx *term;
0031 
0032     if (!extra || !err)
0033         return false;
0034 
0035     fprintf(stderr, "Validating EXTRA...\n");
0036     term = GET_RESV_NEXT_HEAD(extra);
0037     if (!term || term->magic || term->size) {
0038         *err = "Missing terminator after EXTRA context";
0039         return false;
0040     }
0041     if (extra->datap & 0x0fUL)
0042         *err = "Extra DATAP misaligned";
0043     else if (extra->size & 0x0fUL)
0044         *err = "Extra SIZE misaligned";
0045     else if (extra->datap != (uint64_t)term + sizeof(*term))
0046         *err = "Extra DATAP misplaced (not contiguous)";
0047     if (*err)
0048         return false;
0049 
0050     return true;
0051 }
0052 
0053 bool validate_sve_context(struct sve_context *sve, char **err)
0054 {
0055     /* Size will be rounded up to a multiple of 16 bytes */
0056     size_t regs_size
0057         = ((SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(sve->vl)) + 15) / 16) * 16;
0058 
0059     if (!sve || !err)
0060         return false;
0061 
0062     /* Either a bare sve_context or a sve_context followed by regs data */
0063     if ((sve->head.size != sizeof(struct sve_context)) &&
0064         (sve->head.size != regs_size)) {
0065         *err = "bad size for SVE context";
0066         return false;
0067     }
0068 
0069     if (!sve_vl_valid(sve->vl)) {
0070         *err = "SVE VL invalid";
0071 
0072         return false;
0073     }
0074 
0075     return true;
0076 }
0077 
0078 bool validate_za_context(struct za_context *za, char **err)
0079 {
0080     /* Size will be rounded up to a multiple of 16 bytes */
0081     size_t regs_size
0082         = ((ZA_SIG_CONTEXT_SIZE(sve_vq_from_vl(za->vl)) + 15) / 16) * 16;
0083 
0084     if (!za || !err)
0085         return false;
0086 
0087     /* Either a bare za_context or a za_context followed by regs data */
0088     if ((za->head.size != sizeof(struct za_context)) &&
0089         (za->head.size != regs_size)) {
0090         *err = "bad size for ZA context";
0091         return false;
0092     }
0093 
0094     if (!sve_vl_valid(za->vl)) {
0095         *err = "SME VL in ZA context invalid";
0096 
0097         return false;
0098     }
0099 
0100     return true;
0101 }
0102 
0103 bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err)
0104 {
0105     bool terminated = false;
0106     size_t offs = 0;
0107     int flags = 0;
0108     struct extra_context *extra = NULL;
0109     struct sve_context *sve = NULL;
0110     struct za_context *za = NULL;
0111     struct _aarch64_ctx *head =
0112         (struct _aarch64_ctx *)uc->uc_mcontext.__reserved;
0113 
0114     if (!err)
0115         return false;
0116     /* Walk till the end terminator verifying __reserved contents */
0117     while (head && !terminated && offs < resv_sz) {
0118         if ((uint64_t)head & 0x0fUL) {
0119             *err = "Misaligned HEAD";
0120             return false;
0121         }
0122 
0123         switch (head->magic) {
0124         case 0:
0125             if (head->size)
0126                 *err = "Bad size for terminator";
0127             else
0128                 terminated = true;
0129             break;
0130         case FPSIMD_MAGIC:
0131             if (flags & FPSIMD_CTX)
0132                 *err = "Multiple FPSIMD_MAGIC";
0133             else if (head->size !=
0134                  sizeof(struct fpsimd_context))
0135                 *err = "Bad size for fpsimd_context";
0136             flags |= FPSIMD_CTX;
0137             break;
0138         case ESR_MAGIC:
0139             if (head->size != sizeof(struct esr_context))
0140                 *err = "Bad size for esr_context";
0141             break;
0142         case SVE_MAGIC:
0143             if (flags & SVE_CTX)
0144                 *err = "Multiple SVE_MAGIC";
0145             /* Size is validated in validate_sve_context() */
0146             sve = (struct sve_context *)head;
0147             flags |= SVE_CTX;
0148             break;
0149         case ZA_MAGIC:
0150             if (flags & ZA_CTX)
0151                 *err = "Multiple ZA_MAGIC";
0152             /* Size is validated in validate_za_context() */
0153             za = (struct za_context *)head;
0154             flags |= ZA_CTX;
0155             break;
0156         case EXTRA_MAGIC:
0157             if (flags & EXTRA_CTX)
0158                 *err = "Multiple EXTRA_MAGIC";
0159             else if (head->size !=
0160                  sizeof(struct extra_context))
0161                 *err = "Bad size for extra_context";
0162             flags |= EXTRA_CTX;
0163             extra = (struct extra_context *)head;
0164             break;
0165         case KSFT_BAD_MAGIC:
0166             /*
0167              * This is a BAD magic header defined
0168              * artificially by a testcase and surely
0169              * unknown to the Kernel parse_user_sigframe().
0170              * It MUST cause a Kernel induced SEGV
0171              */
0172             *err = "BAD MAGIC !";
0173             break;
0174         default:
0175             /*
0176              * A still unknown Magic: potentially freshly added
0177              * to the Kernel code and still unknown to the
0178              * tests.
0179              */
0180             fprintf(stdout,
0181                 "SKIP Unknown MAGIC: 0x%X - Is KSFT arm64/signal up to date ?\n",
0182                 head->magic);
0183             break;
0184         }
0185 
0186         if (*err)
0187             return false;
0188 
0189         offs += head->size;
0190         if (resv_sz < offs + sizeof(*head)) {
0191             *err = "HEAD Overrun";
0192             return false;
0193         }
0194 
0195         if (flags & EXTRA_CTX)
0196             if (!validate_extra_context(extra, err))
0197                 return false;
0198         if (flags & SVE_CTX)
0199             if (!validate_sve_context(sve, err))
0200                 return false;
0201         if (flags & ZA_CTX)
0202             if (!validate_za_context(za, err))
0203                 return false;
0204 
0205         head = GET_RESV_NEXT_HEAD(head);
0206     }
0207 
0208     if (terminated && !(flags & FPSIMD_CTX)) {
0209         *err = "Missing FPSIMD";
0210         return false;
0211     }
0212 
0213     return true;
0214 }
0215 
0216 /*
0217  * This function walks through the records inside the provided reserved area
0218  * trying to find enough space to fit @need_sz bytes: if not enough space is
0219  * available and an extra_context record is present, it throws away the
0220  * extra_context record.
0221  *
0222  * It returns a pointer to a new header where it is possible to start storing
0223  * our need_sz bytes.
0224  *
0225  * @shead: points to the start of reserved area
0226  * @need_sz: needed bytes
0227  * @resv_sz: reserved area size in bytes
0228  * @offset: if not null, this will be filled with the offset of the return
0229  *      head pointer from @shead
0230  *
0231  * @return: pointer to a new head where to start storing need_sz bytes, or
0232  *      NULL if space could not be made available.
0233  */
0234 struct _aarch64_ctx *get_starting_head(struct _aarch64_ctx *shead,
0235                        size_t need_sz, size_t resv_sz,
0236                        size_t *offset)
0237 {
0238     size_t offs = 0;
0239     struct _aarch64_ctx *head;
0240 
0241     head = get_terminator(shead, resv_sz, &offs);
0242     /* not found a terminator...no need to update offset if any */
0243     if (!head)
0244         return head;
0245     if (resv_sz - offs < need_sz) {
0246         fprintf(stderr, "Low on space:%zd. Discarding extra_context.\n",
0247             resv_sz - offs);
0248         head = get_header(shead, EXTRA_MAGIC, resv_sz, &offs);
0249         if (!head || resv_sz - offs < need_sz) {
0250             fprintf(stderr,
0251                 "Failed to reclaim space on sigframe.\n");
0252             return NULL;
0253         }
0254     }
0255 
0256     fprintf(stderr, "Available space:%zd\n", resv_sz - offs);
0257     if (offset)
0258         *offset = offs;
0259     return head;
0260 }