1*48f8d9ceSMark Brown// SPDX-License-Identifier: GPL-2.0-only 2*48f8d9ceSMark Brown// 3*48f8d9ceSMark Brown// Copyright 2024 Arm Limited 4*48f8d9ceSMark Brown// 5*48f8d9ceSMark Brown// Give ourselves GCS write permissions then use them 6*48f8d9ceSMark Brown 7*48f8d9ceSMark Brown#include <asm/unistd.h> 8*48f8d9ceSMark Brown 9*48f8d9ceSMark Brown/* Shadow Stack/Guarded Control Stack interface */ 10*48f8d9ceSMark Brown#define PR_GET_SHADOW_STACK_STATUS 74 11*48f8d9ceSMark Brown#define PR_SET_SHADOW_STACK_STATUS 75 12*48f8d9ceSMark Brown#define PR_LOCK_SHADOW_STACK_STATUS 76 13*48f8d9ceSMark Brown 14*48f8d9ceSMark Brown# define PR_SHADOW_STACK_ENABLE (1UL << 0) 15*48f8d9ceSMark Brown# define PR_SHADOW_STACK_WRITE (1UL << 1) 16*48f8d9ceSMark Brown# define PR_SHADOW_STACK_PUSH (1UL << 2) 17*48f8d9ceSMark Brown 18*48f8d9ceSMark Brown#define GCSPR_EL0 S3_3_C2_C5_1 19*48f8d9ceSMark Brown 20*48f8d9ceSMark Brown#define KSFT_SKIP 4 21*48f8d9ceSMark Brown 22*48f8d9ceSMark Brown.macro function name 23*48f8d9ceSMark Brown .macro endfunction 24*48f8d9ceSMark Brown .type \name, @function 25*48f8d9ceSMark Brown .purgem endfunction 26*48f8d9ceSMark Brown .endm 27*48f8d9ceSMark Brown\name: 28*48f8d9ceSMark Brown.endm 29*48f8d9ceSMark Brown 30*48f8d9ceSMark Brown// Print a single character x0 to stdout 31*48f8d9ceSMark Brown// Clobbers x0-x2,x8 32*48f8d9ceSMark Brownfunction putc 33*48f8d9ceSMark Brown str x0, [sp, #-16]! 34*48f8d9ceSMark Brown 35*48f8d9ceSMark Brown mov x0, #1 // STDOUT_FILENO 36*48f8d9ceSMark Brown mov x1, sp 37*48f8d9ceSMark Brown mov x2, #1 38*48f8d9ceSMark Brown mov x8, #__NR_write 39*48f8d9ceSMark Brown svc #0 40*48f8d9ceSMark Brown 41*48f8d9ceSMark Brown add sp, sp, #16 42*48f8d9ceSMark Brown ret 43*48f8d9ceSMark Brownendfunction 44*48f8d9ceSMark Brown.globl putc 45*48f8d9ceSMark Brown 46*48f8d9ceSMark Brown// Print a NUL-terminated string starting at address x0 to stdout 47*48f8d9ceSMark Brown// Clobbers x0-x3,x8 48*48f8d9ceSMark Brownfunction puts 49*48f8d9ceSMark Brown mov x1, x0 50*48f8d9ceSMark Brown 51*48f8d9ceSMark Brown mov x2, #0 52*48f8d9ceSMark Brown0: ldrb w3, [x0], #1 53*48f8d9ceSMark Brown cbz w3, 1f 54*48f8d9ceSMark Brown add x2, x2, #1 55*48f8d9ceSMark Brown b 0b 56*48f8d9ceSMark Brown 57*48f8d9ceSMark Brown1: mov w0, #1 // STDOUT_FILENO 58*48f8d9ceSMark Brown mov x8, #__NR_write 59*48f8d9ceSMark Brown svc #0 60*48f8d9ceSMark Brown 61*48f8d9ceSMark Brown ret 62*48f8d9ceSMark Brownendfunction 63*48f8d9ceSMark Brown.globl puts 64*48f8d9ceSMark Brown 65*48f8d9ceSMark Brown// Utility macro to print a literal string 66*48f8d9ceSMark Brown// Clobbers x0-x4,x8 67*48f8d9ceSMark Brown.macro puts string 68*48f8d9ceSMark Brown .pushsection .rodata.str1.1, "aMS", @progbits, 1 69*48f8d9ceSMark Brown.L__puts_literal\@: .string "\string" 70*48f8d9ceSMark Brown .popsection 71*48f8d9ceSMark Brown 72*48f8d9ceSMark Brown ldr x0, =.L__puts_literal\@ 73*48f8d9ceSMark Brown bl puts 74*48f8d9ceSMark Brown.endm 75*48f8d9ceSMark Brown 76*48f8d9ceSMark Brown.globl _start 77*48f8d9ceSMark Brownfunction _start 78*48f8d9ceSMark Brown // Run with GCS 79*48f8d9ceSMark Brown mov x0, PR_SET_SHADOW_STACK_STATUS 80*48f8d9ceSMark Brown mov x1, PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE 81*48f8d9ceSMark Brown mov x2, xzr 82*48f8d9ceSMark Brown mov x3, xzr 83*48f8d9ceSMark Brown mov x4, xzr 84*48f8d9ceSMark Brown mov x5, xzr 85*48f8d9ceSMark Brown mov x8, #__NR_prctl 86*48f8d9ceSMark Brown svc #0 87*48f8d9ceSMark Brown cbz x0, 1f 88*48f8d9ceSMark Brown puts "Failed to enable GCS with write permission\n" 89*48f8d9ceSMark Brown mov x0, #KSFT_SKIP 90*48f8d9ceSMark Brown b 2f 91*48f8d9ceSMark Brown1: 92*48f8d9ceSMark Brown mrs x0, GCSPR_EL0 93*48f8d9ceSMark Brown sub x0, x0, #8 94*48f8d9ceSMark Brown .inst 0xd91f1c01 // GCSSTR x1, x0 95*48f8d9ceSMark Brown 96*48f8d9ceSMark Brown mov x0, #0 97*48f8d9ceSMark Brown2: 98*48f8d9ceSMark Brown mov x8, #__NR_exit 99*48f8d9ceSMark Brown svc #0 100