1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2019 ARM Limited */
5 struct _aarch64_ctx
*get_header(struct _aarch64_ctx
*head
, uint32_t magic
,
6 size_t resv_sz
, size_t *offset
)
9 struct _aarch64_ctx
*found
= NULL
;
11 if (!head
|| resv_sz
< HDR_SZ
)
14 while (offs
<= resv_sz
- HDR_SZ
&&
15 head
->magic
!= magic
&& head
->magic
) {
17 head
= GET_RESV_NEXT_HEAD(head
);
19 if (head
->magic
== magic
) {
28 bool validate_extra_context(struct extra_context
*extra
, char **err
)
30 struct _aarch64_ctx
*term
;
35 fprintf(stderr
, "Validating EXTRA...\n");
36 term
= GET_RESV_NEXT_HEAD(extra
);
37 if (!term
|| term
->magic
|| term
->size
) {
38 *err
= "Missing terminator after EXTRA context";
41 if (extra
->datap
& 0x0fUL
)
42 *err
= "Extra DATAP misaligned";
43 else if (extra
->size
& 0x0fUL
)
44 *err
= "Extra SIZE misaligned";
45 else if (extra
->datap
!= (uint64_t)term
+ sizeof(*term
))
46 *err
= "Extra DATAP misplaced (not contiguous)";
53 bool validate_reserved(ucontext_t
*uc
, size_t resv_sz
, char **err
)
55 bool terminated
= false;
58 struct extra_context
*extra
= NULL
;
59 struct _aarch64_ctx
*head
=
60 (struct _aarch64_ctx
*)uc
->uc_mcontext
.__reserved
;
64 /* Walk till the end terminator verifying __reserved contents */
65 while (head
&& !terminated
&& offs
< resv_sz
) {
66 if ((uint64_t)head
& 0x0fUL
) {
67 *err
= "Misaligned HEAD";
71 switch (head
->magic
) {
74 *err
= "Bad size for terminator";
79 if (flags
& FPSIMD_CTX
)
80 *err
= "Multiple FPSIMD_MAGIC";
81 else if (head
->size
!=
82 sizeof(struct fpsimd_context
))
83 *err
= "Bad size for fpsimd_context";
87 if (head
->size
!= sizeof(struct esr_context
))
88 *err
= "Bad size for esr_context";
92 *err
= "Multiple SVE_MAGIC";
93 else if (head
->size
!=
94 sizeof(struct sve_context
))
95 *err
= "Bad size for sve_context";
99 if (flags
& EXTRA_CTX
)
100 *err
= "Multiple EXTRA_MAGIC";
101 else if (head
->size
!=
102 sizeof(struct extra_context
))
103 *err
= "Bad size for extra_context";
105 extra
= (struct extra_context
*)head
;
109 * This is a BAD magic header defined
110 * artificially by a testcase and surely
111 * unknown to the Kernel parse_user_sigframe().
112 * It MUST cause a Kernel induced SEGV
114 *err
= "BAD MAGIC !";
118 * A still unknown Magic: potentially freshly added
119 * to the Kernel code and still unknown to the
123 "SKIP Unknown MAGIC: 0x%X - Is KSFT arm64/signal up to date ?\n",
132 if (resv_sz
< offs
+ sizeof(*head
)) {
133 *err
= "HEAD Overrun";
137 if (flags
& EXTRA_CTX
)
138 if (!validate_extra_context(extra
, err
))
141 head
= GET_RESV_NEXT_HEAD(head
);
144 if (terminated
&& !(flags
& FPSIMD_CTX
)) {
145 *err
= "Missing FPSIMD";
153 * This function walks through the records inside the provided reserved area
154 * trying to find enough space to fit @need_sz bytes: if not enough space is
155 * available and an extra_context record is present, it throws away the
156 * extra_context record.
158 * It returns a pointer to a new header where it is possible to start storing
161 * @shead: points to the start of reserved area
162 * @need_sz: needed bytes
163 * @resv_sz: reserved area size in bytes
164 * @offset: if not null, this will be filled with the offset of the return
165 * head pointer from @shead
167 * @return: pointer to a new head where to start storing need_sz bytes, or
168 * NULL if space could not be made available.
170 struct _aarch64_ctx
*get_starting_head(struct _aarch64_ctx
*shead
,
171 size_t need_sz
, size_t resv_sz
,
175 struct _aarch64_ctx
*head
;
177 head
= get_terminator(shead
, resv_sz
, &offs
);
178 /* not found a terminator...no need to update offset if any */
181 if (resv_sz
- offs
< need_sz
) {
182 fprintf(stderr
, "Low on space:%zd. Discarding extra_context.\n",
184 head
= get_header(shead
, EXTRA_MAGIC
, resv_sz
, &offs
);
185 if (!head
|| resv_sz
- offs
< need_sz
) {
187 "Failed to reclaim space on sigframe.\n");
192 fprintf(stderr
, "Available space:%zd\n", resv_sz
- offs
);