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 push 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 KSFT_SKIP 4 19*48f8d9ceSMark Brown 20*48f8d9ceSMark Brown.macro function name 21*48f8d9ceSMark Brown .macro endfunction 22*48f8d9ceSMark Brown .type \name, @function 23*48f8d9ceSMark Brown .purgem endfunction 24*48f8d9ceSMark Brown .endm 25*48f8d9ceSMark Brown\name: 26*48f8d9ceSMark Brown.endm 27*48f8d9ceSMark Brown 28*48f8d9ceSMark Brown// Print a single character x0 to stdout 29*48f8d9ceSMark Brown// Clobbers x0-x2,x8 30*48f8d9ceSMark Brownfunction putc 31*48f8d9ceSMark Brown str x0, [sp, #-16]! 32*48f8d9ceSMark Brown 33*48f8d9ceSMark Brown mov x0, #1 // STDOUT_FILENO 34*48f8d9ceSMark Brown mov x1, sp 35*48f8d9ceSMark Brown mov x2, #1 36*48f8d9ceSMark Brown mov x8, #__NR_write 37*48f8d9ceSMark Brown svc #0 38*48f8d9ceSMark Brown 39*48f8d9ceSMark Brown add sp, sp, #16 40*48f8d9ceSMark Brown ret 41*48f8d9ceSMark Brownendfunction 42*48f8d9ceSMark Brown.globl putc 43*48f8d9ceSMark Brown 44*48f8d9ceSMark Brown// Print a NUL-terminated string starting at address x0 to stdout 45*48f8d9ceSMark Brown// Clobbers x0-x3,x8 46*48f8d9ceSMark Brownfunction puts 47*48f8d9ceSMark Brown mov x1, x0 48*48f8d9ceSMark Brown 49*48f8d9ceSMark Brown mov x2, #0 50*48f8d9ceSMark Brown0: ldrb w3, [x0], #1 51*48f8d9ceSMark Brown cbz w3, 1f 52*48f8d9ceSMark Brown add x2, x2, #1 53*48f8d9ceSMark Brown b 0b 54*48f8d9ceSMark Brown 55*48f8d9ceSMark Brown1: mov w0, #1 // STDOUT_FILENO 56*48f8d9ceSMark Brown mov x8, #__NR_write 57*48f8d9ceSMark Brown svc #0 58*48f8d9ceSMark Brown 59*48f8d9ceSMark Brown ret 60*48f8d9ceSMark Brownendfunction 61*48f8d9ceSMark Brown.globl puts 62*48f8d9ceSMark Brown 63*48f8d9ceSMark Brown// Utility macro to print a literal string 64*48f8d9ceSMark Brown// Clobbers x0-x4,x8 65*48f8d9ceSMark Brown.macro puts string 66*48f8d9ceSMark Brown .pushsection .rodata.str1.1, "aMS", @progbits, 1 67*48f8d9ceSMark Brown.L__puts_literal\@: .string "\string" 68*48f8d9ceSMark Brown .popsection 69*48f8d9ceSMark Brown 70*48f8d9ceSMark Brown ldr x0, =.L__puts_literal\@ 71*48f8d9ceSMark Brown bl puts 72*48f8d9ceSMark Brown.endm 73*48f8d9ceSMark Brown 74*48f8d9ceSMark Brown.globl _start 75*48f8d9ceSMark Brownfunction _start 76*48f8d9ceSMark Brown // Run with GCS 77*48f8d9ceSMark Brown mov x0, PR_SET_SHADOW_STACK_STATUS 78*48f8d9ceSMark Brown mov x1, PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_PUSH 79*48f8d9ceSMark Brown mov x2, xzr 80*48f8d9ceSMark Brown mov x3, xzr 81*48f8d9ceSMark Brown mov x4, xzr 82*48f8d9ceSMark Brown mov x5, xzr 83*48f8d9ceSMark Brown mov x8, #__NR_prctl 84*48f8d9ceSMark Brown svc #0 85*48f8d9ceSMark Brown cbz x0, 1f 86*48f8d9ceSMark Brown puts "Failed to enable GCS with push permission\n" 87*48f8d9ceSMark Brown mov x0, #KSFT_SKIP 88*48f8d9ceSMark Brown b 2f 89*48f8d9ceSMark Brown1: 90*48f8d9ceSMark Brown sys #3, c7, c7, #0, x0 // GCSPUSHM 91*48f8d9ceSMark Brown sysl x0, #3, c7, c7, #1 // GCSPOPM 92*48f8d9ceSMark Brown 93*48f8d9ceSMark Brown mov x0, #0 94*48f8d9ceSMark Brown2: 95*48f8d9ceSMark Brown mov x8, #__NR_exit 96*48f8d9ceSMark Brown svc #0 97