master
h 80 lines 2.94 KB
Raw
1 /*
2 * Linux kernel fallback API definitions for GCS and test helpers.
3 *
4 * Copyright (c) 2025 Linaro Ltd
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 */
7
8 #include <assert.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <stdint.h>
13 #include <unistd.h>
14 #include <errno.h>
15 #include <signal.h>
16 #include <sys/mman.h>
17 #include <sys/prctl.h>
18 #include <sys/syscall.h>
19
20 #ifndef PR_GET_SHADOW_STACK_STATUS
21 #define PR_GET_SHADOW_STACK_STATUS 74
22 #endif
23 #ifndef PR_SET_SHADOW_STACK_STATUS
24 #define PR_SET_SHADOW_STACK_STATUS 75
25 #endif
26 #ifndef PR_LOCK_SHADOW_STACK_STATUS
27 #define PR_LOCK_SHADOW_STACK_STATUS 76
28 #endif
29 #ifndef PR_SHADOW_STACK_ENABLE
30 # define PR_SHADOW_STACK_ENABLE (1 << 0)
31 # define PR_SHADOW_STACK_WRITE (1 << 1)
32 # define PR_SHADOW_STACK_PUSH (1 << 2)
33 #endif
34 #ifndef SHADOW_STACK_SET_TOKEN
35 #define SHADOW_STACK_SET_TOKEN (1 << 0)
36 #endif
37 #ifndef SHADOW_STACK_SET_MARKER
38 #define SHADOW_STACK_SET_MARKER (1 << 1)
39 #endif
40 #ifndef SEGV_CPERR
41 #define SEGV_CPERR 10
42 #endif
43 #ifndef __NR_map_shadow_stack
44 #define __NR_map_shadow_stack 453
45 #endif
46
47 /*
48 * Macros, and implement the syscall inline, lest we fail
49 * the checked return from any function call.
50 */
51 #define enable_gcs(flags) \
52 do { \
53 register long num __asm__ ("x8") = __NR_prctl; \
54 register long arg1 __asm__ ("x0") = PR_SET_SHADOW_STACK_STATUS; \
55 register long arg2 __asm__ ("x1") = PR_SHADOW_STACK_ENABLE | flags; \
56 register long arg3 __asm__ ("x2") = 0; \
57 register long arg4 __asm__ ("x3") = 0; \
58 register long arg5 __asm__ ("x4") = 0; \
59 asm volatile("svc #0" \
60 : "+r"(arg1) \
61 : "r"(arg2), "r"(arg3), "r"(arg4), "r"(arg5), "r"(num) \
62 : "memory", "cc"); \
63 if (arg1) { \
64 errno = -arg1; \
65 perror("PR_SET_SHADOW_STACK_STATUS"); \
66 exit(2); \
67 } \
68 } while (0)
69
70 #define gcspr() \
71 ({ uint64_t *r; asm volatile("mrs %0, s3_3_c2_c5_1" : "=r"(r)); r; })
72
73 #define gcsss1(val) \
74 do { \
75 asm volatile("sys #3, c7, c7, #2, %0" : : "r"(val) : "memory"); \
76 } while (0)
77
78 #define gcsss2() \
79 ({ uint64_t *r; \
80 asm volatile("sysl %0, #3, c7, c7, #3" : "=r"(r) : : "memory"); r; })