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