1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2023 ARM Limited
4 */
5
6 #include <errno.h>
7 #include <signal.h>
8 #include <unistd.h>
9
10 #include <sys/mman.h>
11 #include <sys/prctl.h>
12
13 #include "test_signals_utils.h"
14 #include "testcases.h"
15
16 static uint64_t *gcs_page;
17
18 #ifndef __NR_map_shadow_stack
19 #define __NR_map_shadow_stack 453
20 #endif
21
alloc_gcs(struct tdescr * td)22 static bool alloc_gcs(struct tdescr *td)
23 {
24 long page_size = sysconf(_SC_PAGE_SIZE);
25
26 gcs_page = (void *)syscall(__NR_map_shadow_stack, 0,
27 page_size, 0);
28 if (gcs_page == MAP_FAILED) {
29 fprintf(stderr, "Failed to map %ld byte GCS: %d\n",
30 page_size, errno);
31 return false;
32 }
33
34 return true;
35 }
36
gcs_write_fault_trigger(struct tdescr * td)37 static int gcs_write_fault_trigger(struct tdescr *td)
38 {
39 /* Verify that the page is readable (ie, not completely unmapped) */
40 fprintf(stderr, "Read value 0x%lx\n", gcs_page[0]);
41
42 /* A regular write should trigger a fault */
43 gcs_page[0] = EINVAL;
44
45 return 0;
46 }
47
gcs_write_fault_signal(struct tdescr * td,siginfo_t * si,ucontext_t * uc)48 static int gcs_write_fault_signal(struct tdescr *td, siginfo_t *si,
49 ucontext_t *uc)
50 {
51 ASSERT_GOOD_CONTEXT(uc);
52
53 return 1;
54 }
55
56
57 struct tdescr tde = {
58 .name = "GCS write fault",
59 .descr = "Normal writes to a GCS segfault",
60 .feats_required = FEAT_GCS,
61 .timeout = 3,
62 .sig_ok = SIGSEGV,
63 .sanity_disabled = true,
64 .init = alloc_gcs,
65 .trigger = gcs_write_fault_trigger,
66 .run = gcs_write_fault_signal,
67 };
68