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