1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2023 ARM Limited 4 */ 5 6 #include <signal.h> 7 #include <ucontext.h> 8 #include <sys/prctl.h> 9 10 #include "test_signals_utils.h" 11 #include "testcases.h" 12 13 static union { 14 ucontext_t uc; 15 char buf[1024 * 64]; 16 } context; 17 18 static int gcs_regs(struct tdescr *td, siginfo_t *si, ucontext_t *uc) 19 { 20 size_t offset; 21 struct _aarch64_ctx *head = GET_BUF_RESV_HEAD(context); 22 struct gcs_context *gcs; 23 unsigned long expected, gcspr; 24 uint64_t *u64_val; 25 int ret; 26 27 ret = prctl(PR_GET_SHADOW_STACK_STATUS, &expected, 0, 0, 0); 28 if (ret != 0) { 29 fprintf(stderr, "Unable to query GCS status\n"); 30 return 1; 31 } 32 33 /* We expect a cap to be added to the GCS in the signal frame */ 34 gcspr = get_gcspr_el0(); 35 gcspr -= 8; 36 fprintf(stderr, "Expecting GCSPR_EL0 %lx\n", gcspr); 37 38 if (!get_current_context(td, &context.uc, sizeof(context))) { 39 fprintf(stderr, "Failed getting context\n"); 40 return 1; 41 } 42 43 /* Ensure that the signal restore token was consumed */ 44 u64_val = (uint64_t *)get_gcspr_el0() + 1; 45 if (*u64_val) { 46 fprintf(stderr, "GCS value at %p is %lx not 0\n", 47 u64_val, *u64_val); 48 return 1; 49 } 50 51 fprintf(stderr, "Got context\n"); 52 53 head = get_header(head, GCS_MAGIC, GET_BUF_RESV_SIZE(context), 54 &offset); 55 if (!head) { 56 fprintf(stderr, "No GCS context\n"); 57 return 1; 58 } 59 60 gcs = (struct gcs_context *)head; 61 62 /* Basic size validation is done in get_current_context() */ 63 64 if (gcs->features_enabled != expected) { 65 fprintf(stderr, "Features enabled %llx but expected %lx\n", 66 gcs->features_enabled, expected); 67 return 1; 68 } 69 70 if (gcs->gcspr != gcspr) { 71 fprintf(stderr, "Got GCSPR %llx but expected %lx\n", 72 gcs->gcspr, gcspr); 73 return 1; 74 } 75 76 fprintf(stderr, "GCS context validated\n"); 77 td->pass = 1; 78 79 return 0; 80 } 81 82 struct tdescr tde = { 83 .name = "GCS basics", 84 .descr = "Validate a GCS signal context", 85 .feats_required = FEAT_GCS, 86 .timeout = 3, 87 .run = gcs_regs, 88 }; 89