1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
|
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2019 ARM Limited */
#ifndef __TESTCASES_H__
#define __TESTCASES_H__
#include <stddef.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <ucontext.h>
#include <signal.h>
/* Architecture specific sigframe definitions */
#include <asm/sigcontext.h>
#define FPSIMD_CTX (1 << 0)
#define SVE_CTX (1 << 1)
#define ZA_CTX (1 << 2)
#define EXTRA_CTX (1 << 3)
#define ZT_CTX (1 << 4)
#define FPMR_CTX (1 << 5)
#define KSFT_BAD_MAGIC 0xdeadbeef
#define HDR_SZ \
sizeof(struct _aarch64_ctx)
#define GET_UC_RESV_HEAD(uc) \
(struct _aarch64_ctx *)(&(uc->uc_mcontext.__reserved))
#define GET_SF_RESV_HEAD(sf) \
(struct _aarch64_ctx *)(&(sf).uc.uc_mcontext.__reserved)
#define GET_SF_RESV_SIZE(sf) \
sizeof((sf).uc.uc_mcontext.__reserved)
#define GET_BUF_RESV_HEAD(buf) \
(struct _aarch64_ctx *)(&(buf).uc.uc_mcontext.__reserved)
#define GET_BUF_RESV_SIZE(buf) \
(sizeof(buf) - sizeof(buf.uc) + \
sizeof((buf).uc.uc_mcontext.__reserved))
#define GET_UCP_RESV_SIZE(ucp) \
sizeof((ucp)->uc_mcontext.__reserved)
#define ASSERT_BAD_CONTEXT(uc) do { \
char *err = NULL; \
if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) { \
if (err) \
fprintf(stderr, \
"Using badly built context - ERR: %s\n",\
err); \
} else { \
abort(); \
} \
} while (0)
#define ASSERT_GOOD_CONTEXT(uc) do { \
char *err = NULL; \
if (!validate_reserved((uc), GET_UCP_RESV_SIZE((uc)), &err)) { \
if (err) \
fprintf(stderr, \
"Detected BAD context - ERR: %s\n", err);\
abort(); \
} else { \
fprintf(stderr, "uc context validated.\n"); \
} \
} while (0)
/*
* A simple record-walker for __reserved area: it walks through assuming
* only to find a proper struct __aarch64_ctx header descriptor.
*
* Instead it makes no assumptions on the content and ordering of the
* records, any needed bounds checking must be enforced by the caller
* if wanted: this way can be used by caller on any maliciously built bad
* contexts.
*
* head->size accounts both for payload and header _aarch64_ctx size !
*/
#define GET_RESV_NEXT_HEAD(h) \
(struct _aarch64_ctx *)((char *)(h) + (h)->size)
struct fake_sigframe {
siginfo_t info;
ucontext_t uc;
};
bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err);
static inline struct _aarch64_ctx *get_header(struct _aarch64_ctx *head, uint32_t magic,
size_t resv_sz, size_t *offset)
{
size_t offs = 0;
struct _aarch64_ctx *found = NULL;
if (!head || resv_sz < HDR_SZ)
return found;
while (offs <= resv_sz - HDR_SZ &&
head->magic != magic && head->magic) {
offs += head->size;
head = GET_RESV_NEXT_HEAD(head);
}
if (head->magic == magic) {
found = head;
if (offset)
*offset = offs;
}
return found;
}
static inline struct _aarch64_ctx *get_terminator(struct _aarch64_ctx *head,
size_t resv_sz,
size_t *offset)
{
return get_header(head, 0, resv_sz, offset);
}
static inline void write_terminator_record(struct _aarch64_ctx *tail)
{
if (tail) {
tail->magic = 0;
tail->size = 0;
}
}
struct _aarch64_ctx *get_starting_head(struct _aarch64_ctx *shead,
size_t need_sz, size_t resv_sz,
size_t *offset);
#endif
|