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 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 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 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