mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
kselftest/arm64: Validate that GCS push and write permissions work
Add trivial assembly programs which give themselves the appropriate permissions and then execute GCSPUSHM and GCSSTR, they will report errors by generating signals on the non-permitted instructions. Not using libc minimises the interaction with any policy set for the system but we skip on failure to get the permissions in case the system is locked down to make them inaccessible. Signed-off-by: Mark Brown <broonie@kernel.org> Link: https://lore.kernel.org/r/20241005-arm64-gcs-test-flags-v1-1-03cb9786c5cd@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
bb9ae1a66c
commit
48f8d9cef7
2
tools/testing/selftests/arm64/gcs/.gitignore
vendored
2
tools/testing/selftests/arm64/gcs/.gitignore
vendored
@ -3,3 +3,5 @@ libc-gcs
|
||||
gcs-locking
|
||||
gcs-stress
|
||||
gcs-stress-thread
|
||||
gcspushm
|
||||
gcsstr
|
||||
|
@ -6,7 +6,7 @@
|
||||
# nolibc.
|
||||
#
|
||||
|
||||
TEST_GEN_PROGS := basic-gcs libc-gcs gcs-locking gcs-stress
|
||||
TEST_GEN_PROGS := basic-gcs libc-gcs gcs-locking gcs-stress gcspushm gcsstr
|
||||
TEST_GEN_PROGS_EXTENDED := gcs-stress-thread
|
||||
|
||||
LDLIBS+=-lpthread
|
||||
@ -22,3 +22,9 @@ $(OUTPUT)/basic-gcs: basic-gcs.c
|
||||
|
||||
$(OUTPUT)/gcs-stress-thread: gcs-stress-thread.S
|
||||
$(CC) -nostdlib $^ -o $@
|
||||
|
||||
$(OUTPUT)/gcspushm: gcspushm.S
|
||||
$(CC) -nostdlib $^ -o $@
|
||||
|
||||
$(OUTPUT)/gcsstr: gcsstr.S
|
||||
$(CC) -nostdlib $^ -o $@
|
||||
|
96
tools/testing/selftests/arm64/gcs/gcspushm.S
Normal file
96
tools/testing/selftests/arm64/gcs/gcspushm.S
Normal file
@ -0,0 +1,96 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Copyright 2024 Arm Limited
|
||||
//
|
||||
// Give ourselves GCS push permissions then use them
|
||||
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/* Shadow Stack/Guarded Control Stack interface */
|
||||
#define PR_GET_SHADOW_STACK_STATUS 74
|
||||
#define PR_SET_SHADOW_STACK_STATUS 75
|
||||
#define PR_LOCK_SHADOW_STACK_STATUS 76
|
||||
|
||||
# define PR_SHADOW_STACK_ENABLE (1UL << 0)
|
||||
# define PR_SHADOW_STACK_WRITE (1UL << 1)
|
||||
# define PR_SHADOW_STACK_PUSH (1UL << 2)
|
||||
|
||||
#define KSFT_SKIP 4
|
||||
|
||||
.macro function name
|
||||
.macro endfunction
|
||||
.type \name, @function
|
||||
.purgem endfunction
|
||||
.endm
|
||||
\name:
|
||||
.endm
|
||||
|
||||
// Print a single character x0 to stdout
|
||||
// Clobbers x0-x2,x8
|
||||
function putc
|
||||
str x0, [sp, #-16]!
|
||||
|
||||
mov x0, #1 // STDOUT_FILENO
|
||||
mov x1, sp
|
||||
mov x2, #1
|
||||
mov x8, #__NR_write
|
||||
svc #0
|
||||
|
||||
add sp, sp, #16
|
||||
ret
|
||||
endfunction
|
||||
.globl putc
|
||||
|
||||
// Print a NUL-terminated string starting at address x0 to stdout
|
||||
// Clobbers x0-x3,x8
|
||||
function puts
|
||||
mov x1, x0
|
||||
|
||||
mov x2, #0
|
||||
0: ldrb w3, [x0], #1
|
||||
cbz w3, 1f
|
||||
add x2, x2, #1
|
||||
b 0b
|
||||
|
||||
1: mov w0, #1 // STDOUT_FILENO
|
||||
mov x8, #__NR_write
|
||||
svc #0
|
||||
|
||||
ret
|
||||
endfunction
|
||||
.globl puts
|
||||
|
||||
// Utility macro to print a literal string
|
||||
// Clobbers x0-x4,x8
|
||||
.macro puts string
|
||||
.pushsection .rodata.str1.1, "aMS", @progbits, 1
|
||||
.L__puts_literal\@: .string "\string"
|
||||
.popsection
|
||||
|
||||
ldr x0, =.L__puts_literal\@
|
||||
bl puts
|
||||
.endm
|
||||
|
||||
.globl _start
|
||||
function _start
|
||||
// Run with GCS
|
||||
mov x0, PR_SET_SHADOW_STACK_STATUS
|
||||
mov x1, PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_PUSH
|
||||
mov x2, xzr
|
||||
mov x3, xzr
|
||||
mov x4, xzr
|
||||
mov x5, xzr
|
||||
mov x8, #__NR_prctl
|
||||
svc #0
|
||||
cbz x0, 1f
|
||||
puts "Failed to enable GCS with push permission\n"
|
||||
mov x0, #KSFT_SKIP
|
||||
b 2f
|
||||
1:
|
||||
sys #3, c7, c7, #0, x0 // GCSPUSHM
|
||||
sysl x0, #3, c7, c7, #1 // GCSPOPM
|
||||
|
||||
mov x0, #0
|
||||
2:
|
||||
mov x8, #__NR_exit
|
||||
svc #0
|
99
tools/testing/selftests/arm64/gcs/gcsstr.S
Normal file
99
tools/testing/selftests/arm64/gcs/gcsstr.S
Normal file
@ -0,0 +1,99 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
//
|
||||
// Copyright 2024 Arm Limited
|
||||
//
|
||||
// Give ourselves GCS write permissions then use them
|
||||
|
||||
#include <asm/unistd.h>
|
||||
|
||||
/* Shadow Stack/Guarded Control Stack interface */
|
||||
#define PR_GET_SHADOW_STACK_STATUS 74
|
||||
#define PR_SET_SHADOW_STACK_STATUS 75
|
||||
#define PR_LOCK_SHADOW_STACK_STATUS 76
|
||||
|
||||
# define PR_SHADOW_STACK_ENABLE (1UL << 0)
|
||||
# define PR_SHADOW_STACK_WRITE (1UL << 1)
|
||||
# define PR_SHADOW_STACK_PUSH (1UL << 2)
|
||||
|
||||
#define GCSPR_EL0 S3_3_C2_C5_1
|
||||
|
||||
#define KSFT_SKIP 4
|
||||
|
||||
.macro function name
|
||||
.macro endfunction
|
||||
.type \name, @function
|
||||
.purgem endfunction
|
||||
.endm
|
||||
\name:
|
||||
.endm
|
||||
|
||||
// Print a single character x0 to stdout
|
||||
// Clobbers x0-x2,x8
|
||||
function putc
|
||||
str x0, [sp, #-16]!
|
||||
|
||||
mov x0, #1 // STDOUT_FILENO
|
||||
mov x1, sp
|
||||
mov x2, #1
|
||||
mov x8, #__NR_write
|
||||
svc #0
|
||||
|
||||
add sp, sp, #16
|
||||
ret
|
||||
endfunction
|
||||
.globl putc
|
||||
|
||||
// Print a NUL-terminated string starting at address x0 to stdout
|
||||
// Clobbers x0-x3,x8
|
||||
function puts
|
||||
mov x1, x0
|
||||
|
||||
mov x2, #0
|
||||
0: ldrb w3, [x0], #1
|
||||
cbz w3, 1f
|
||||
add x2, x2, #1
|
||||
b 0b
|
||||
|
||||
1: mov w0, #1 // STDOUT_FILENO
|
||||
mov x8, #__NR_write
|
||||
svc #0
|
||||
|
||||
ret
|
||||
endfunction
|
||||
.globl puts
|
||||
|
||||
// Utility macro to print a literal string
|
||||
// Clobbers x0-x4,x8
|
||||
.macro puts string
|
||||
.pushsection .rodata.str1.1, "aMS", @progbits, 1
|
||||
.L__puts_literal\@: .string "\string"
|
||||
.popsection
|
||||
|
||||
ldr x0, =.L__puts_literal\@
|
||||
bl puts
|
||||
.endm
|
||||
|
||||
.globl _start
|
||||
function _start
|
||||
// Run with GCS
|
||||
mov x0, PR_SET_SHADOW_STACK_STATUS
|
||||
mov x1, PR_SHADOW_STACK_ENABLE | PR_SHADOW_STACK_WRITE
|
||||
mov x2, xzr
|
||||
mov x3, xzr
|
||||
mov x4, xzr
|
||||
mov x5, xzr
|
||||
mov x8, #__NR_prctl
|
||||
svc #0
|
||||
cbz x0, 1f
|
||||
puts "Failed to enable GCS with write permission\n"
|
||||
mov x0, #KSFT_SKIP
|
||||
b 2f
|
||||
1:
|
||||
mrs x0, GCSPR_EL0
|
||||
sub x0, x0, #8
|
||||
.inst 0xd91f1c01 // GCSSTR x1, x0
|
||||
|
||||
mov x0, #0
|
||||
2:
|
||||
mov x8, #__NR_exit
|
||||
svc #0
|
Loading…
Reference in New Issue
Block a user