From d2733037ad227fe894ff167a881a384d1d0387dc Mon Sep 17 00:00:00 2001 From: James McGregor Date: Tue, 27 Aug 2024 15:12:29 +0100 Subject: [PATCH] arm-gcs/linux-yocto: update to 6.11-rc3 and v12 of the GCS patches Update the GCS patches to v12. They've been rebased onto 6.11-rc3, so update to use that too. GCS support now depends on !UPROBES, so add a config fragment to disable it. Signed-off-by: James McGregor --- meta-arm-gcs/gcs.yml | 2 +- ...ers_6.10.bb => linux-libc-headers_6.11.bb} | 6 +- .../linux/files/disable_uprobe.cfg | 1 + .../recipes-kernel/linux/files/gcs.patch | 2856 +++++------------ .../linux/linux-yocto-dev.bbappend | 8 +- 5 files changed, 796 insertions(+), 2077 deletions(-) rename meta-arm-gcs/recipes-kernel/linux-libc-headers/{linux-libc-headers_6.10.bb => linux-libc-headers_6.11.bb} (79%) create mode 100644 meta-arm-gcs/recipes-kernel/linux/files/disable_uprobe.cfg diff --git a/meta-arm-gcs/gcs.yml b/meta-arm-gcs/gcs.yml index f8a196c0..eeeac1e2 100644 --- a/meta-arm-gcs/gcs.yml +++ b/meta-arm-gcs/gcs.yml @@ -28,7 +28,7 @@ local_conf_header: IMAGE_CLASSES += "fvpboot" # Use the -dev patched kernel PREFERRED_PROVIDER_virtual/kernel = "linux-yocto-dev" - LINUXLIBCVERSION = "6.10" + LINUXLIBCVERSION = "6.11" # No root password for ease EXTRA_IMAGE_FEATURES += "empty-root-password allow-empty-password allow-root-login" # Install a toolchain diff --git a/meta-arm-gcs/recipes-kernel/linux-libc-headers/linux-libc-headers_6.10.bb b/meta-arm-gcs/recipes-kernel/linux-libc-headers/linux-libc-headers_6.11.bb similarity index 79% rename from meta-arm-gcs/recipes-kernel/linux-libc-headers/linux-libc-headers_6.10.bb rename to meta-arm-gcs/recipes-kernel/linux-libc-headers/linux-libc-headers_6.11.bb index 7626a4c6..5776113f 100644 --- a/meta-arm-gcs/recipes-kernel/linux-libc-headers/linux-libc-headers_6.10.bb +++ b/meta-arm-gcs/recipes-kernel/linux-libc-headers/linux-libc-headers_6.11.bb @@ -2,9 +2,9 @@ require ${COREBASE}/meta/recipes-kernel/linux-libc-headers/linux-libc-headers.in FILESEXTRAPATHS:prepend = "${THISDIR}/../linux/files/:" -KBRANCH = "v6.10/standard/base" -# 6.10-rc3 -SRCREV = "83a7eefedc9b56fe7bfeff13b6c7356688ffa670" +KBRANCH = "v6.11/standard/base" +# 6.11-rc3 +SRCREV = "7c626ce4bae1ac14f60076d00eafe71af30450ba" SRC_URI = "git://git.yoctoproject.org/linux-yocto-dev.git;branch=${KBRANCH};protocol=https" SRC_URI += "file://gcs.patch" diff --git a/meta-arm-gcs/recipes-kernel/linux/files/disable_uprobe.cfg b/meta-arm-gcs/recipes-kernel/linux/files/disable_uprobe.cfg new file mode 100644 index 00000000..30598ec3 --- /dev/null +++ b/meta-arm-gcs/recipes-kernel/linux/files/disable_uprobe.cfg @@ -0,0 +1 @@ +CONFIG_UPROBE_EVENTS=n \ No newline at end of file diff --git a/meta-arm-gcs/recipes-kernel/linux/files/gcs.patch b/meta-arm-gcs/recipes-kernel/linux/files/gcs.patch index 2c9bd049..29b16d75 100644 --- a/meta-arm-gcs/recipes-kernel/linux/files/gcs.patch +++ b/meta-arm-gcs/recipes-kernel/linux/files/gcs.patch @@ -1,190 +1,7 @@ -From 802aaf860bb5f70c9b87385eab6178d3f15cd781 Mon Sep 17 00:00:00 2001 +From 7e87a4aa8c3462fb7bc5518c130566b4e6bcf375 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Thu, 18 Jan 2024 21:30:07 +0000 -Subject: [PATCH 02/50] Documentation: userspace-api: Add shadow stack API - documentation - -There are a number of architectures with shadow stack features which we are -presenting to userspace with as consistent an API as we can (though there -are some architecture specifics). Especially given that there are some -important considerations for userspace code interacting directly with the -feature let's provide some documentation covering the common aspects. - -Signed-off-by: Mark Brown - -Upstream-Status: Submitted [https://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git/log/?h=arm64-gcs] -Signed-off-by: Ross Burton - ---- - Documentation/userspace-api/index.rst | 1 + - Documentation/userspace-api/shadow_stack.rst | 41 ++++++++++++++++++++ - 2 files changed, 42 insertions(+) - create mode 100644 Documentation/userspace-api/shadow_stack.rst - -diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst -index 5926115ec0ed8..d60a6dc0cbcff 100644 ---- a/Documentation/userspace-api/index.rst -+++ b/Documentation/userspace-api/index.rst -@@ -59,6 +59,7 @@ Everything else - - ELF - netlink/index -+ shadow_stack - sysfs-platform_profile - vduse - futex2 -diff --git a/Documentation/userspace-api/shadow_stack.rst b/Documentation/userspace-api/shadow_stack.rst -new file mode 100644 -index 0000000000000..c576ad3d7ec12 ---- /dev/null -+++ b/Documentation/userspace-api/shadow_stack.rst -@@ -0,0 +1,41 @@ -+============= -+Shadow Stacks -+============= -+ -+Introduction -+============ -+ -+Several architectures have features which provide backward edge -+control flow protection through a hardware maintained stack, only -+writeable by userspace through very limited operations. This feature -+is referred to as shadow stacks on Linux, on x86 it is part of Intel -+Control Enforcement Technology (CET), on arm64 it is Guarded Control -+Stacks feature (FEAT_GCS) and for RISC-V it is the Zicfiss extension. -+It is expected that this feature will normally be managed by the -+system dynamic linker and libc in ways broadly transparent to -+application code, this document covers interfaces and considerations. -+ -+ -+Enabling -+======== -+ -+Shadow stacks default to disabled when a userspace process is -+executed, they can be enabled for the current thread with a syscall: -+ -+ - For x86 the ARCH_SHSTK_ENABLE arch_prctl() -+ -+It is expected that this will normally be done by the dynamic linker. -+Any new threads created by a thread with shadow stacks enabled will -+themselves have shadow stacks enabled. -+ -+ -+Enablement considerations -+========================= -+ -+- Returning from the function that enables shadow stacks without first -+ disabling them will cause a shadow stack exception. This includes -+ any syscall wrapper or other library functions, the syscall will need -+ to be inlined. -+- A lock feature allows userspace to prevent disabling of shadow stacks. -+- Those that change the stack context like longjmp() or use of ucontext -+ changes on signal return will need support from libc. --- -2.34.1 - - -From 5c5bd1324b075333416fd10251f61e7970051cd6 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Mon, 29 Jan 2024 22:29:38 +0000 -Subject: [PATCH 03/50] selftests: Provide helper header for shadow stack - testing - -While almost all users of shadow stacks should be relying on the dynamic -linker and libc to enable the feature there are several low level test -programs where it is useful to enable without any libc support, allowing -testing without full system enablement. This low level testing is helpful -during bringup of the support itself, and also in enabling coverage by -automated testing without needing all system components in the target root -filesystems to have enablement. - -Provide a header with helpers for this purpose, intended for use only by -test programs directly exercising shadow stack interfaces. - -Reviewed-by: Rick Edgecombe -Signed-off-by: Mark Brown ---- - tools/testing/selftests/ksft_shstk.h | 63 ++++++++++++++++++++++++++++ - 1 file changed, 63 insertions(+) - create mode 100644 tools/testing/selftests/ksft_shstk.h - -diff --git a/tools/testing/selftests/ksft_shstk.h b/tools/testing/selftests/ksft_shstk.h -new file mode 100644 -index 0000000000000..85d0747c18022 ---- /dev/null -+++ b/tools/testing/selftests/ksft_shstk.h -@@ -0,0 +1,63 @@ -+/* SPDX-License-Identifier: GPL-2.0-only */ -+/* -+ * Helpers for shadow stack enablement, this is intended to only be -+ * used by low level test programs directly exercising interfaces for -+ * working with shadow stacks. -+ * -+ * Copyright (C) 2024 ARM Ltd. -+ */ -+ -+#ifndef __KSFT_SHSTK_H -+#define __KSFT_SHSTK_H -+ -+#include -+ -+/* This is currently only defined for x86 */ -+#ifndef SHADOW_STACK_SET_TOKEN -+#define SHADOW_STACK_SET_TOKEN (1ULL << 0) -+#endif -+ -+static bool shadow_stack_enabled; -+ -+#ifdef __x86_64__ -+#define ARCH_SHSTK_ENABLE 0x5001 -+#define ARCH_SHSTK_SHSTK (1ULL << 0) -+ -+#define ARCH_PRCTL(arg1, arg2) \ -+({ \ -+ long _ret; \ -+ register long _num asm("eax") = __NR_arch_prctl; \ -+ register long _arg1 asm("rdi") = (long)(arg1); \ -+ register long _arg2 asm("rsi") = (long)(arg2); \ -+ \ -+ asm volatile ( \ -+ "syscall\n" \ -+ : "=a"(_ret) \ -+ : "r"(_arg1), "r"(_arg2), \ -+ "0"(_num) \ -+ : "rcx", "r11", "memory", "cc" \ -+ ); \ -+ _ret; \ -+}) -+ -+#define ENABLE_SHADOW_STACK -+static inline __attribute__((always_inline)) void enable_shadow_stack(void) -+{ -+ int ret = ARCH_PRCTL(ARCH_SHSTK_ENABLE, ARCH_SHSTK_SHSTK); -+ if (ret == 0) -+ shadow_stack_enabled = true; -+} -+ -+#endif -+ -+#ifndef __NR_map_shadow_stack -+#define __NR_map_shadow_stack 453 -+#endif -+ -+#ifndef ENABLE_SHADOW_STACK -+static inline void enable_shadow_stack(void) { } -+#endif -+ -+#endif -+ -+ --- -2.34.1 - - -From a7f27146a718276ca001393ef91db3f9c583619a Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Thu, 19 Oct 2023 17:43:34 +0100 -Subject: [PATCH 04/50] mm: Introduce ARCH_HAS_USER_SHADOW_STACK +Date: Thu, 29 Aug 2024 00:27:17 +0100 +Subject: [PATCH 01/39] mm: Introduce ARCH_HAS_USER_SHADOW_STACK Since multiple architectures have support for shadow stacks and we need to select support for this feature in several places in the generic code @@ -194,7 +11,16 @@ Suggested-by: David Hildenbrand Acked-by: David Hildenbrand Reviewed-by: Deepak Gupta Reviewed-by: Rick Edgecombe +Reviewed-by: Mike Rapoport (IBM) +Reviewed-by: Catalin Marinas +Reviewed-by: Kees Cook +Tested-by: Kees Cook +Acked-by: Shuah Khan +Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown + +Upstream-Status: Submitted [https://git.kernel.org/pub/scm/linux/kernel/git/broonie/misc.git/log/?h=arm64-gcs] +Signed-off-by: James McGregor --- arch/x86/Kconfig | 1 + fs/proc/task_mmu.c | 2 +- @@ -203,10 +29,10 @@ Signed-off-by: Mark Brown 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig -index 1d7122a1883e8..4a5e40d4c14e1 100644 +index 007bab9f2a0e..320e1f411163 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig -@@ -1949,6 +1949,7 @@ config X86_USER_SHADOW_STACK +@@ -1957,6 +1957,7 @@ config X86_USER_SHADOW_STACK depends on AS_WRUSS depends on X86_64 select ARCH_USES_HIGH_VMA_FLAGS @@ -215,10 +41,10 @@ index 1d7122a1883e8..4a5e40d4c14e1 100644 help Shadow stack protection is a hardware feature that detects function diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index f8d35f993fe50..1b56c10775072 100644 +index 5f171ad7b436..0ea49725f524 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c -@@ -704,7 +704,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) +@@ -984,7 +984,7 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) #ifdef CONFIG_HAVE_ARCH_USERFAULTFD_MINOR [ilog2(VM_UFFD_MINOR)] = "ui", #endif /* CONFIG_HAVE_ARCH_USERFAULTFD_MINOR */ @@ -226,9 +52,9 @@ index f8d35f993fe50..1b56c10775072 100644 +#ifdef CONFIG_ARCH_HAS_USER_SHADOW_STACK [ilog2(VM_SHADOW_STACK)] = "ss", #endif - }; + #ifdef CONFIG_64BIT diff --git a/include/linux/mm.h b/include/linux/mm.h -index 9849dfda44d43..5ec7bc3556578 100644 +index c4b238a20b76..3357625c1db3 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -342,7 +342,7 @@ extern unsigned int kobjsize(const void *objp); @@ -241,10 +67,10 @@ index 9849dfda44d43..5ec7bc3556578 100644 * VM_SHADOW_STACK should not be set with VM_SHARED because of lack of * support core mm. diff --git a/mm/Kconfig b/mm/Kconfig -index b4cb45255a541..45416916dec1e 100644 +index b72e7d040f78..3167be663bca 100644 --- a/mm/Kconfig +++ b/mm/Kconfig -@@ -1249,6 +1249,12 @@ config IOMMU_MM_DATA +@@ -1263,6 +1263,12 @@ config IOMMU_MM_DATA config EXECMEM bool @@ -252,1021 +78,19 @@ index b4cb45255a541..45416916dec1e 100644 + bool + help + The architecture has hardware support for userspace shadow call -+ stacks (eg, x87 CET, arm64 GCS or RISC-V Zicfiss). ++ stacks (eg, x86 CET, arm64 GCS or RISC-V Zicfiss). + source "mm/damon/Kconfig" endmenu -- -2.34.1 +2.25.1 -From e5ddf197fb74f41da968a4d2198c11b4b70c2e44 Mon Sep 17 00:00:00 2001 +From c44c0542e38efc48d63ea7c3bb9f180cdd4d0ec9 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Mon, 16 Oct 2023 19:40:40 +0100 -Subject: [PATCH 05/50] fork: Add shadow stack support to clone3() - -Unlike with the normal stack there is no API for configuring the the shadow -stack for a new thread, instead the kernel will dynamically allocate a new -shadow stack with the same size as the normal stack. This appears to be due -to the shadow stack series having been in development since before the more -extensible clone3() was added rather than anything more deliberate. - -Add parameters to clone3() specifying the location and size of a shadow -stack for the newly created process. If no shadow stack is specified -then the existing implicit allocation behaviour is maintained. - -If a stack is specified then it is required to have an architecture -defined token placed on the stack, this will be consumed by the new -task. If the token is not provided then this will be reported as a -segmentation fault with si_code SEGV_CPERR, as a runtime shadow stack -protection error would be. This allows architectures to implement the -validation of the token in the child process context. - -If the architecture does not support shadow stacks the shadow stack -parameters must be zero, architectures that do support the feature are -expected to enforce the same requirement on individual systems that lack -shadow stack support. - -Update the existing x86 implementation to pay attention to the newly added -arguments, in order to maintain compatibility we use the existing behaviour -if no shadow stack is specified. Minimal validation is done of the supplied -parameters, detailed enforcement is left to when the thread is executed. -Since we are now using more fields from the kernel_clone_args we pass that -into the shadow stack code rather than individual fields. - -At present this implementation does not consume the shadow stack token -atomically as would be desirable, it uses a separate read and write. - -Signed-off-by: Mark Brown ---- - arch/x86/include/asm/shstk.h | 11 ++-- - arch/x86/kernel/process.c | 2 +- - arch/x86/kernel/shstk.c | 104 +++++++++++++++++++++++++++-------- - include/linux/sched/task.h | 13 +++++ - include/uapi/linux/sched.h | 13 ++++- - kernel/fork.c | 76 +++++++++++++++++++++---- - 6 files changed, 176 insertions(+), 43 deletions(-) - -diff --git a/arch/x86/include/asm/shstk.h b/arch/x86/include/asm/shstk.h -index 42fee8959df7b..8be7b0a909c37 100644 ---- a/arch/x86/include/asm/shstk.h -+++ b/arch/x86/include/asm/shstk.h -@@ -6,6 +6,7 @@ - #include - - struct task_struct; -+struct kernel_clone_args; - struct ksignal; - - #ifdef CONFIG_X86_USER_SHADOW_STACK -@@ -16,8 +17,8 @@ struct thread_shstk { - - long shstk_prctl(struct task_struct *task, int option, unsigned long arg2); - void reset_thread_features(void); --unsigned long shstk_alloc_thread_stack(struct task_struct *p, unsigned long clone_flags, -- unsigned long stack_size); -+unsigned long shstk_alloc_thread_stack(struct task_struct *p, -+ const struct kernel_clone_args *args); - void shstk_free(struct task_struct *p); - int setup_signal_shadow_stack(struct ksignal *ksig); - int restore_signal_shadow_stack(void); -@@ -26,8 +27,10 @@ static inline long shstk_prctl(struct task_struct *task, int option, - unsigned long arg2) { return -EINVAL; } - static inline void reset_thread_features(void) {} - static inline unsigned long shstk_alloc_thread_stack(struct task_struct *p, -- unsigned long clone_flags, -- unsigned long stack_size) { return 0; } -+ const struct kernel_clone_args *args) -+{ -+ return 0; -+} - static inline void shstk_free(struct task_struct *p) {} - static inline int setup_signal_shadow_stack(struct ksignal *ksig) { return 0; } - static inline int restore_signal_shadow_stack(void) { return 0; } -diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c -index b8441147eb5e8..f206e997f91d2 100644 ---- a/arch/x86/kernel/process.c -+++ b/arch/x86/kernel/process.c -@@ -207,7 +207,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) - * is disabled, new_ssp will remain 0, and fpu_clone() will know not to - * update it. - */ -- new_ssp = shstk_alloc_thread_stack(p, clone_flags, args->stack_size); -+ new_ssp = shstk_alloc_thread_stack(p, args); - if (IS_ERR_VALUE(new_ssp)) - return PTR_ERR((void *)new_ssp); - -diff --git a/arch/x86/kernel/shstk.c b/arch/x86/kernel/shstk.c -index 6f1e9883f0742..953cc08930972 100644 ---- a/arch/x86/kernel/shstk.c -+++ b/arch/x86/kernel/shstk.c -@@ -191,44 +191,102 @@ void reset_thread_features(void) - current->thread.features_locked = 0; - } - --unsigned long shstk_alloc_thread_stack(struct task_struct *tsk, unsigned long clone_flags, -- unsigned long stack_size) -+int arch_shstk_post_fork(struct task_struct *t, struct kernel_clone_args *args) -+{ -+ /* -+ * SSP is aligned, so reserved bits and mode bit are a zero, just mark -+ * the token 64-bit. -+ */ -+ struct mm_struct *mm; -+ unsigned long addr; -+ u64 expected; -+ u64 val; -+ int ret = -EINVAL;; -+ -+ addr = args->shadow_stack + args->shadow_stack_size - sizeof(u64); -+ expected = (addr - SS_FRAME_SIZE) | BIT(0); -+ -+ mm = get_task_mm(t); -+ if (!mm) -+ return -EFAULT; -+ -+ /* This should really be an atomic cpmxchg. It is not. */ -+ if (access_remote_vm(mm, addr, &val, sizeof(val), -+ FOLL_FORCE) != sizeof(val)) -+ goto out; -+ -+ if (val != expected) -+ goto out; -+ val = 0; -+ if (access_remote_vm(mm, addr, &val, sizeof(val), -+ FOLL_FORCE | FOLL_WRITE) != sizeof(val)) -+ goto out; -+ -+ ret = 0; -+ -+out: -+ mmput(mm); -+ return ret; -+} -+ -+unsigned long shstk_alloc_thread_stack(struct task_struct *tsk, -+ const struct kernel_clone_args *args) - { - struct thread_shstk *shstk = &tsk->thread.shstk; -+ unsigned long clone_flags = args->flags; - unsigned long addr, size; - - /* - * If shadow stack is not enabled on the new thread, skip any -- * switch to a new shadow stack. -+ * implicit switch to a new shadow stack and reject attempts to -+ * explciitly specify one. - */ -- if (!features_enabled(ARCH_SHSTK_SHSTK)) -- return 0; -+ if (!features_enabled(ARCH_SHSTK_SHSTK)) { -+ if (args->shadow_stack || args->shadow_stack_size) -+ return (unsigned long)ERR_PTR(-EINVAL); - -- /* -- * For CLONE_VFORK the child will share the parents shadow stack. -- * Make sure to clear the internal tracking of the thread shadow -- * stack so the freeing logic run for child knows to leave it alone. -- */ -- if (clone_flags & CLONE_VFORK) { -- shstk->base = 0; -- shstk->size = 0; - return 0; - } - - /* -- * For !CLONE_VM the child will use a copy of the parents shadow -- * stack. -+ * If the user specified a shadow stack then do some basic -+ * validation and use it, otherwise fall back to a default -+ * shadow stack size if the clone_flags don't indicate an -+ * allocation is unneeded. - */ -- if (!(clone_flags & CLONE_VM)) -- return 0; -+ if (args->shadow_stack) { -+ addr = args->shadow_stack; -+ size = args->shadow_stack_size; -+ } else { -+ /* -+ * For CLONE_VFORK the child will share the parents -+ * shadow stack. Make sure to clear the internal -+ * tracking of the thread shadow stack so the freeing -+ * logic run for child knows to leave it alone. -+ */ -+ if (clone_flags & CLONE_VFORK) { -+ shstk->base = 0; -+ shstk->size = 0; -+ return 0; -+ } - -- size = adjust_shstk_size(stack_size); -- addr = alloc_shstk(0, size, 0, false); -- if (IS_ERR_VALUE(addr)) -- return addr; -+ /* -+ * For !CLONE_VM the child will use a copy of the -+ * parents shadow stack. -+ */ -+ if (!(clone_flags & CLONE_VM)) -+ return 0; - -- shstk->base = addr; -- shstk->size = size; -+ size = args->stack_size; -+ size = adjust_shstk_size(size); -+ addr = alloc_shstk(0, size, 0, false); -+ if (IS_ERR_VALUE(addr)) -+ return addr; -+ -+ /* We allocated the shadow stack, we should deallocate it. */ -+ shstk->base = addr; -+ shstk->size = size; -+ } - - return addr + size; - } -diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h -index d362aacf9f897..56b2013d7fe5b 100644 ---- a/include/linux/sched/task.h -+++ b/include/linux/sched/task.h -@@ -43,6 +43,8 @@ struct kernel_clone_args { - void *fn_arg; - struct cgroup *cgrp; - struct css_set *cset; -+ unsigned long shadow_stack; -+ unsigned long shadow_stack_size; - }; - - /* -@@ -230,4 +232,15 @@ static inline void task_unlock(struct task_struct *p) - - DEFINE_GUARD(task_lock, struct task_struct *, task_lock(_T), task_unlock(_T)) - -+#ifdef CONFIG_ARCH_HAS_USER_SHADOW_STACK -+int arch_shstk_post_fork(struct task_struct *p, -+ struct kernel_clone_args *args); -+#else -+static inline int arch_shstk_post_fork(struct task_struct *p, -+ struct kernel_clone_args *args) -+{ -+ return 0; -+} -+#endif -+ - #endif /* _LINUX_SCHED_TASK_H */ -diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h -index 3bac0a8ceab26..8b7af52548fd9 100644 ---- a/include/uapi/linux/sched.h -+++ b/include/uapi/linux/sched.h -@@ -84,6 +84,10 @@ - * kernel's limit of nested PID namespaces. - * @cgroup: If CLONE_INTO_CGROUP is specified set this to - * a file descriptor for the cgroup. -+ * @shadow_stack: Pointer to the memory allocated for the child -+ * shadow stack. -+ * @shadow_stack_size: Specify the size of the shadow stack for -+ * the child process. - * - * The structure is versioned by size and thus extensible. - * New struct members must go at the end of the struct and -@@ -101,12 +105,15 @@ struct clone_args { - __aligned_u64 set_tid; - __aligned_u64 set_tid_size; - __aligned_u64 cgroup; -+ __aligned_u64 shadow_stack; -+ __aligned_u64 shadow_stack_size; - }; - #endif - --#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ --#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */ --#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ -+#define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */ -+#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */ -+#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ -+#define CLONE_ARGS_SIZE_VER3 104 /* sizeof fourth published struct */ - - /* - * Scheduling policies -diff --git a/kernel/fork.c b/kernel/fork.c -index 99076dbe27d83..d7c5769942f85 100644 ---- a/kernel/fork.c -+++ b/kernel/fork.c -@@ -125,6 +125,11 @@ - */ - #define MAX_THREADS FUTEX_TID_MASK - -+/* -+ * Require that shadow stacks can store at least one element -+ */ -+#define SHADOW_STACK_SIZE_MIN sizeof(void *) -+ - /* - * Protected counters by write_lock_irq(&tasklist_lock) - */ -@@ -2745,6 +2750,19 @@ struct task_struct *create_io_thread(int (*fn)(void *), void *arg, int node) - return copy_process(NULL, 0, node, &args); - } - -+static void shstk_post_fork(struct task_struct *p, -+ struct kernel_clone_args *args) -+{ -+ if (!IS_ENABLED(CONFIG_ARCH_HAS_USER_SHADOW_STACK)) -+ return; -+ -+ if (!args->shadow_stack) -+ return; -+ -+ if (arch_shstk_post_fork(p, args) != 0) -+ force_sig_fault_to_task(SIGSEGV, SEGV_CPERR, NULL, p); -+} -+ - /* - * Ok, this is the main fork-routine. - * -@@ -2806,6 +2824,8 @@ pid_t kernel_clone(struct kernel_clone_args *args) - */ - trace_sched_process_fork(current, p); - -+ shstk_post_fork(p, args); -+ - pid = get_task_pid(p, PIDTYPE_PID); - nr = pid_vnr(pid); - -@@ -2957,7 +2977,9 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, - CLONE_ARGS_SIZE_VER1); - BUILD_BUG_ON(offsetofend(struct clone_args, cgroup) != - CLONE_ARGS_SIZE_VER2); -- BUILD_BUG_ON(sizeof(struct clone_args) != CLONE_ARGS_SIZE_VER2); -+ BUILD_BUG_ON(offsetofend(struct clone_args, shadow_stack_size) != -+ CLONE_ARGS_SIZE_VER3); -+ BUILD_BUG_ON(sizeof(struct clone_args) != CLONE_ARGS_SIZE_VER3); - - if (unlikely(usize > PAGE_SIZE)) - return -E2BIG; -@@ -2990,16 +3012,18 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, - return -EINVAL; - - *kargs = (struct kernel_clone_args){ -- .flags = args.flags, -- .pidfd = u64_to_user_ptr(args.pidfd), -- .child_tid = u64_to_user_ptr(args.child_tid), -- .parent_tid = u64_to_user_ptr(args.parent_tid), -- .exit_signal = args.exit_signal, -- .stack = args.stack, -- .stack_size = args.stack_size, -- .tls = args.tls, -- .set_tid_size = args.set_tid_size, -- .cgroup = args.cgroup, -+ .flags = args.flags, -+ .pidfd = u64_to_user_ptr(args.pidfd), -+ .child_tid = u64_to_user_ptr(args.child_tid), -+ .parent_tid = u64_to_user_ptr(args.parent_tid), -+ .exit_signal = args.exit_signal, -+ .stack = args.stack, -+ .stack_size = args.stack_size, -+ .tls = args.tls, -+ .set_tid_size = args.set_tid_size, -+ .cgroup = args.cgroup, -+ .shadow_stack = args.shadow_stack, -+ .shadow_stack_size = args.shadow_stack_size, - }; - - if (args.set_tid && -@@ -3040,6 +3064,34 @@ static inline bool clone3_stack_valid(struct kernel_clone_args *kargs) - return true; - } - -+/** -+ * clone3_shadow_stack_valid - check and prepare shadow stack -+ * @kargs: kernel clone args -+ * -+ * Verify that shadow stacks are only enabled if supported. -+ */ -+static inline bool clone3_shadow_stack_valid(struct kernel_clone_args *kargs) -+{ -+ if (kargs->shadow_stack) { -+ if (!kargs->shadow_stack_size) -+ return false; -+ -+ if (kargs->shadow_stack_size < SHADOW_STACK_SIZE_MIN) -+ return false; -+ -+ if (kargs->shadow_stack_size > rlimit(RLIMIT_STACK)) -+ return false; -+ -+ /* -+ * The architecture must check support on the specific -+ * machine. -+ */ -+ return IS_ENABLED(CONFIG_ARCH_HAS_USER_SHADOW_STACK); -+ } else { -+ return !kargs->shadow_stack_size; -+ } -+} -+ - static bool clone3_args_valid(struct kernel_clone_args *kargs) - { - /* Verify that no unknown flags are passed along. */ -@@ -3062,7 +3114,7 @@ static bool clone3_args_valid(struct kernel_clone_args *kargs) - kargs->exit_signal) - return false; - -- if (!clone3_stack_valid(kargs)) -+ if (!clone3_stack_valid(kargs) || !clone3_shadow_stack_valid(kargs)) - return false; - - return true; --- -2.34.1 - - -From 061afbd50f75fc0792528ff54dd1a8cfc9d3396b Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 19 Jun 2024 18:18:12 +0100 -Subject: [PATCH 06/50] selftests/clone3: Remove redundant flushes of output - streams - -Since there were widespread issues with output not being flushed the -kselftest framework was modified to explicitly set the output streams -unbuffered in commit 58e2847ad2e6 ("selftests: line buffer test -program's stdout") so there is no need to explicitly flush in the clone3 -tests. - -Signed-off-by: Mark Brown ---- - tools/testing/selftests/clone3/clone3_selftests.h | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/tools/testing/selftests/clone3/clone3_selftests.h b/tools/testing/selftests/clone3/clone3_selftests.h -index 3d2663fe50ba5..39b5dcba663c3 100644 ---- a/tools/testing/selftests/clone3/clone3_selftests.h -+++ b/tools/testing/selftests/clone3/clone3_selftests.h -@@ -35,8 +35,6 @@ struct __clone_args { - - static pid_t sys_clone3(struct __clone_args *args, size_t size) - { -- fflush(stdout); -- fflush(stderr); - return syscall(__NR_clone3, args, size); - } - --- -2.34.1 - - -From d5c5c6845bfce26673d41141b7b7768858ea4277 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Thu, 19 Oct 2023 15:43:49 +0100 -Subject: [PATCH 07/50] selftests/clone3: Factor more of main loop into - test_clone3() - -In order to make it easier to add more configuration for the tests and -more support for runtime detection of when tests can be run pass the -structure describing the tests into test_clone3() rather than picking -the arguments out of it and have that function do all the per-test work. - -No functional change. - -Signed-off-by: Mark Brown ---- - tools/testing/selftests/clone3/clone3.c | 77 ++++++++++++------------- - 1 file changed, 37 insertions(+), 40 deletions(-) - -diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c -index e61f07973ce5e..e066b201fa64e 100644 ---- a/tools/testing/selftests/clone3/clone3.c -+++ b/tools/testing/selftests/clone3/clone3.c -@@ -30,6 +30,19 @@ enum test_mode { - CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG, - }; - -+typedef bool (*filter_function)(void); -+typedef size_t (*size_function)(void); -+ -+struct test { -+ const char *name; -+ uint64_t flags; -+ size_t size; -+ size_function size_function; -+ int expected; -+ enum test_mode test_mode; -+ filter_function filter; -+}; -+ - static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - { - struct __clone_args args = { -@@ -109,30 +122,40 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - return 0; - } - --static bool test_clone3(uint64_t flags, size_t size, int expected, -- enum test_mode test_mode) -+static void test_clone3(const struct test *test) - { -+ size_t size; - int ret; - -+ if (test->filter && test->filter()) { -+ ksft_test_result_skip("%s\n", test->name); -+ return; -+ } -+ -+ if (test->size_function) -+ size = test->size_function(); -+ else -+ size = test->size; -+ -+ ksft_print_msg("Running test '%s'\n", test->name); -+ - ksft_print_msg( - "[%d] Trying clone3() with flags %#" PRIx64 " (size %zu)\n", -- getpid(), flags, size); -- ret = call_clone3(flags, size, test_mode); -+ getpid(), test->flags, size); -+ ret = call_clone3(test->flags, size, test->test_mode); - ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n", -- getpid(), ret, expected); -- if (ret != expected) { -+ getpid(), ret, test->expected); -+ if (ret != test->expected) { - ksft_print_msg( - "[%d] Result (%d) is different than expected (%d)\n", -- getpid(), ret, expected); -- return false; -+ getpid(), ret, test->expected); -+ ksft_test_result_fail("%s\n", test->name); -+ return; - } - -- return true; -+ ksft_test_result_pass("%s\n", test->name); - } - --typedef bool (*filter_function)(void); --typedef size_t (*size_function)(void); -- - static bool not_root(void) - { - if (getuid() != 0) { -@@ -160,16 +183,6 @@ static size_t page_size_plus_8(void) - return getpagesize() + 8; - } - --struct test { -- const char *name; -- uint64_t flags; -- size_t size; -- size_function size_function; -- int expected; -- enum test_mode test_mode; -- filter_function filter; --}; -- - static const struct test tests[] = { - { - .name = "simple clone3()", -@@ -319,24 +332,8 @@ int main(int argc, char *argv[]) - ksft_set_plan(ARRAY_SIZE(tests)); - test_clone3_supported(); - -- for (i = 0; i < ARRAY_SIZE(tests); i++) { -- if (tests[i].filter && tests[i].filter()) { -- ksft_test_result_skip("%s\n", tests[i].name); -- continue; -- } -- -- if (tests[i].size_function) -- size = tests[i].size_function(); -- else -- size = tests[i].size; -- -- ksft_print_msg("Running test '%s'\n", tests[i].name); -- -- ksft_test_result(test_clone3(tests[i].flags, size, -- tests[i].expected, -- tests[i].test_mode), -- "%s\n", tests[i].name); -- } -+ for (i = 0; i < ARRAY_SIZE(tests); i++) -+ test_clone3(&tests[i]); - - ksft_finished(); - } --- -2.34.1 - - -From 553a2ad7825eee4d94bbc149bdf4b75ca8eef9bd Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Fri, 21 Jun 2024 01:27:35 +0100 -Subject: [PATCH 08/50] selftests/clone3: Explicitly handle child exits due to - signals - -In order to improve diagnostics and allow tests to explicitly look for -signals check to see if the child exited due to a signal and if it did -print the code and return it as a positive value, distinct from the -negative errnos currently returned. - -Signed-off-by: Mark Brown ---- - tools/testing/selftests/clone3/clone3.c | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c -index e066b201fa64e..3b3a08e6a34d7 100644 ---- a/tools/testing/selftests/clone3/clone3.c -+++ b/tools/testing/selftests/clone3/clone3.c -@@ -111,6 +111,13 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - ksft_print_msg("waitpid() returned %s\n", strerror(errno)); - return -errno; - } -+ -+ if (WIFSIGNALED(status)) { -+ ksft_print_msg("Child exited with signal %d\n", -+ WTERMSIG(status)); -+ return WTERMSIG(status); -+ } -+ - if (!WIFEXITED(status)) { - ksft_print_msg("Child did not exit normally, status 0x%x\n", - status); --- -2.34.1 - - -From 67595ba0fea2a0cbf31f9598015f7947dd4678e2 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Thu, 19 Oct 2023 16:15:08 +0100 -Subject: [PATCH 09/50] selftests/clone3: Allow tests to flag if -E2BIG is a - valid error code - -The clone_args structure is extensible, with the syscall passing in the -length of the structure. Inside the kernel we use copy_struct_from_user() -to read the struct but this has the unfortunate side effect of silently -accepting some overrun in the structure size providing the extra data is -all zeros. This means that we can't discover the clone3() features that -the running kernel supports by simply probing with various struct sizes. -We need to check this for the benefit of test systems which run newer -kselftests on old kernels. - -Add a flag which can be set on a test to indicate that clone3() may return --E2BIG due to the use of newer struct versions. Currently no tests need -this but it will become an issue for testing clone3() support for shadow -stacks, the support for shadow stacks is already present on x86. - -Signed-off-by: Mark Brown ---- - tools/testing/selftests/clone3/clone3.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c -index 3b3a08e6a34d7..26221661e9aec 100644 ---- a/tools/testing/selftests/clone3/clone3.c -+++ b/tools/testing/selftests/clone3/clone3.c -@@ -39,6 +39,7 @@ struct test { - size_t size; - size_function size_function; - int expected; -+ bool e2big_valid; - enum test_mode test_mode; - filter_function filter; - }; -@@ -153,6 +154,11 @@ static void test_clone3(const struct test *test) - ksft_print_msg("[%d] clone3() with flags says: %d expected %d\n", - getpid(), ret, test->expected); - if (ret != test->expected) { -+ if (test->e2big_valid && ret == -E2BIG) { -+ ksft_print_msg("Test reported -E2BIG\n"); -+ ksft_test_result_skip("%s\n", test->name); -+ return; -+ } - ksft_print_msg( - "[%d] Result (%d) is different than expected (%d)\n", - getpid(), ret, test->expected); --- -2.34.1 - - -From 4c8cf8814957090ce50ad18f318f72e6fe0d1a32 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 18 Oct 2023 23:09:49 +0100 -Subject: [PATCH 10/50] selftests/clone3: Test shadow stack support - -Add basic test coverage for specifying the shadow stack for a newly -created thread via clone3(), including coverage of the newly extended -argument structure. We check that a user specified shadow stack can be -provided, and that invalid combinations of parameters are rejected. - -In order to facilitate testing on systems without userspace shadow stack -support we manually enable shadow stacks on startup, this is architecture -specific due to the use of an arch_prctl() on x86. Due to interactions with -potential userspace locking of features we actually detect support for -shadow stacks on the running system by attempting to allocate a shadow -stack page during initialisation using map_shadow_stack(), warning if this -succeeds when the enable failed. - -In order to allow testing of user configured shadow stacks on -architectures with that feature we need to ensure that we do not return -from the function where the clone3() syscall is called in the child -process, doing so would trigger a shadow stack underflow. To do this we -use inline assembly rather than the standard syscall wrapper to call -clone3(). In order to avoid surprises we also use a syscall rather than -the libc exit() function., this should be overly cautious. - -Signed-off-by: Mark Brown ---- - tools/testing/selftests/clone3/clone3.c | 135 +++++++++++++++++- - .../selftests/clone3/clone3_selftests.h | 38 +++++ - 2 files changed, 172 insertions(+), 1 deletion(-) - -diff --git a/tools/testing/selftests/clone3/clone3.c b/tools/testing/selftests/clone3/clone3.c -index 26221661e9aec..696fbb6f94963 100644 ---- a/tools/testing/selftests/clone3/clone3.c -+++ b/tools/testing/selftests/clone3/clone3.c -@@ -3,6 +3,7 @@ - /* Based on Christian Brauner's clone3() example */ - - #define _GNU_SOURCE -+#include - #include - #include - #include -@@ -11,6 +12,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -19,8 +21,12 @@ - #include - - #include "../kselftest.h" -+#include "../ksft_shstk.h" - #include "clone3_selftests.h" - -+static bool shadow_stack_supported; -+static size_t max_supported_args_size; -+ - enum test_mode { - CLONE3_ARGS_NO_TEST, - CLONE3_ARGS_ALL_0, -@@ -28,6 +34,10 @@ enum test_mode { - CLONE3_ARGS_INVAL_EXIT_SIGNAL_NEG, - CLONE3_ARGS_INVAL_EXIT_SIGNAL_CSIG, - CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG, -+ CLONE3_ARGS_SHADOW_STACK, -+ CLONE3_ARGS_SHADOW_STACK_NO_SIZE, -+ CLONE3_ARGS_SHADOW_STACK_NO_POINTER, -+ CLONE3_ARGS_SHADOW_STACK_NO_TOKEN, - }; - - typedef bool (*filter_function)(void); -@@ -44,6 +54,44 @@ struct test { - filter_function filter; - }; - -+ -+/* -+ * We check for shadow stack support by attempting to use -+ * map_shadow_stack() since features may have been locked by the -+ * dynamic linker resulting in spurious errors when we attempt to -+ * enable on startup. We warn if the enable failed. -+ */ -+static void test_shadow_stack_supported(void) -+{ -+ long ret; -+ -+ ret = syscall(__NR_map_shadow_stack, 0, getpagesize(), 0); -+ if (ret == -1) { -+ ksft_print_msg("map_shadow_stack() not supported\n"); -+ } else if ((void *)ret == MAP_FAILED) { -+ ksft_print_msg("Failed to map shadow stack\n"); -+ } else { -+ ksft_print_msg("Shadow stack supportd\n"); -+ shadow_stack_supported = true; -+ -+ if (!shadow_stack_enabled) -+ ksft_print_msg("Mapped but did not enable shadow stack\n"); -+ } -+} -+ -+static unsigned long long get_shadow_stack_page(unsigned long flags) -+{ -+ unsigned long long page; -+ -+ page = syscall(__NR_map_shadow_stack, 0, getpagesize(), flags); -+ if ((void *)page == MAP_FAILED) { -+ ksft_print_msg("map_shadow_stack() failed: %d\n", errno); -+ return 0; -+ } -+ -+ return page; -+} -+ - static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - { - struct __clone_args args = { -@@ -89,6 +137,21 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - case CLONE3_ARGS_INVAL_EXIT_SIGNAL_NSIG: - args.exit_signal = 0x00000000000000f0ULL; - break; -+ case CLONE3_ARGS_SHADOW_STACK: -+ /* We need to specify a normal stack too to avoid corruption */ -+ args.shadow_stack = get_shadow_stack_page(SHADOW_STACK_SET_TOKEN); -+ args.shadow_stack_size = getpagesize(); -+ break; -+ case CLONE3_ARGS_SHADOW_STACK_NO_POINTER: -+ args.shadow_stack_size = getpagesize(); -+ break; -+ case CLONE3_ARGS_SHADOW_STACK_NO_SIZE: -+ args.shadow_stack = get_shadow_stack_page(SHADOW_STACK_SET_TOKEN); -+ break; -+ case CLONE3_ARGS_SHADOW_STACK_NO_TOKEN: -+ args.shadow_stack = get_shadow_stack_page(0); -+ args.shadow_stack_size = getpagesize(); -+ break; - } - - memcpy(&args_ext.args, &args, sizeof(struct __clone_args)); -@@ -102,7 +165,12 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - - if (pid == 0) { - ksft_print_msg("I am the child, my PID is %d\n", getpid()); -- _exit(EXIT_SUCCESS); -+ /* -+ * Use a raw syscall to ensure we don't get issues -+ * with manually specified shadow stack and exit handlers. -+ */ -+ syscall(__NR_exit, EXIT_SUCCESS); -+ ksft_print_msg("CHILD FAILED TO EXIT PID is %d\n", getpid()); - } - - ksft_print_msg("I am the parent (%d). My child's pid is %d\n", -@@ -112,6 +180,7 @@ static int call_clone3(uint64_t flags, size_t size, enum test_mode test_mode) - ksft_print_msg("waitpid() returned %s\n", strerror(errno)); - return -errno; - } -+ ksft_print_msg("WAITED\n"); - - if (WIFSIGNALED(status)) { - ksft_print_msg("Child exited with signal %d\n", -@@ -191,6 +260,26 @@ static bool no_timenamespace(void) - return true; - } - -+static bool have_shadow_stack(void) -+{ -+ if (shadow_stack_supported) { -+ ksft_print_msg("Shadow stack supported\n"); -+ return true; -+ } -+ -+ return false; -+} -+ -+static bool no_shadow_stack(void) -+{ -+ if (!shadow_stack_supported) { -+ ksft_print_msg("Shadow stack not supported\n"); -+ return true; -+ } -+ -+ return false; -+} -+ - static size_t page_size_plus_8(void) - { - return getpagesize() + 8; -@@ -334,6 +423,47 @@ static const struct test tests[] = { - .expected = -EINVAL, - .test_mode = CLONE3_ARGS_NO_TEST, - }, -+ { -+ .name = "Shadow stack on system with shadow stack", -+ .size = 0, -+ .expected = 0, -+ .e2big_valid = true, -+ .test_mode = CLONE3_ARGS_SHADOW_STACK, -+ .filter = no_shadow_stack, -+ }, -+ { -+ .name = "Shadow stack with no pointer", -+ .size = 0, -+ .expected = -EINVAL, -+ .e2big_valid = true, -+ .test_mode = CLONE3_ARGS_SHADOW_STACK_NO_POINTER, -+ }, -+ { -+ .name = "Shadow stack with no size", -+ .size = 0, -+ .expected = -EINVAL, -+ .e2big_valid = true, -+ .test_mode = CLONE3_ARGS_SHADOW_STACK_NO_SIZE, -+ .filter = no_shadow_stack, -+ }, -+ { -+ .name = "Shadow stack with no token", -+ .flags = CLONE_VM, -+ .size = 0, -+ .expected = SIGSEGV, -+ .e2big_valid = true, -+ .test_mode = CLONE3_ARGS_SHADOW_STACK_NO_TOKEN, -+ .filter = no_shadow_stack, -+ }, -+ { -+ .name = "Shadow stack on system without shadow stack", -+ .flags = CLONE_VM, -+ .size = 0, -+ .expected = -EINVAL, -+ .e2big_valid = true, -+ .test_mode = CLONE3_ARGS_SHADOW_STACK, -+ .filter = have_shadow_stack, -+ }, - }; - - int main(int argc, char *argv[]) -@@ -341,9 +471,12 @@ int main(int argc, char *argv[]) - size_t size; - int i; - -+ enable_shadow_stack(); -+ - ksft_print_header(); - ksft_set_plan(ARRAY_SIZE(tests)); - test_clone3_supported(); -+ test_shadow_stack_supported(); - - for (i = 0; i < ARRAY_SIZE(tests); i++) - test_clone3(&tests[i]); -diff --git a/tools/testing/selftests/clone3/clone3_selftests.h b/tools/testing/selftests/clone3/clone3_selftests.h -index 39b5dcba663c3..38d82934668a8 100644 ---- a/tools/testing/selftests/clone3/clone3_selftests.h -+++ b/tools/testing/selftests/clone3/clone3_selftests.h -@@ -31,12 +31,50 @@ struct __clone_args { - __aligned_u64 set_tid; - __aligned_u64 set_tid_size; - __aligned_u64 cgroup; -+#ifndef CLONE_ARGS_SIZE_VER2 -+#define CLONE_ARGS_SIZE_VER2 88 /* sizeof third published struct */ -+#endif -+ __aligned_u64 shadow_stack; -+ __aligned_u64 shadow_stack_size; -+#ifndef CLONE_ARGS_SIZE_VER3 -+#define CLONE_ARGS_SIZE_VER3 104 /* sizeof fourth published struct */ -+#endif - }; - -+/* -+ * For architectures with shadow stack support we need to be -+ * absolutely sure that the clone3() syscall will be inline and not a -+ * function call so we open code. -+ */ -+#ifdef __x86_64__ -+static pid_t __always_inline sys_clone3(struct __clone_args *args, size_t size) -+{ -+ long ret; -+ register long _num __asm__ ("rax") = __NR_clone3; -+ register long _args __asm__ ("rdi") = (long)(args); -+ register long _size __asm__ ("rsi") = (long)(size); -+ -+ __asm__ volatile ( -+ "syscall\n" -+ : "=a"(ret) -+ : "r"(_args), "r"(_size), -+ "0"(_num) -+ : "rcx", "r11", "memory", "cc" -+ ); -+ -+ if (ret < 0) { -+ errno = -ret; -+ return -1; -+ } -+ -+ return ret; -+} -+#else - static pid_t sys_clone3(struct __clone_args *args, size_t size) - { - return syscall(__NR_clone3, args, size); - } -+#endif - - static inline void test_clone3_supported(void) - { --- -2.34.1 - - -From a872040cac3fdcd2d39b6bcdf39a3090c4162d88 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 16 Aug 2023 17:33:47 +0100 -Subject: [PATCH 12/50] arm64/mm: Restructure arch_validate_flags() for +Date: Thu, 29 Aug 2024 00:27:18 +0100 +Subject: [PATCH 02/39] arm64/mm: Restructure arch_validate_flags() for extensibility Currently arch_validate_flags() is written in a very non-extensible @@ -1276,13 +100,14 @@ refactor the existing code to be more extensible, no functional change intended. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/mman.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h -index 5966ee4a61542..c21849ffdd88c 100644 +index 5966ee4a6154..c21849ffdd88 100644 --- a/arch/arm64/include/asm/mman.h +++ b/arch/arm64/include/asm/mman.h @@ -52,11 +52,17 @@ static inline bool arch_validate_prot(unsigned long prot, @@ -1308,13 +133,13 @@ index 5966ee4a61542..c21849ffdd88c 100644 #define arch_validate_flags(vm_flags) arch_validate_flags(vm_flags) -- -2.34.1 +2.25.1 -From 66bdc8c5b63b58092141260d4454dadfacb839f6 Mon Sep 17 00:00:00 2001 +From 7e1b99d29949a05bbaa86f5786f8cc1f04765959 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Sun, 12 Feb 2023 20:53:44 -0800 -Subject: [PATCH 13/50] prctl: arch-agnostic prctl for shadow stack +Date: Thu, 29 Aug 2024 00:27:19 +0100 +Subject: [PATCH 03/39] prctl: arch-agnostic prctl for shadow stack Three architectures (x86, aarch64, riscv) have announced support for shadow stacks with fairly similar functionality. While x86 is using @@ -1343,6 +168,7 @@ is also reworked to just set flags, if setting/reading the shadow stack pointer is required this could be a separate prctl. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- include/linux/mm.h | 4 ++++ @@ -1351,12 +177,12 @@ Signed-off-by: Mark Brown 3 files changed, 56 insertions(+) diff --git a/include/linux/mm.h b/include/linux/mm.h -index 5ec7bc3556578..120abcfaf974a 100644 +index 3357625c1db3..96faf26b6083 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h -@@ -4263,4 +4263,8 @@ static inline bool pfn_is_unaccepted_memory(unsigned long pfn) - void vma_pgtable_walk_begin(struct vm_area_struct *vma); - void vma_pgtable_walk_end(struct vm_area_struct *vma); +@@ -4201,4 +4201,8 @@ void vma_pgtable_walk_end(struct vm_area_struct *vma); + + int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t *size); +int arch_get_shadow_stack_status(struct task_struct *t, unsigned long __user *status); +int arch_set_shadow_stack_status(struct task_struct *t, unsigned long status); @@ -1364,7 +190,7 @@ index 5ec7bc3556578..120abcfaf974a 100644 + #endif /* _LINUX_MM_H */ diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h -index 35791791a879b..557a3d2ac1d48 100644 +index 35791791a879..557a3d2ac1d4 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -328,4 +328,26 @@ struct prctl_mm_map { @@ -1395,7 +221,7 @@ index 35791791a879b..557a3d2ac1d48 100644 + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c -index 3a2df1bd9f640..7e0c10e867cf5 100644 +index 3a2df1bd9f64..7e0c10e867cf 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -2324,6 +2324,21 @@ int __weak arch_prctl_spec_ctrl_set(struct task_struct *t, unsigned long which, @@ -1443,17 +269,17 @@ index 3a2df1bd9f640..7e0c10e867cf5 100644 error = -EINVAL; break; -- -2.34.1 +2.25.1 -From b999f727c6252e72559cce536ee465b264e51ab4 Mon Sep 17 00:00:00 2001 +From cc766f912025c1c4d5018c01d3bb9bbba4ecfd57 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 4 Aug 2023 14:50:18 +0100 -Subject: [PATCH 14/50] mman: Add map_shadow_stack() flags +Date: Thu, 29 Aug 2024 00:27:20 +0100 +Subject: [PATCH 04/39] mman: Add map_shadow_stack() flags In preparation for adding arm64 GCS support make the map_shadow_stack() SHADOW_STACK_SET_TOKEN flag generic and add _SET_MARKER. The existing -flag indicats that a token usable for stack switch should be added to +flag indicates that a token usable for stack switch should be added to the top of the newly mapped GCS region while the new flag indicates that a top of stack marker suitable for use by unwinders should be added above that. @@ -1461,6 +287,7 @@ above that. For arm64 the top of stack marker is all bits 0. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/x86/include/uapi/asm/mman.h | 3 --- @@ -1468,7 +295,7 @@ Signed-off-by: Mark Brown 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/x86/include/uapi/asm/mman.h b/arch/x86/include/uapi/asm/mman.h -index 46cdc941f9586..ac1e6277212b9 100644 +index 46cdc941f958..ac1e6277212b 100644 --- a/arch/x86/include/uapi/asm/mman.h +++ b/arch/x86/include/uapi/asm/mman.h @@ -5,9 +5,6 @@ @@ -1482,7 +309,7 @@ index 46cdc941f9586..ac1e6277212b9 100644 #endif /* _ASM_X86_MMAN_H */ diff --git a/include/uapi/asm-generic/mman.h b/include/uapi/asm-generic/mman.h -index 57e8195d0b538..d6a282687af51 100644 +index 57e8195d0b53..5e3d61ddbd8c 100644 --- a/include/uapi/asm-generic/mman.h +++ b/include/uapi/asm-generic/mman.h @@ -19,4 +19,8 @@ @@ -1490,46 +317,64 @@ index 57e8195d0b538..d6a282687af51 100644 #define MCL_ONFAULT 4 /* lock all pages that are faulted in */ +#define SHADOW_STACK_SET_TOKEN (1ULL << 0) /* Set up a restore token in the shadow stack */ -+#define SHADOW_STACK_SET_MARKER (1ULL << 1) /* Set up a top of stack merker in the shadow stack */ ++#define SHADOW_STACK_SET_MARKER (1ULL << 1) /* Set up a top of stack marker in the shadow stack */ + + #endif /* __ASM_GENERIC_MMAN_H */ -- -2.34.1 +2.25.1 -From f52fed1e45fc1eedb78305f38b74cc54b36fc91f Mon Sep 17 00:00:00 2001 +From bf77ab79ee24ae44c6a07b36c3571a1f7b435d1d Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 3 Mar 2023 17:16:43 +0000 -Subject: [PATCH 15/50] arm64: Document boot requirements for Guarded Control +Date: Thu, 29 Aug 2024 00:27:21 +0100 +Subject: [PATCH 05/39] arm64: Document boot requirements for Guarded Control Stacks FEAT_GCS introduces a number of new system registers, we require that access to these registers is not trapped when we identify that the feature -is detected. +is present. There is also a HCRX_EL2 control to make GCS operations +functional. + +Since if GCS is enabled any function call instruction will cause a fault +we also require that the feature be specifically disabled, existing +kernels implicitly have this requirement and especially given that the +MMU must be disabled it is difficult to see a situation where leaving +GCS enabled would be reasonable. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - Documentation/arch/arm64/booting.rst | 22 ++++++++++++++++++++++ - 1 file changed, 22 insertions(+) + Documentation/arch/arm64/booting.rst | 32 ++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) diff --git a/Documentation/arch/arm64/booting.rst b/Documentation/arch/arm64/booting.rst -index b57776a68f156..de3679770c645 100644 +index b57776a68f15..aed6e9f47cf3 100644 --- a/Documentation/arch/arm64/booting.rst +++ b/Documentation/arch/arm64/booting.rst -@@ -411,6 +411,28 @@ Before jumping into the kernel, the following conditions must be met: +@@ -411,6 +411,38 @@ Before jumping into the kernel, the following conditions must be met: - HFGRWR_EL2.nPIRE0_EL1 (bit 57) must be initialised to 0b1. -+ - For features with Guarded Control Stacks (FEAT_GCS): ++ - For CPUs with Guarded Control Stacks (FEAT_GCS): ++ ++ - GCSCR_EL1 must be initialised to 0. ++ ++ - GCSCRE0_EL1 must be initialised to 0. + + - If EL3 is present: + + - SCR_EL3.GCSEn (bit 39) must be initialised to 0b1. + ++ - If EL2 is present: ++ ++ - GCSCR_EL2 must be initialised to 0. ++ + - If the kernel is entered at EL1 and EL2 is present: + ++ - HCRX_EL2.GCSEn must be initialised to 0b1. ++ + - HFGITR_EL2.nGCSEPP (bit 59) must be initialised to 0b1. + + - HFGITR_EL2.nGCSSTR_EL1 (bit 58) must be initialised to 0b1. @@ -1548,30 +393,31 @@ index b57776a68f156..de3679770c645 100644 timers, coherency and system registers apply to all CPUs. All CPUs must enter the kernel in the same exception level. Where the values documented -- -2.34.1 +2.25.1 -From 39d2bab06fb1b6e21ba896425f3c5bda455f4e5d Mon Sep 17 00:00:00 2001 +From 138a58cabaadd18f6959c3458d19b9f06b1e9b55 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Tue, 4 Jul 2023 00:17:55 +0100 -Subject: [PATCH 16/50] arm64/gcs: Document the ABI for Guarded Control Stacks +Date: Thu, 29 Aug 2024 00:27:22 +0100 +Subject: [PATCH 06/39] arm64/gcs: Document the ABI for Guarded Control Stacks Add some documentation of the userspace ABI for Guarded Control Stacks. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - Documentation/arch/arm64/gcs.rst | 233 +++++++++++++++++++++++++++++ + Documentation/arch/arm64/gcs.rst | 230 +++++++++++++++++++++++++++++ Documentation/arch/arm64/index.rst | 1 + - 2 files changed, 234 insertions(+) + 2 files changed, 231 insertions(+) create mode 100644 Documentation/arch/arm64/gcs.rst diff --git a/Documentation/arch/arm64/gcs.rst b/Documentation/arch/arm64/gcs.rst new file mode 100644 -index 0000000000000..c45c0326836a4 +index 000000000000..421c953a0ffc --- /dev/null +++ b/Documentation/arch/arm64/gcs.rst -@@ -0,0 +1,233 @@ +@@ -0,0 +1,230 @@ +=============================================== +Guarded Control Stack support for AArch64 Linux +=============================================== @@ -1598,7 +444,7 @@ index 0000000000000..c45c0326836a4 + performed the current PC is pushed onto the GCS and on RET the + address in the LR is verified against that on the top of the GCS. + -+* When active current GCS pointer is stored in the system register ++* When active the current GCS pointer is stored in the system register + GCSPR_EL0. This is readable by userspace but can only be updated + via specific GCS instructions. + @@ -1630,9 +476,6 @@ index 0000000000000..c45c0326836a4 + in LR match those in the GCS, the LR will be ignored. This is not supported + by Linux. + -+* EL0 GCS entries with bit 63 set are reserved for use, one such use is defined -+ below for signals and should be ignored when parsing the stack if not -+ understood. + + +2. Enabling and disabling Guarded Control Stacks @@ -1691,8 +534,8 @@ index 0000000000000..c45c0326836a4 +---------------------------------------- + +* When GCS is enabled for a thread a new Guarded Control Stack will be -+ allocated for it of size RLIMIT_STACK or 4 gigabytes, whichever is -+ smaller. ++ allocated for it of half the standard stack size or 2 gigabytes, ++ whichever is smaller. + +* When a new thread is created by a thread which has GCS enabled then a + new Guarded Control Stack will be allocated for the new thread with @@ -1740,8 +583,8 @@ index 0000000000000..c45c0326836a4 + +* When GCS is enabled for the interrupted thread a signal handling specific + GCS cap token will be written to the GCS, this is an architectural GCS cap -+ token with bit 63 set and the token type (bits 0..11) all clear. The -+ GCSPR_EL0 reported in the signal frame will point to this cap token. ++ with the token type (bits 0..11) all clear. The GCSPR_EL0 reported in the ++ signal frame will point to this cap token. + +* The signal handler will use the same GCS as the interrupted context. + @@ -1806,41 +649,42 @@ index 0000000000000..c45c0326836a4 +* Guarded Control Stack pages will include "ss" in their VmFlags in + /proc//smaps. diff --git a/Documentation/arch/arm64/index.rst b/Documentation/arch/arm64/index.rst -index d08e924204bf1..dcf3ee3eb8c08 100644 +index 78544de0a8a9..056f6a739d25 100644 --- a/Documentation/arch/arm64/index.rst +++ b/Documentation/arch/arm64/index.rst -@@ -14,6 +14,7 @@ ARM64 Architecture - booting +@@ -15,6 +15,7 @@ ARM64 Architecture cpu-feature-registers + cpu-hotplug elf_hwcaps + gcs hugetlbpage kdump legacy_instructions -- -2.34.1 +2.25.1 -From 257fd303f69127cf067d922e56997db78e3b131d Mon Sep 17 00:00:00 2001 +From 5c37d654752a01150628a12e6997fc4929bc368d Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Tue, 20 Jun 2023 19:28:37 +0100 -Subject: [PATCH 17/50] arm64/sysreg: Add definitions for architected GCS caps +Date: Thu, 29 Aug 2024 00:27:23 +0100 +Subject: [PATCH 07/39] arm64/sysreg: Add definitions for architected GCS caps The architecture defines a format for guarded control stack caps, used to mark the top of an unused GCS in order to limit the potential for exploitation via stack switching. Add definitions associated with these. Reviewed-by: Thiago Jung Bauermann +Acked-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/sysreg.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h -index af3b206fa4239..325a1daa98ed8 100644 +index 4a9ea103817e..b8d8718a7b8b 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h -@@ -1064,6 +1064,26 @@ +@@ -1077,6 +1077,26 @@ #define POE_RXW UL(0x7) #define POE_MASK UL(0xf) @@ -1868,13 +712,13 @@ index af3b206fa4239..325a1daa98ed8 100644 /* Defined for compatibility only, do not add new users. */ -- -2.34.1 +2.25.1 -From 2f8a10699e2a674df32ce70ecf43afdfa28c9527 Mon Sep 17 00:00:00 2001 +From db1f96f6cb106892b45857028397743c6a0d1dab Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Tue, 20 Jun 2023 19:31:24 +0100 -Subject: [PATCH 18/50] arm64/gcs: Add manual encodings of GCS instructions +Date: Thu, 29 Aug 2024 00:27:24 +0100 +Subject: [PATCH 08/39] arm64/gcs: Add manual encodings of GCS instructions Define C callable functions for GCS instructions used by the kernel. In order to avoid ambitious toolchain requirements for GCS support these are @@ -1885,6 +729,7 @@ sufficiently fast paths for this to be a problem. Note that GCSSTTR is used to store to EL0. Reviewed-by: Thiago Jung Bauermann +Acked-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/gcs.h | 51 ++++++++++++++++++++++++++++++++ @@ -1894,7 +739,7 @@ Signed-off-by: Mark Brown diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h new file mode 100644 -index 0000000000000..7c5e95218db6b +index 000000000000..7c5e95218db6 --- /dev/null +++ b/arch/arm64/include/asm/gcs.h @@ -0,0 +1,51 @@ @@ -1950,10 +795,10 @@ index 0000000000000..7c5e95218db6b + +#endif diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h -index 14be5000c5a0c..22e10e79f56ae 100644 +index 28f665e0975a..6aba10e38d1c 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h -@@ -425,4 +425,26 @@ static inline size_t probe_subpage_writeable(const char __user *uaddr, +@@ -502,4 +502,26 @@ static inline size_t probe_subpage_writeable(const char __user *uaddr, #endif /* CONFIG_ARCH_HAS_SUBPAGE_FAULTS */ @@ -1981,28 +826,29 @@ index 14be5000c5a0c..22e10e79f56ae 100644 + #endif /* __ASM_UACCESS_H */ -- -2.34.1 +2.25.1 -From f0081588cadbd6a4e64c1f64209c29b76586c0ef Mon Sep 17 00:00:00 2001 +From 7ef79e5e03ad17c40dff10cceaf5e7c4b86c2eaf Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Sun, 16 Jul 2023 14:43:47 +0100 -Subject: [PATCH 19/50] arm64/gcs: Provide put_user_gcs() +Date: Thu, 29 Aug 2024 00:27:25 +0100 +Subject: [PATCH 09/39] arm64/gcs: Provide put_user_gcs() In order for EL1 to write to an EL0 GCS it must use the GCSSTTR instruction rather than a normal STTR. Provide a put_user_gcs() which does this. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/uaccess.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h -index 22e10e79f56ae..e118c3d772c8d 100644 +index 6aba10e38d1c..ecdd47cf1d01 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h -@@ -445,6 +445,24 @@ static inline int gcssttr(unsigned long __user *addr, unsigned long val) +@@ -522,6 +522,24 @@ static inline int gcssttr(unsigned long __user *addr, unsigned long val) return err; } @@ -2028,28 +874,116 @@ index 22e10e79f56ae..e118c3d772c8d 100644 #endif /* __ASM_UACCESS_H */ -- -2.34.1 +2.25.1 -From e149c7101e4fb52b0e365acfc7ee760837d49d46 Mon Sep 17 00:00:00 2001 +From 2e599797e44eeb1e124b8a3b1ecf97e486e59aaf Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Tue, 7 Mar 2023 22:35:56 +0000 -Subject: [PATCH 20/50] arm64/cpufeature: Runtime detection of Guarded Control +Date: Thu, 29 Aug 2024 00:27:26 +0100 +Subject: [PATCH 10/39] arm64/gcs: Provide basic EL2 setup to allow GCS usage + at EL0 and EL1 + +There is a control HCRX_EL2.GCSEn which must be set to allow GCS +features to take effect at lower ELs and also fine grained traps for GCS +usage at EL0 and EL1. Configure all these to allow GCS usage by EL0 and +EL1. + +We also initialise GCSCR_EL1 and GCSCRE0_EL1 to ensure that we can +execute function call instructions without faulting regardless of the +state when the kernel is started. + +Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas +Signed-off-by: Mark Brown +--- + arch/arm64/include/asm/el2_setup.h | 29 +++++++++++++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h +index fd87c4b8f984..09211aebcf03 100644 +--- a/arch/arm64/include/asm/el2_setup.h ++++ b/arch/arm64/include/asm/el2_setup.h +@@ -27,6 +27,14 @@ + ubfx x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4 + cbz x0, .Lskip_hcrx_\@ + mov_q x0, HCRX_HOST_FLAGS ++ ++ /* Enable GCS if supported */ ++ mrs_s x1, SYS_ID_AA64PFR1_EL1 ++ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 ++ cbz x1, .Lset_hcrx_\@ ++ orr x0, x0, #HCRX_EL2_GCSEn ++ ++.Lset_hcrx_\@: + msr_s SYS_HCRX_EL2, x0 + .Lskip_hcrx_\@: + .endm +@@ -191,6 +199,15 @@ + orr x0, x0, #HFGxTR_EL2_nPIR_EL1 + orr x0, x0, #HFGxTR_EL2_nPIRE0_EL1 + ++ /* GCS depends on PIE so we don't check it if PIE is absent */ ++ mrs_s x1, SYS_ID_AA64PFR1_EL1 ++ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 ++ cbz x1, .Lset_fgt_\@ ++ ++ /* Disable traps of access to GCS registers at EL0 and EL1 */ ++ orr x0, x0, #HFGxTR_EL2_nGCS_EL1_MASK ++ orr x0, x0, #HFGxTR_EL2_nGCS_EL0_MASK ++ + .Lset_fgt_\@: + msr_s SYS_HFGRTR_EL2, x0 + msr_s SYS_HFGWTR_EL2, x0 +@@ -204,6 +221,17 @@ + .Lskip_fgt_\@: + .endm + ++.macro __init_el2_gcs ++ mrs_s x1, SYS_ID_AA64PFR1_EL1 ++ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 ++ cbz x1, .Lskip_gcs_\@ ++ ++ /* Ensure GCS is not enabled when we start trying to do BLs */ ++ msr_s SYS_GCSCR_EL1, xzr ++ msr_s SYS_GCSCRE0_EL1, xzr ++.Lskip_gcs_\@: ++.endm ++ + .macro __init_el2_nvhe_prepare_eret + mov x0, #INIT_PSTATE_EL1 + msr spsr_el2, x0 +@@ -229,6 +257,7 @@ + __init_el2_nvhe_idregs + __init_el2_cptr + __init_el2_fgt ++ __init_el2_gcs + .endm + + #ifndef __KVM_NVHE_HYPERVISOR__ +-- +2.25.1 + + +From dd7c0014582d449dff1b71171bb2405aa090f574 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Thu, 29 Aug 2024 00:27:27 +0100 +Subject: [PATCH 11/39] arm64/cpufeature: Runtime detection of Guarded Control Stack (GCS) Add a cpufeature for GCS, allowing other code to conditionally support it at runtime. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - arch/arm64/include/asm/cpufeature.h | 6 ++++++ - arch/arm64/kernel/cpufeature.c | 16 ++++++++++++++++ - arch/arm64/tools/cpucaps | 1 + - 3 files changed, 23 insertions(+) + arch/arm64/include/asm/cpufeature.h | 6 ++++++ + arch/arm64/kernel/cpufeature.c | 9 +++++++++ + arch/arm64/tools/cpucaps | 1 + + 3 files changed, 16 insertions(+) diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h -index 8b904a757bd34..0ebed5dfe55fc 100644 +index 558434267271..e0f0e4c24544 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -832,6 +832,12 @@ static inline bool system_supports_lpa2(void) @@ -2066,7 +1000,7 @@ index 8b904a757bd34..0ebed5dfe55fc 100644 bool try_emulate_mrs(struct pt_regs *regs, u32 isn); diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c -index 48e7029f10548..056d394920f9f 100644 +index 646ecd3069fd..315bd7be1106 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -291,6 +291,8 @@ static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { @@ -2078,20 +1012,7 @@ index 48e7029f10548..056d394920f9f 100644 ARM64_FTR_BITS(FTR_VISIBLE_IF_IS_ENABLED(CONFIG_ARM64_SME), FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_SME_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR1_EL1_MPAM_frac_SHIFT, 4, 0), -@@ -2347,6 +2349,12 @@ static void cpu_enable_mops(const struct arm64_cpu_capabilities *__unused) - sysreg_clear_set(sctlr_el1, 0, SCTLR_EL1_MSCEn); - } - -+static void cpu_enable_gcs(const struct arm64_cpu_capabilities *__unused) -+{ -+ /* GCS is not currently used at EL1 */ -+ write_sysreg_s(0, SYS_GCSCR_EL1); -+} -+ - /* Internal helper functions to match cpu capability type */ - static bool - cpucap_late_cpu_optional(const struct arm64_cpu_capabilities *cap) -@@ -2869,6 +2877,14 @@ static const struct arm64_cpu_capabilities arm64_features[] = { +@@ -2870,6 +2872,13 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .matches = has_nv1, ARM64_CPUID_FIELDS_NEG(ID_AA64MMFR4_EL1, E2H0, NI_NV1) }, @@ -2099,7 +1020,6 @@ index 48e7029f10548..056d394920f9f 100644 + .desc = "Guarded Control Stack (GCS)", + .capability = ARM64_HAS_GCS, + .type = ARM64_CPUCAP_SYSTEM_FEATURE, -+ .cpu_enable = cpu_enable_gcs, + .matches = has_cpuid_feature, + ARM64_CPUID_FIELDS(ID_AA64PFR1_EL1, GCS, IMP) + }, @@ -2107,7 +1027,7 @@ index 48e7029f10548..056d394920f9f 100644 }; diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps -index ac3429d892b9a..66eff95c0824b 100644 +index ac3429d892b9..66eff95c0824 100644 --- a/arch/arm64/tools/cpucaps +++ b/arch/arm64/tools/cpucaps @@ -29,6 +29,7 @@ HAS_EVT @@ -2119,13 +1039,13 @@ index ac3429d892b9a..66eff95c0824b 100644 HAS_GENERIC_AUTH_ARCH_QARMA3 HAS_GENERIC_AUTH_ARCH_QARMA5 -- -2.34.1 +2.25.1 -From 31d2836d393caa031a762a392f70dcb3a9096aab Mon Sep 17 00:00:00 2001 +From 497e9d9d1ad7090c0cc3ca3c4667c0b67e8b0634 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 21 Apr 2023 19:37:37 +0100 -Subject: [PATCH 21/50] arm64/mm: Allocate PIE slots for EL0 guarded control +Date: Thu, 29 Aug 2024 00:27:28 +0100 +Subject: [PATCH 12/39] arm64/mm: Allocate PIE slots for EL0 guarded control stack Pages used for guarded control stacks need to be described to the hardware @@ -2139,13 +1059,14 @@ does not matter to the hardware but we choose two values which differ only in PTE_WRITE in order to help share code with non-PIE cases. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/pgtable-prot.h | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h -index b11cfb9fdd379..545d54c885203 100644 +index b11cfb9fdd37..545d54c88520 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -144,15 +144,23 @@ static inline bool __pure lpa2_is_enabled(void) @@ -2184,54 +1105,40 @@ index b11cfb9fdd379..545d54c885203 100644 PIRx_ELx_PERM(pte_pi_index(_PAGE_READONLY_EXEC), PIE_R) | \ PIRx_ELx_PERM(pte_pi_index(_PAGE_SHARED_EXEC), PIE_RW) | \ -- -2.34.1 +2.25.1 -From 7dd12e2cb546f804ead1022d46ae6a62d3dc4523 Mon Sep 17 00:00:00 2001 +From ae0358190c7d47fb04d849d7dd8f3e67a40db0b0 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 14 Apr 2023 20:29:18 +0100 -Subject: [PATCH 22/50] mm: Define VM_SHADOW_STACK for arm64 when we support +Date: Thu, 29 Aug 2024 00:27:29 +0100 +Subject: [PATCH 13/39] mm: Define VM_SHADOW_STACK for arm64 when we support GCS Use VM_HIGH_ARCH_5 for guarded control stack pages. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- Documentation/filesystems/proc.rst | 2 +- - fs/proc/task_mmu.c | 3 +++ include/linux/mm.h | 12 +++++++++++- - 3 files changed, 15 insertions(+), 2 deletions(-) + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst -index 7c3a565ffbef3..105312a0b33dd 100644 +index e834779d9611..6a882c57a7e7 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst -@@ -570,7 +570,7 @@ encoded manner. The codes are the following: +@@ -579,7 +579,7 @@ encoded manner. The codes are the following: mt arm64 MTE allocation tags are enabled um userfaultfd missing tracking uw userfaultfd wr-protect tracking - ss shadow stack page + ss shadow/guarded control stack page + sl sealed == ======================================= - Note that there is no guarantee that every flag and associated mnemonic will -diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c -index 1b56c10775072..6ef1137bcad82 100644 ---- a/fs/proc/task_mmu.c -+++ b/fs/proc/task_mmu.c -@@ -706,6 +706,9 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) - #endif /* CONFIG_HAVE_ARCH_USERFAULTFD_MINOR */ - #ifdef CONFIG_ARCH_HAS_USER_SHADOW_STACK - [ilog2(VM_SHADOW_STACK)] = "ss", -+#endif -+#ifdef CONFIG_ARM64_GCS -+ [ilog2(VM_SHADOW_STACK)] = "ss", - #endif - }; - size_t i; diff --git a/include/linux/mm.h b/include/linux/mm.h -index 120abcfaf974a..73211cfe7b313 100644 +index 96faf26b6083..c6c7454ce4e0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -353,7 +353,17 @@ extern unsigned int kobjsize(const void *objp); @@ -2254,13 +1161,13 @@ index 120abcfaf974a..73211cfe7b313 100644 #endif -- -2.34.1 +2.25.1 -From befe6494800c8c67ff50c36f01ab3265ae562f1f Mon Sep 17 00:00:00 2001 +From 22cd858937a818979e73be6809c2baa2c24f601f Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 21 Apr 2023 20:53:01 +0100 -Subject: [PATCH 23/50] arm64/mm: Map pages for guarded control stack +Date: Thu, 29 Aug 2024 00:27:30 +0100 +Subject: [PATCH 14/39] arm64/mm: Map pages for guarded control stack Map pages flagged as being part of a GCS as such rather than using the full set of generic VM flags. @@ -2269,14 +1176,15 @@ This is done using a conditional rather than extending the size of protection_map since that would make for a very sparse array. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - arch/arm64/include/asm/mman.h | 9 +++++++++ - arch/arm64/mm/mmap.c | 13 ++++++++++++- - 2 files changed, 21 insertions(+), 1 deletion(-) + arch/arm64/include/asm/mman.h | 9 +++++++++ + arch/arm64/mm/mmap.c | 9 ++++++++- + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h -index c21849ffdd88c..6d3fe6433a627 100644 +index c21849ffdd88..37dfd2882f04 100644 --- a/arch/arm64/include/asm/mman.h +++ b/arch/arm64/include/asm/mman.h @@ -61,6 +61,15 @@ static inline bool arch_validate_flags(unsigned long vm_flags) @@ -2284,71 +1192,76 @@ index c21849ffdd88c..6d3fe6433a627 100644 } + if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) { -+ /* -+ * An executable GCS isn't a good idea, and the mm -+ * core can't cope with a shared GCS. -+ */ -+ if (vm_flags & (VM_EXEC | VM_ARM64_BTI | VM_SHARED)) ++ /* An executable GCS isn't a good idea. */ ++ if (vm_flags & VM_EXEC) + return false; ++ ++ /* The memory management core should prevent this */ ++ VM_WARN_ON(vm_flags & VM_SHARED); + } + return true; } diff --git a/arch/arm64/mm/mmap.c b/arch/arm64/mm/mmap.c -index 642bdf908b22f..68a17bd09d002 100644 +index 642bdf908b22..5943898f366b 100644 --- a/arch/arm64/mm/mmap.c +++ b/arch/arm64/mm/mmap.c -@@ -83,9 +83,20 @@ arch_initcall(adjust_protection_map); +@@ -83,8 +83,15 @@ arch_initcall(adjust_protection_map); pgprot_t vm_get_page_prot(unsigned long vm_flags) { - pteval_t prot = pgprot_val(protection_map[vm_flags & + pteval_t prot; + -+ /* If this is a GCS then only interpret VM_WRITE. */ ++ /* Short circuit GCS to avoid bloating the table. */ + if (system_supports_gcs() && (vm_flags & VM_SHADOW_STACK)) { -+ if (vm_flags & VM_WRITE) -+ prot = _PAGE_GCS; -+ else -+ prot = _PAGE_GCS_RO; ++ prot = _PAGE_GCS_RO; + } else { + prot = pgprot_val(protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]); + } -+ /* VM_ARM64_BTI on a GCS is rejected in arch_validate_flags() */ if (vm_flags & VM_ARM64_BTI) prot |= PTE_GP; - -- -2.34.1 +2.25.1 -From fb9b5068a4ff18668afb0d7bd0c0ff419f8acc35 Mon Sep 17 00:00:00 2001 +From 6095f8d4a7255549566549a285cdade980f4629c Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 8 Mar 2023 00:40:28 +0000 -Subject: [PATCH 24/50] KVM: arm64: Manage GCS registers for guests +Date: Thu, 29 Aug 2024 00:27:31 +0100 +Subject: [PATCH 15/39] KVM: arm64: Manage GCS access and registers for guests GCS introduces a number of system registers for EL1 and EL0, on systems with GCS we need to context switch them and expose them to VMMs to allow -guests to use GCS, as well as describe their fine grained traps to -nested virtualisation. Traps are already disabled. +guests to use GCS. + +In order to allow guests to use GCS we also need to configure +HCRX_EL2.GCSEn, if this is not set GCS instructions will be noops and +CHKFEAT will report GCS as disabled. Also enable fine grained traps for +access to the GCS registers by guests which do not have the feature +enabled. + +In order to allow userspace to control availability of the feature to +guests we enable writability for only ID_AA64PFR1_EL1.GCS, this is a +deliberately conservative choice to avoid errors due to oversights. +Further fields should be made writable in future. Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- - arch/arm64/include/asm/kvm_host.h | 14 +++++++ + arch/arm64/include/asm/kvm_host.h | 12 ++++++ arch/arm64/include/asm/vncr_mapping.h | 2 + - arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 48 +++++++++++++++++----- - arch/arm64/kvm/sys_regs.c | 25 ++++++++++- - 4 files changed, 78 insertions(+), 11 deletions(-) + arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h | 49 +++++++++++++++++----- + arch/arm64/kvm/sys_regs.c | 27 +++++++++++- + 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h -index 36b8e97bf49ec..316fb412f3554 100644 +index a33f5996ca9f..88d6a85a2844 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h -@@ -411,6 +411,10 @@ enum vcpu_sysreg { +@@ -446,6 +446,10 @@ enum vcpu_sysreg { GCR_EL1, /* Tag Control Register */ TFSRE0_EL1, /* Tag Fault Status Register (EL0) */ @@ -2359,7 +1272,7 @@ index 36b8e97bf49ec..316fb412f3554 100644 /* 32bit specific registers. */ DACR32_EL2, /* Domain Access Control Register */ IFSR32_EL2, /* Instruction Fault Status Register */ -@@ -481,6 +485,10 @@ enum vcpu_sysreg { +@@ -517,6 +521,10 @@ enum vcpu_sysreg { VNCR(PIR_EL1), /* Permission Indirection Register 1 (EL1) */ VNCR(PIRE0_EL1), /* Permission Indirection Register 0 (EL1) */ @@ -2370,21 +1283,17 @@ index 36b8e97bf49ec..316fb412f3554 100644 VNCR(HFGRTR_EL2), VNCR(HFGWTR_EL2), VNCR(HFGITR_EL2), -@@ -1343,6 +1351,12 @@ static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature) +@@ -1473,4 +1481,8 @@ void kvm_set_vm_id_reg(struct kvm *kvm, u32 reg, u64 val); + (pa + pi + pa3) == 1; \ + }) - #define kvm_vcpu_initialized(v) vcpu_get_flag(vcpu, VCPU_INITIALIZED) - -+static inline bool has_gcs(void) -+{ -+ return IS_ENABLED(CONFIG_ARM64_GCS) && -+ cpus_have_final_cap(ARM64_HAS_GCS); -+} ++#define kvm_has_gcs(k) \ ++ (system_supports_gcs() && \ ++ kvm_has_feat((k), ID_AA64PFR1_EL1, GCS, IMP)) + - int kvm_trng_call(struct kvm_vcpu *vcpu); - #ifdef CONFIG_KVM - extern phys_addr_t hyp_mem_base; + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/vncr_mapping.h b/arch/arm64/include/asm/vncr_mapping.h -index df2c47c559728..5e83e6f579fd6 100644 +index df2c47c55972..5e83e6f579fd 100644 --- a/arch/arm64/include/asm/vncr_mapping.h +++ b/arch/arm64/include/asm/vncr_mapping.h @@ -88,6 +88,8 @@ @@ -2397,7 +1306,7 @@ index df2c47c559728..5e83e6f579fd6 100644 #define VNCR_MPAMHCR_EL2 0x930 #define VNCR_MPAMVPMV_EL2 0x938 diff --git a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h -index 4be6a7fa00708..b20212d80e9b6 100644 +index 4c0fdabaf8ae..ac29352e225a 100644 --- a/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h +++ b/arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h @@ -16,6 +16,27 @@ @@ -2428,7 +1337,7 @@ index 4be6a7fa00708..b20212d80e9b6 100644 static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, MDSCR_EL1) = read_sysreg(mdscr_el1); -@@ -25,16 +46,8 @@ static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) +@@ -25,16 +46,10 @@ static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt) { ctxt_sys_reg(ctxt, TPIDR_EL0) = read_sysreg(tpidr_el0); ctxt_sys_reg(ctxt, TPIDRRO_EL0) = read_sysreg(tpidrro_el0); @@ -2442,183 +1351,147 @@ index 4be6a7fa00708..b20212d80e9b6 100644 - vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt); - - return vcpu; -+ if (ctxt_has_gcs(ctxt)) ++ if (ctxt_has_gcs(ctxt)) { + ctxt_sys_reg(ctxt, GCSPR_EL0) = read_sysreg_s(SYS_GCSPR_EL0); ++ ctxt_sys_reg(ctxt, GCSCRE0_EL1) = read_sysreg_s(SYS_GCSCRE0_EL1); ++ } } static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt) -@@ -80,6 +93,12 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) - ctxt_sys_reg(ctxt, PAR_EL1) = read_sysreg_par(); - ctxt_sys_reg(ctxt, TPIDR_EL1) = read_sysreg(tpidr_el1); - -+ if (ctxt_has_gcs(ctxt)) { -+ ctxt_sys_reg(ctxt, GCSPR_EL1) = read_sysreg_el1(SYS_GCSPR); -+ ctxt_sys_reg(ctxt, GCSCR_EL1) = read_sysreg_el1(SYS_GCSCR); -+ ctxt_sys_reg(ctxt, GCSCRE0_EL1) = read_sysreg_s(SYS_GCSCRE0_EL1); -+ } -+ - if (ctxt_has_mte(ctxt)) { - ctxt_sys_reg(ctxt, TFSR_EL1) = read_sysreg_el1(SYS_TFSR); - ctxt_sys_reg(ctxt, TFSRE0_EL1) = read_sysreg_s(SYS_TFSRE0_EL1); -@@ -113,6 +132,8 @@ static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) +@@ -79,6 +94,10 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) + if (ctxt_has_s1pie(ctxt)) { + ctxt_sys_reg(ctxt, PIR_EL1) = read_sysreg_el1(SYS_PIR); + ctxt_sys_reg(ctxt, PIRE0_EL1) = read_sysreg_el1(SYS_PIRE0); ++ if (ctxt_has_gcs(ctxt)) { ++ ctxt_sys_reg(ctxt, GCSPR_EL1) = read_sysreg_el1(SYS_GCSPR); ++ ctxt_sys_reg(ctxt, GCSCR_EL1) = read_sysreg_el1(SYS_GCSCR); ++ } + } + } + ctxt_sys_reg(ctxt, ESR_EL1) = read_sysreg_el1(SYS_ESR); +@@ -126,6 +145,11 @@ static inline void __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) { write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL0), tpidr_el0); write_sysreg(ctxt_sys_reg(ctxt, TPIDRRO_EL0), tpidrro_el0); -+ if (ctxt_has_gcs(ctxt)) -+ write_sysreg_s(ctxt_sys_reg(ctxt, GCSPR_EL0), SYS_GCSPR_EL0); - } - - static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) -@@ -156,6 +177,13 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) - write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1), par_el1); - write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1), tpidr_el1); - + if (ctxt_has_gcs(ctxt)) { -+ write_sysreg_el1(ctxt_sys_reg(ctxt, GCSPR_EL1), SYS_GCSPR); -+ write_sysreg_el1(ctxt_sys_reg(ctxt, GCSCR_EL1), SYS_GCSCR); ++ write_sysreg_s(ctxt_sys_reg(ctxt, GCSPR_EL0), SYS_GCSPR_EL0); + write_sysreg_s(ctxt_sys_reg(ctxt, GCSCRE0_EL1), + SYS_GCSCRE0_EL1); + } + } + + static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) +@@ -157,6 +181,11 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) + if (ctxt_has_s1pie(ctxt)) { + write_sysreg_el1(ctxt_sys_reg(ctxt, PIR_EL1), SYS_PIR); + write_sysreg_el1(ctxt_sys_reg(ctxt, PIRE0_EL1), SYS_PIRE0); + - if (ctxt_has_mte(ctxt)) { - write_sysreg_el1(ctxt_sys_reg(ctxt, TFSR_EL1), SYS_TFSR); - write_sysreg_s(ctxt_sys_reg(ctxt, TFSRE0_EL1), SYS_TFSRE0_EL1); ++ if (ctxt_has_gcs(ctxt)) { ++ write_sysreg_el1(ctxt_sys_reg(ctxt, GCSPR_EL1), SYS_GCSPR); ++ write_sysreg_el1(ctxt_sys_reg(ctxt, GCSCR_EL1), SYS_GCSCR); ++ } + } + } + write_sysreg_el1(ctxt_sys_reg(ctxt, ESR_EL1), SYS_ESR); diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c -index 22b45a15d0688..cf068dcfbd494 100644 +index c90324060436..4e820dd50414 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c -@@ -2015,6 +2015,23 @@ static unsigned int mte_visibility(const struct kvm_vcpu *vcpu, - .visibility = mte_visibility, \ +@@ -1645,6 +1645,15 @@ static unsigned int raz_visibility(const struct kvm_vcpu *vcpu, + return REG_RAZ; } +static unsigned int gcs_visibility(const struct kvm_vcpu *vcpu, -+ const struct sys_reg_desc *rd) ++ const struct sys_reg_desc *r) +{ -+ if (has_gcs()) ++ if (kvm_has_gcs(vcpu->kvm)) + return 0; + + return REG_HIDDEN; +} + -+#define GCS_REG(name) { \ -+ SYS_DESC(SYS_##name), \ -+ .access = undef_access, \ -+ .reset = reset_unknown, \ -+ .reg = name, \ -+ .visibility = gcs_visibility, \ -+} -+ - static unsigned int el2_visibility(const struct kvm_vcpu *vcpu, - const struct sys_reg_desc *rd) - { -@@ -2306,7 +2323,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { + /* cpufeature ID register access trap handlers */ + + static bool access_id_reg(struct kvm_vcpu *vcpu, +@@ -2362,7 +2371,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { ID_AA64PFR0_EL1_GIC | ID_AA64PFR0_EL1_AdvSIMD | ID_AA64PFR0_EL1_FP), }, - ID_SANITISED(ID_AA64PFR1_EL1), -+ ID_WRITABLE(ID_AA64PFR1_EL1, ~(ID_AA64PFR1_EL1_RES0 | -+ ID_AA64PFR1_EL1_BT)), ++ ID_WRITABLE(ID_AA64PFR1_EL1, ID_AA64PFR1_EL1_GCS), ID_UNALLOCATED(4,2), ID_UNALLOCATED(4,3), ID_WRITABLE(ID_AA64ZFR0_EL1, ~ID_AA64ZFR0_EL1_RES0), -@@ -2390,6 +2408,10 @@ static const struct sys_reg_desc sys_reg_descs[] = { +@@ -2446,6 +2455,13 @@ static const struct sys_reg_desc sys_reg_descs[] = { PTRAUTH_KEY(APDB), PTRAUTH_KEY(APGA), -+ GCS_REG(GCSCR_EL1), -+ GCS_REG(GCSPR_EL1), -+ GCS_REG(GCSCRE0_EL1), ++ { SYS_DESC(SYS_GCSCR_EL1), NULL, reset_val, GCSCR_EL1, 0, ++ .visibility = gcs_visibility }, ++ { SYS_DESC(SYS_GCSPR_EL1), NULL, reset_unknown, GCSPR_EL1, ++ .visibility = gcs_visibility }, ++ { SYS_DESC(SYS_GCSCRE0_EL1), NULL, reset_val, GCSCRE0_EL1, 0, ++ .visibility = gcs_visibility }, + { SYS_DESC(SYS_SPSR_EL1), access_spsr}, { SYS_DESC(SYS_ELR_EL1), access_elr}, -@@ -2476,6 +2498,7 @@ static const struct sys_reg_desc sys_reg_descs[] = { - { SYS_DESC(SYS_SMIDR_EL1), undef_access }, - { SYS_DESC(SYS_CSSELR_EL1), access_csselr, reset_unknown, CSSELR_EL1 }, - { SYS_DESC(SYS_CTR_EL0), access_ctr }, -+ GCS_REG(GCSPR_EL0), +@@ -2535,6 +2551,8 @@ static const struct sys_reg_desc sys_reg_descs[] = { + CTR_EL0_IDC_MASK | + CTR_EL0_DminLine_MASK | + CTR_EL0_IminLine_MASK), ++ { SYS_DESC(SYS_GCSPR_EL0), NULL, reset_unknown, GCSPR_EL0, ++ .visibility = gcs_visibility }, { SYS_DESC(SYS_SVCR), undef_access }, { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr, .reset = reset_pmcr, --- -2.34.1 - - -From 4d20a635efb93819c99ab92797445c26defb7411 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 15 Mar 2023 18:48:06 +0000 -Subject: [PATCH 25/50] arm64/gcs: Allow GCS usage at EL0 and EL1 - -There is a control HCRX_EL2.GCSEn which must be set to allow GCS -features to take effect at lower ELs and also fine grained traps for GCS -usage at EL0 and EL1. Configure all these to allow GCS usage by EL0 and -EL1. - -Reviewed-by: Thiago Jung Bauermann -Signed-off-by: Mark Brown ---- - arch/arm64/include/asm/el2_setup.h | 17 +++++++++++++++++ - 1 file changed, 17 insertions(+) - -diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h -index fd87c4b8f9840..36aa40c19e85e 100644 ---- a/arch/arm64/include/asm/el2_setup.h -+++ b/arch/arm64/include/asm/el2_setup.h -@@ -27,6 +27,14 @@ - ubfx x0, x0, #ID_AA64MMFR1_EL1_HCX_SHIFT, #4 - cbz x0, .Lskip_hcrx_\@ - mov_q x0, HCRX_HOST_FLAGS -+ -+ /* Enable GCS if supported */ -+ mrs_s x1, SYS_ID_AA64PFR1_EL1 -+ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 -+ cbz x1, .Lset_hcrx_\@ -+ orr x0, x0, #HCRX_EL2_GCSEn -+ -+.Lset_hcrx_\@: - msr_s SYS_HCRX_EL2, x0 - .Lskip_hcrx_\@: - .endm -@@ -191,6 +199,15 @@ - orr x0, x0, #HFGxTR_EL2_nPIR_EL1 - orr x0, x0, #HFGxTR_EL2_nPIRE0_EL1 +@@ -4560,6 +4578,9 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) -+ /* GCS depends on PIE so we don't check it if PIE is absent */ -+ mrs_s x1, SYS_ID_AA64PFR1_EL1 -+ ubfx x1, x1, #ID_AA64PFR1_EL1_GCS_SHIFT, #4 -+ cbz x1, .Lset_fgt_\@ + if (kvm_has_feat(kvm, ID_AA64MMFR3_EL1, TCRX, IMP)) + vcpu->arch.hcrx_el2 |= HCRX_EL2_TCR2En; + -+ /* Disable traps of access to GCS registers at EL0 and EL1 */ -+ orr x0, x0, #HFGxTR_EL2_nGCS_EL1_MASK -+ orr x0, x0, #HFGxTR_EL2_nGCS_EL0_MASK ++ if (kvm_has_gcs(kvm)) ++ vcpu->arch.hcrx_el2 |= HCRX_EL2_GCSEn; + } + + if (test_bit(KVM_ARCH_FLAG_FGU_INITIALIZED, &kvm->arch.flags)) +@@ -4604,6 +4625,10 @@ void kvm_calculate_traps(struct kvm_vcpu *vcpu) + kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nPIRE0_EL1 | + HFGxTR_EL2_nPIR_EL1); + ++ if (!kvm_has_gcs(kvm)) ++ kvm->arch.fgu[HFGxTR_GROUP] |= (HFGxTR_EL2_nGCS_EL0 | ++ HFGxTR_EL2_nGCS_EL1); + - .Lset_fgt_\@: - msr_s SYS_HFGRTR_EL2, x0 - msr_s SYS_HFGWTR_EL2, x0 + if (!kvm_has_feat(kvm, ID_AA64PFR0_EL1, AMU, IMP)) + kvm->arch.fgu[HAFGRTR_GROUP] |= ~(HAFGRTR_EL2_RES0 | + HAFGRTR_EL2_RES1); -- -2.34.1 +2.25.1 -From 9fbe5600495fa7acfe41e0bb9586f5102f6bf36b Mon Sep 17 00:00:00 2001 +From f54e24ad44138119021cb4cac1158969ca88eddb Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 15 Mar 2023 18:52:09 +0000 -Subject: [PATCH 26/50] arm64/idreg: Add overrride for GCS +Date: Thu, 29 Aug 2024 00:27:32 +0100 +Subject: [PATCH 16/39] arm64/idreg: Add overrride for GCS Hook up an override for GCS, allowing it to be disabled from the command line by specifying arm64.nogcs in case there are problems. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas +Acked-by: Catalin Marinas Signed-off-by: Mark Brown --- - Documentation/admin-guide/kernel-parameters.txt | 6 ++++++ + Documentation/admin-guide/kernel-parameters.txt | 3 +++ arch/arm64/kernel/pi/idreg-override.c | 2 ++ - 2 files changed, 8 insertions(+) + 2 files changed, 5 insertions(+) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt -index b600df82669db..c1151d547b812 100644 +index 09126bb8cc9f..e6413bb8e6e1 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt -@@ -437,9 +437,15 @@ +@@ -441,6 +441,9 @@ arm64.nobti [ARM64] Unconditionally disable Branch Target Identification support @@ -2628,14 +1501,8 @@ index b600df82669db..c1151d547b812 100644 arm64.nomops [ARM64] Unconditionally disable Memory Copy and Memory Set instructions support -+ arm64.nopauth [ARM64] Unconditionally disable Pointer Authentication -+ support -+ - arm64.nomte [ARM64] Unconditionally disable Memory Tagging Extension - support - diff --git a/arch/arm64/kernel/pi/idreg-override.c b/arch/arm64/kernel/pi/idreg-override.c -index 29d4b6244a6f6..2bb709d784051 100644 +index 29d4b6244a6f..2bb709d78405 100644 --- a/arch/arm64/kernel/pi/idreg-override.c +++ b/arch/arm64/kernel/pi/idreg-override.c @@ -133,6 +133,7 @@ static const struct ftr_set_desc pfr1 __prel64_initconst = { @@ -2655,17 +1522,18 @@ index 29d4b6244a6f6..2bb709d784051 100644 "id_aa64isar1.gpi=0 id_aa64isar1.gpa=0 " "id_aa64isar1.api=0 id_aa64isar1.apa=0 " -- -2.34.1 +2.25.1 -From c02d741b60e1fa1288ee7e2e89619a64b2bced3c Mon Sep 17 00:00:00 2001 +From 0acda112ee1cf97a0c40b3aa11ff885574d3cc8a Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Mon, 20 Mar 2023 18:21:38 +0000 -Subject: [PATCH 27/50] arm64/hwcap: Add hwcap for GCS +Date: Thu, 29 Aug 2024 00:27:33 +0100 +Subject: [PATCH 17/39] arm64/hwcap: Add hwcap for GCS Provide a hwcap to enable userspace to detect support for GCS. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- Documentation/arch/arm64/elf_hwcaps.rst | 2 ++ @@ -2676,7 +1544,7 @@ Signed-off-by: Mark Brown 5 files changed, 8 insertions(+) diff --git a/Documentation/arch/arm64/elf_hwcaps.rst b/Documentation/arch/arm64/elf_hwcaps.rst -index 448c1664879bc..cf87be078f33c 100644 +index 448c1664879b..cf87be078f33 100644 --- a/Documentation/arch/arm64/elf_hwcaps.rst +++ b/Documentation/arch/arm64/elf_hwcaps.rst @@ -365,6 +365,8 @@ HWCAP2_SME_SF8DP2 @@ -2689,7 +1557,7 @@ index 448c1664879bc..cf87be078f33c 100644 4. Unused AT_HWCAP bits ----------------------- diff --git a/arch/arm64/include/asm/hwcap.h b/arch/arm64/include/asm/hwcap.h -index 4edd3b61df112..fd7e162e7e393 100644 +index 4edd3b61df11..fd7e162e7e39 100644 --- a/arch/arm64/include/asm/hwcap.h +++ b/arch/arm64/include/asm/hwcap.h @@ -157,6 +157,7 @@ @@ -2701,7 +1569,7 @@ index 4edd3b61df112..fd7e162e7e393 100644 /* * This yields a mask that user programs can use to figure out what diff --git a/arch/arm64/include/uapi/asm/hwcap.h b/arch/arm64/include/uapi/asm/hwcap.h -index 285610e626f5f..328fb7843e2ff 100644 +index 285610e626f5..328fb7843e2f 100644 --- a/arch/arm64/include/uapi/asm/hwcap.h +++ b/arch/arm64/include/uapi/asm/hwcap.h @@ -122,5 +122,6 @@ @@ -2712,10 +1580,10 @@ index 285610e626f5f..328fb7843e2ff 100644 #endif /* _UAPI__ASM_HWCAP_H */ diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c -index 056d394920f9f..d2d9b0be9c5b8 100644 +index 315bd7be1106..e3e8290a4447 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c -@@ -3000,6 +3000,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { +@@ -2994,6 +2994,9 @@ static const struct arm64_cpu_capabilities arm64_elf_hwcaps[] = { HWCAP_CAP(ID_AA64ZFR0_EL1, I8MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEI8MM), HWCAP_CAP(ID_AA64ZFR0_EL1, F32MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEF32MM), HWCAP_CAP(ID_AA64ZFR0_EL1, F64MM, IMP, CAP_HWCAP, KERNEL_HWCAP_SVEF64MM), @@ -2726,7 +1594,7 @@ index 056d394920f9f..d2d9b0be9c5b8 100644 HWCAP_CAP(ID_AA64PFR1_EL1, SSBS, SSBS2, CAP_HWCAP, KERNEL_HWCAP_SSBS), #ifdef CONFIG_ARM64_BTI diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c -index 09eeaa24d4560..2f539e3101eee 100644 +index 09eeaa24d456..2f539e3101ee 100644 --- a/arch/arm64/kernel/cpuinfo.c +++ b/arch/arm64/kernel/cpuinfo.c @@ -143,6 +143,7 @@ static const char *const hwcap_str[] = { @@ -2738,13 +1606,13 @@ index 09eeaa24d4560..2f539e3101eee 100644 #ifdef CONFIG_COMPAT -- -2.34.1 +2.25.1 -From eb6dab845aa2164ccfdd36aaeaa2fc03b33c0daa Mon Sep 17 00:00:00 2001 +From 2b89824699f65e9e6f6cdf9e720c9d1dda24aca1 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 14 Apr 2023 20:57:45 +0100 -Subject: [PATCH 28/50] arm64/traps: Handle GCS exceptions +Date: Thu, 29 Aug 2024 00:27:34 +0100 +Subject: [PATCH 18/39] arm64/traps: Handle GCS exceptions A new exception code is defined for GCS specific faults other than standard load/store faults, for example GCS token validation failures, @@ -2761,6 +1629,7 @@ there but while we're at it we wire things up there, treating any GCS fault as fatal. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/esr.h | 28 +++++++++++++++++++++++++++- @@ -2770,7 +1639,7 @@ Signed-off-by: Mark Brown 4 files changed, 63 insertions(+), 1 deletion(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h -index 7abf09df70331..8982b4ab297f0 100644 +index 56c148890daf..0c231adf3867 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -51,7 +51,8 @@ @@ -2783,7 +1652,7 @@ index 7abf09df70331..8982b4ab297f0 100644 #define ESR_ELx_EC_SERROR (0x2F) #define ESR_ELx_EC_BREAKPT_LOW (0x30) #define ESR_ELx_EC_BREAKPT_CUR (0x31) -@@ -376,6 +377,31 @@ +@@ -385,6 +386,31 @@ #define ESR_ELx_MOPS_ISS_SRCREG(esr) (((esr) & (UL(0x1f) << 5)) >> 5) #define ESR_ELx_MOPS_ISS_SIZEREG(esr) (((esr) & (UL(0x1f) << 0)) >> 0) @@ -2816,7 +1685,7 @@ index 7abf09df70331..8982b4ab297f0 100644 #include diff --git a/arch/arm64/include/asm/exception.h b/arch/arm64/include/asm/exception.h -index f296662590c7f..674518464718f 100644 +index f296662590c7..674518464718 100644 --- a/arch/arm64/include/asm/exception.h +++ b/arch/arm64/include/asm/exception.h @@ -57,6 +57,8 @@ void do_el0_undef(struct pt_regs *regs, unsigned long esr); @@ -2829,7 +1698,7 @@ index f296662590c7f..674518464718f 100644 struct pt_regs *regs); void do_fpsimd_acc(unsigned long esr, struct pt_regs *regs); diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c -index b77a15955f28b..54f2d16d82f41 100644 +index b77a15955f28..54f2d16d82f4 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -463,6 +463,15 @@ static void noinstr el1_bti(struct pt_regs *regs, unsigned long esr) @@ -2884,7 +1753,7 @@ index b77a15955f28b..54f2d16d82f41 100644 case ESR_ELx_EC_SOFTSTP_LOW: case ESR_ELx_EC_WATCHPT_LOW: diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c -index 215e6d7f2df8c..fb867c6526a65 100644 +index 9e22683aa921..d410dcc12ed8 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -500,6 +500,16 @@ void do_el1_bti(struct pt_regs *regs, unsigned long esr) @@ -2913,13 +1782,13 @@ index 215e6d7f2df8c..fb867c6526a65 100644 [ESR_ELx_EC_BREAKPT_LOW] = "Breakpoint (lower EL)", [ESR_ELx_EC_BREAKPT_CUR] = "Breakpoint (current EL)", -- -2.34.1 +2.25.1 -From 8f813d26be798d51a787d246c94da595c12361f3 Mon Sep 17 00:00:00 2001 +From 1a943ef9d546c579fdbe2510b389e3a28d443a10 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 28 Apr 2023 13:59:24 +0100 -Subject: [PATCH 29/50] arm64/mm: Handle GCS data aborts +Date: Thu, 29 Aug 2024 00:27:35 +0100 +Subject: [PATCH 19/39] arm64/mm: Handle GCS data aborts All GCS operations at EL0 must happen on a page which is marked as having UnprivGCS access, including read operations. If a GCS operation @@ -2944,13 +1813,14 @@ We also report any GCS faults in VMAs not marked as part of a GCS as access violations, causing a fault to be delivered to userspace if it attempts to do GCS operations outside a GCS. +Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- - arch/arm64/mm/fault.c | 43 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 43 insertions(+) + arch/arm64/mm/fault.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c -index 451ba7cbd5adb..bdc28588163dd 100644 +index 451ba7cbd5ad..387f991e6e36 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -486,6 +486,14 @@ static void do_bad_area(unsigned long far, unsigned long esr, @@ -2968,7 +1838,7 @@ index 451ba7cbd5adb..bdc28588163dd 100644 static bool is_el0_instruction_abort(unsigned long esr) { return ESR_ELx_EC(esr) == ESR_ELx_EC_IABT_LOW; -@@ -500,6 +508,25 @@ static bool is_write_abort(unsigned long esr) +@@ -500,6 +508,23 @@ static bool is_write_abort(unsigned long esr) return (esr & ESR_ELx_WNR) && !(esr & ESR_ELx_CM); } @@ -2981,11 +1851,9 @@ index 451ba7cbd5adb..bdc28588163dd 100644 + /* GCS accesses must be performed on a GCS page */ + if (!(vma->vm_flags & VM_SHADOW_STACK)) + return true; -+ if (!(vma->vm_flags & VM_WRITE)) -+ return true; + } else if (unlikely(vma->vm_flags & VM_SHADOW_STACK)) { + /* Only GCS operations can write to a GCS page */ -+ return is_write_abort(esr); ++ return esr_is_data_abort(esr) && is_write_abort(esr); + } + + return false; @@ -2994,7 +1862,7 @@ index 451ba7cbd5adb..bdc28588163dd 100644 static int __kprobes do_page_fault(unsigned long far, unsigned long esr, struct pt_regs *regs) { -@@ -535,6 +562,14 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, +@@ -535,6 +560,14 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, /* It was exec fault */ vm_flags = VM_EXEC; mm_flags |= FAULT_FLAG_INSTRUCTION; @@ -3009,15 +1877,14 @@ index 451ba7cbd5adb..bdc28588163dd 100644 } else if (is_write_abort(esr)) { /* It was write fault */ vm_flags = VM_WRITE; -@@ -568,6 +603,14 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, +@@ -568,6 +601,13 @@ static int __kprobes do_page_fault(unsigned long far, unsigned long esr, if (!vma) goto lock_mmap; + if (is_invalid_gcs_access(vma, esr)) { -+ pr_crit("INVALID GCS\n"); + vma_end_read(vma); + fault = 0; -+ si_code = SEGV_CPERR; ++ si_code = SEGV_ACCERR; + goto bad_area; + } + @@ -3025,13 +1892,13 @@ index 451ba7cbd5adb..bdc28588163dd 100644 vma_end_read(vma); fault = 0; -- -2.34.1 +2.25.1 -From 9459935e317c9cce98477109a3af40833f631189 Mon Sep 17 00:00:00 2001 +From 56b4d84d9e40bc52c42929b29dd2f7a22668d2d9 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 12 Apr 2023 20:31:01 +0100 -Subject: [PATCH 30/50] arm64/gcs: Context switch GCS state for EL0 +Date: Thu, 29 Aug 2024 00:27:36 +0100 +Subject: [PATCH 20/39] arm64/gcs: Context switch GCS state for EL0 There are two registers controlling the GCS state of EL0, GCSPR_EL0 which is the current GCS pointer and GCSCRE0_EL1 which has enable bits for the @@ -3050,19 +1917,20 @@ facilitates reporting of GCS faults if userspace implements disabling of GCS on error - the GCS can still be discovered and examined even if GCS has been disabled. +Reviewed-by: Catalin Marinas Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- - arch/arm64/include/asm/gcs.h | 24 +++++++++++++ - arch/arm64/include/asm/processor.h | 6 ++++ - arch/arm64/kernel/process.c | 56 ++++++++++++++++++++++++++++++ + arch/arm64/include/asm/gcs.h | 24 ++++++++++++ + arch/arm64/include/asm/processor.h | 6 +++ + arch/arm64/kernel/process.c | 62 ++++++++++++++++++++++++++++++ arch/arm64/mm/Makefile | 1 + - arch/arm64/mm/gcs.c | 39 +++++++++++++++++++++ - 5 files changed, 126 insertions(+) + arch/arm64/mm/gcs.c | 39 +++++++++++++++++++ + 5 files changed, 132 insertions(+) create mode 100644 arch/arm64/mm/gcs.c diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h -index 7c5e95218db6b..04594ef59dadd 100644 +index 7c5e95218db6..04594ef59dad 100644 --- a/arch/arm64/include/asm/gcs.h +++ b/arch/arm64/include/asm/gcs.h @@ -48,4 +48,28 @@ static inline u64 gcsss2(void) @@ -3095,7 +1963,7 @@ index 7c5e95218db6b..04594ef59dadd 100644 + #endif diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h -index f77371232d8c6..c55e3600604a6 100644 +index f77371232d8c..c55e3600604a 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -184,6 +184,12 @@ struct thread_struct { @@ -3112,7 +1980,7 @@ index f77371232d8c6..c55e3600604a6 100644 static inline unsigned int thread_get_vl(struct thread_struct *thread, diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c -index 4ae31b7af6c31..5f00cb0da9c3c 100644 +index 4ae31b7af6c3..3622956b6515 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -48,6 +48,7 @@ @@ -3156,7 +2024,7 @@ index 4ae31b7af6c31..5f00cb0da9c3c 100644 } void arch_release_task_struct(struct task_struct *tsk) -@@ -471,6 +492,40 @@ static void entry_task_switch(struct task_struct *next) +@@ -471,6 +492,46 @@ static void entry_task_switch(struct task_struct *next) __this_cpu_write(__entry_task, next); } @@ -3164,8 +2032,7 @@ index 4ae31b7af6c31..5f00cb0da9c3c 100644 + +void gcs_preserve_current_state(void) +{ -+ if (task_gcs_el0_enabled(current)) -+ current->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); ++ current->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); +} + +static void gcs_thread_switch(struct task_struct *next) @@ -3173,14 +2040,21 @@ index 4ae31b7af6c31..5f00cb0da9c3c 100644 + if (!system_supports_gcs()) + return; + ++ /* GCSPR_EL0 is always readable */ + gcs_preserve_current_state(); -+ -+ gcs_set_el0_mode(next); + write_sysreg_s(next->thread.gcspr_el0, SYS_GCSPR_EL0); + ++ if (current->thread.gcs_el0_mode != next->thread.gcs_el0_mode) ++ gcs_set_el0_mode(next); ++ + /* -+ * Ensure that GCS changes are observable by/from other PEs in -+ * case of migration. ++ * Ensure that GCS memory effects of the 'prev' thread are ++ * ordered before other memory accesses with release semantics ++ * (or preceded by a DMB) on the current PE. In addition, any ++ * memory accesses with acquire semantics (or succeeded by a ++ * DMB) are ordered before GCS memory effects of the 'next' ++ * thread. This will ensure that the GCS memory effects are ++ * visible to other PEs in case of migration. + */ + if (task_gcs_el0_enabled(current) || task_gcs_el0_enabled(next)) + gcsb_dsync(); @@ -3197,7 +2071,7 @@ index 4ae31b7af6c31..5f00cb0da9c3c 100644 /* * ARM erratum 1418040 handling, affecting the 32bit view of CNTVCT. * Ensure access is disabled when switching to a 32bit task, ensure -@@ -530,6 +585,7 @@ struct task_struct *__switch_to(struct task_struct *prev, +@@ -530,6 +591,7 @@ struct task_struct *__switch_to(struct task_struct *prev, ssbs_thread_switch(next); erratum_1418040_thread_switch(next); ptrauth_thread_switch_user(next); @@ -3206,7 +2080,7 @@ index 4ae31b7af6c31..5f00cb0da9c3c 100644 /* * Complete any pending TLB or cache maintenance on this CPU in case diff --git a/arch/arm64/mm/Makefile b/arch/arm64/mm/Makefile -index 60454256945b8..1a7b3a2f21e6b 100644 +index 60454256945b..1a7b3a2f21e6 100644 --- a/arch/arm64/mm/Makefile +++ b/arch/arm64/mm/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_TRANS_TABLE) += trans_pgd.o @@ -3219,7 +2093,7 @@ index 60454256945b8..1a7b3a2f21e6b 100644 obj-$(CONFIG_KASAN) += kasan_init.o diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c new file mode 100644 -index 0000000000000..b0a67efc522bd +index 000000000000..b0a67efc522b --- /dev/null +++ b/arch/arm64/mm/gcs.c @@ -0,0 +1,39 @@ @@ -3263,22 +2137,16 @@ index 0000000000000..b0a67efc522bd + task->thread.gcs_size = 0; +} -- -2.34.1 +2.25.1 -From 94201021bb5725ce7c4fc1ad64fa84ad3706af2f Mon Sep 17 00:00:00 2001 +From 92b935bcf6458ea5d644b733420538ce9625f931 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 31 May 2023 16:39:35 +0100 -Subject: [PATCH 31/50] arm64/gcs: Ensure that new threads have a GCS +Date: Thu, 29 Aug 2024 00:27:37 +0100 +Subject: [PATCH 21/39] arm64/gcs: Ensure that new threads have a GCS When a new thread is created by a thread with GCS enabled the GCS needs -to be specified along with the regular stack. clone3() has been -extended to support this case, allowing userspace to explicitly specify -the size and location of the GCS. The specified GCS must have a valid -GCS token at the top of the stack, as though userspace were pivoting to -the new GCS. This will be consumed on use. At present we do not -atomically consume the token, this will be addressed in a future -revision. +to be specified along with the regular stack. Unfortunately plain clone() is not extensible and existing clone3() users will not specify a stack so all existing code would be broken if @@ -3290,19 +2158,19 @@ We follow the extensively discussed x86 implementation and allocate min(RLIMIT_STACK, 2G). Since the GCS only stores the call stack and not any variables this should be more than sufficient for most applications. -GCSs allocated via this mechanism will be freed when the thread exits, -those explicitly configured by the user will not. +GCSs allocated via this mechanism will be freed when the thread exits. +Reviewed-by: Catalin Marinas Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- - arch/arm64/include/asm/gcs.h | 9 +++ - arch/arm64/kernel/process.c | 29 +++++++ - arch/arm64/mm/gcs.c | 143 +++++++++++++++++++++++++++++++++++ - 3 files changed, 181 insertions(+) + arch/arm64/include/asm/gcs.h | 9 +++++ + arch/arm64/kernel/process.c | 26 ++++++++++++++ + arch/arm64/mm/gcs.c | 70 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 105 insertions(+) diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h -index 04594ef59dadd..c1f274fdb9c02 100644 +index 04594ef59dad..c1f274fdb9c0 100644 --- a/arch/arm64/include/asm/gcs.h +++ b/arch/arm64/include/asm/gcs.h @@ -8,6 +8,8 @@ @@ -3336,10 +2204,10 @@ index 04594ef59dadd..c1f274fdb9c02 100644 #endif diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c -index 5f00cb0da9c3c..d6d3a96cf2e4b 100644 +index 3622956b6515..de59aa16919c 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c -@@ -285,9 +285,32 @@ static void flush_gcs(void) +@@ -285,9 +285,29 @@ static void flush_gcs(void) write_sysreg_s(0, SYS_GCSPR_EL0); } @@ -3355,9 +2223,6 @@ index 5f00cb0da9c3c..d6d3a96cf2e4b 100644 + p->thread.gcs_el0_mode = current->thread.gcs_el0_mode; + p->thread.gcs_el0_locked = current->thread.gcs_el0_locked; + -+ /* Ensure the current state of the GCS is seen by CoW */ -+ gcsb_dsync(); -+ + return 0; +} + @@ -3372,7 +2237,7 @@ index 5f00cb0da9c3c..d6d3a96cf2e4b 100644 #endif -@@ -303,6 +326,7 @@ void flush_thread(void) +@@ -303,6 +323,7 @@ void flush_thread(void) void arch_release_task_struct(struct task_struct *tsk) { fpsimd_release_task(tsk); @@ -3380,7 +2245,7 @@ index 5f00cb0da9c3c..d6d3a96cf2e4b 100644 } int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) -@@ -366,6 +390,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) +@@ -366,6 +387,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) unsigned long stack_start = args->stack; unsigned long tls = args->tls; struct pt_regs *childregs = task_pt_regs(p); @@ -3388,7 +2253,7 @@ index 5f00cb0da9c3c..d6d3a96cf2e4b 100644 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); -@@ -407,6 +432,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) +@@ -407,6 +429,10 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args) p->thread.uw.tp_value = tls; p->thread.tpidr2_el0 = 0; } @@ -3400,15 +2265,19 @@ index 5f00cb0da9c3c..d6d3a96cf2e4b 100644 /* * A kthread has no context to ERET to, so ensure any buggy diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c -index b0a67efc522bd..4a3ce8e3bdfb5 100644 +index b0a67efc522b..6e8a5e14fff1 100644 --- a/arch/arm64/mm/gcs.c +++ b/arch/arm64/mm/gcs.c -@@ -8,6 +8,139 @@ +@@ -5,9 +5,69 @@ + #include + #include + ++#include #include ++#include #include -+static unsigned long alloc_gcs(unsigned long addr, unsigned long size, -+ unsigned long token_offset, bool set_res_tok) ++static unsigned long alloc_gcs(unsigned long addr, unsigned long size) +{ + int flags = MAP_ANONYMOUS | MAP_PRIVATE; + struct mm_struct *mm = current->mm; @@ -3418,8 +2287,8 @@ index b0a67efc522bd..4a3ce8e3bdfb5 100644 + flags |= MAP_FIXED_NOREPLACE; + + mmap_write_lock(mm); -+ mapped_addr = do_mmap(NULL, addr, size, PROT_READ | PROT_WRITE, flags, -+ VM_SHADOW_STACK, 0, &unused, NULL); ++ mapped_addr = do_mmap(NULL, addr, size, PROT_READ, flags, ++ VM_SHADOW_STACK | VM_WRITE, 0, &unused, NULL); + mmap_write_unlock(mm); + + return mapped_addr; @@ -3436,114 +2305,40 @@ index b0a67efc522bd..4a3ce8e3bdfb5 100644 + return max(PAGE_SIZE, size); +} + -+static bool gcs_consume_token(struct mm_struct *mm, unsigned long user_addr) -+{ -+ u64 expected = GCS_CAP(user_addr); -+ u64 val; -+ int ret; -+ -+ /* This should really be an atomic cpmxchg. It is not. */ -+ ret = access_remote_vm(mm, user_addr, &val, sizeof(val), -+ FOLL_FORCE); -+ if (ret != sizeof(val)) -+ return false; -+ -+ if (val != expected) -+ return false; -+ -+ val = 0; -+ ret = access_remote_vm(mm, user_addr, &val, sizeof(val), -+ FOLL_FORCE | FOLL_WRITE); -+ if (ret != sizeof(val)) -+ return false; -+ -+ return true; -+} -+ -+int arch_shstk_post_fork(struct task_struct *tsk, -+ struct kernel_clone_args *args) -+{ -+ struct mm_struct *mm; -+ unsigned long addr, size, gcspr_el0; -+ int ret = 0; -+ -+ mm = get_task_mm(tsk); -+ if (!mm) -+ return -EFAULT; -+ -+ addr = args->shadow_stack; -+ size = args->shadow_stack_size; -+ -+ /* -+ * There should be a token, and there is likely to be an optional -+ * end of stack marker above it. -+ */ -+ gcspr_el0 = addr + size - (2 * sizeof(u64)); -+ if (!gcs_consume_token(mm, gcspr_el0)) { -+ gcspr_el0 += sizeof(u64); -+ if (!gcs_consume_token(mm, gcspr_el0)) { -+ ret = -EINVAL; -+ goto out; -+ } -+ } -+ -+ tsk->thread.gcspr_el0 = gcspr_el0 + sizeof(u64); -+ -+out: -+ mmput(mm); -+ -+ return ret; -+} -+ +unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, + const struct kernel_clone_args *args) +{ + unsigned long addr, size; + -+ /* If the user specified a GCS use it. */ -+ if (args->shadow_stack_size) { -+ if (!system_supports_gcs()) -+ return (unsigned long)ERR_PTR(-EINVAL); ++ if (!system_supports_gcs()) ++ return 0; + -+ /* GCSPR_EL0 will be set up when verifying token post fork */ -+ addr = args->shadow_stack; -+ } else { ++ if (!task_gcs_el0_enabled(tsk)) ++ return 0; + -+ /* -+ * Otherwise fall back to legacy clone() support and -+ * implicitly allocate a GCS if we need a new one. -+ */ -+ -+ if (!system_supports_gcs()) -+ return 0; -+ -+ if (!task_gcs_el0_enabled(tsk)) -+ return 0; -+ -+ if ((args->flags & (CLONE_VFORK | CLONE_VM)) != CLONE_VM) { -+ tsk->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); -+ return 0; -+ } -+ -+ size = args->stack_size; -+ -+ size = gcs_size(size); -+ addr = alloc_gcs(0, size, 0, 0); -+ if (IS_ERR_VALUE(addr)) -+ return addr; -+ -+ tsk->thread.gcs_base = addr; -+ tsk->thread.gcs_size = size; -+ tsk->thread.gcspr_el0 = addr + size - sizeof(u64); ++ if ((args->flags & (CLONE_VFORK | CLONE_VM)) != CLONE_VM) { ++ tsk->thread.gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); ++ return 0; + } + ++ size = args->stack_size; ++ ++ size = gcs_size(size); ++ addr = alloc_gcs(0, size); ++ if (IS_ERR_VALUE(addr)) ++ return addr; ++ ++ tsk->thread.gcs_base = addr; ++ tsk->thread.gcs_size = size; ++ tsk->thread.gcspr_el0 = addr + size - sizeof(u64); ++ + return addr; +} + /* * Apply the GCS mode configured for the specified task to the * hardware. -@@ -30,6 +163,16 @@ void gcs_set_el0_mode(struct task_struct *task) +@@ -30,6 +90,16 @@ void gcs_set_el0_mode(struct task_struct *task) void gcs_free(struct task_struct *task) { @@ -3561,15 +2356,15 @@ index b0a67efc522bd..4a3ce8e3bdfb5 100644 vm_munmap(task->thread.gcs_base, task->thread.gcs_size); -- -2.34.1 +2.25.1 -From a5e6f0bb2817dc6431f147da6b0fcde5191c342a Mon Sep 17 00:00:00 2001 +From aa638d2030c080e7cf864cb94a1dba281653683d Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 5 Apr 2023 20:14:17 +0100 -Subject: [PATCH 32/50] arm64/gcs: Implement shadow stack prctl() interface +Date: Thu, 29 Aug 2024 00:27:38 +0100 +Subject: [PATCH 22/39] arm64/gcs: Implement shadow stack prctl() interface -Implement the architecture neutral prtctl() interface for setting the +Implement the architecture neutral prctl() interface for setting the shadow stack status, this supports setting and reading the current GCS configuration for the current thread. @@ -3599,15 +2394,16 @@ on the GCS attempts to reenable GCS after this are rejected. This can be revisted if a use case arises. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - arch/arm64/include/asm/gcs.h | 22 ++++++++ + arch/arm64/include/asm/gcs.h | 22 +++++++++ arch/arm64/include/asm/processor.h | 1 + - arch/arm64/mm/gcs.c | 81 ++++++++++++++++++++++++++++++ - 3 files changed, 104 insertions(+) + arch/arm64/mm/gcs.c | 79 ++++++++++++++++++++++++++++++ + 3 files changed, 102 insertions(+) diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h -index c1f274fdb9c02..48c97e63e56a1 100644 +index c1f274fdb9c0..48c97e63e56a 100644 --- a/arch/arm64/include/asm/gcs.h +++ b/arch/arm64/include/asm/gcs.h @@ -50,6 +50,9 @@ static inline u64 gcsss2(void) @@ -3654,7 +2450,7 @@ index c1f274fdb9c02..48c97e63e56a1 100644 #endif diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h -index c55e3600604a6..58eb48cd539fa 100644 +index c55e3600604a..58eb48cd539f 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -186,6 +186,7 @@ struct thread_struct { @@ -3666,10 +2462,10 @@ index c55e3600604a6..58eb48cd539fa 100644 u64 gcs_base; u64 gcs_size; diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c -index 4a3ce8e3bdfb5..c6fae0eb9bd6e 100644 +index 6e8a5e14fff1..979e02cece93 100644 --- a/arch/arm64/mm/gcs.c +++ b/arch/arm64/mm/gcs.c -@@ -180,3 +180,84 @@ void gcs_free(struct task_struct *task) +@@ -107,3 +107,82 @@ void gcs_free(struct task_struct *task) task->thread.gcs_base = 0; task->thread.gcs_size = 0; } @@ -3694,28 +2490,26 @@ index 4a3ce8e3bdfb5..c6fae0eb9bd6e 100644 + return ret; + + /* If we are enabling GCS then make sure we have a stack */ -+ if (arg & PR_SHADOW_STACK_ENABLE) { -+ if (!task_gcs_el0_enabled(task)) { -+ /* Do not allow GCS to be reenabled */ -+ if (task->thread.gcs_base) -+ return -EINVAL; ++ if (arg & PR_SHADOW_STACK_ENABLE && ++ !task_gcs_el0_enabled(task)) { ++ /* Do not allow GCS to be reenabled */ ++ if (task->thread.gcs_base || task->thread.gcspr_el0) ++ return -EINVAL; + -+ if (task != current) -+ return -EBUSY; ++ if (task != current) ++ return -EBUSY; + -+ size = gcs_size(0); -+ gcs = alloc_gcs(0, size, 0, 0); -+ if (!gcs) -+ return -ENOMEM; ++ size = gcs_size(0); ++ gcs = alloc_gcs(0, size); ++ if (!gcs) ++ return -ENOMEM; + -+ task->thread.gcspr_el0 = gcs + size - sizeof(u64); -+ task->thread.gcs_base = gcs; -+ task->thread.gcs_size = size; -+ if (task == current) -+ write_sysreg_s(task->thread.gcspr_el0, -+ SYS_GCSPR_EL0); -+ -+ } ++ task->thread.gcspr_el0 = gcs + size - sizeof(u64); ++ task->thread.gcs_base = gcs; ++ task->thread.gcs_size = size; ++ if (task == current) ++ write_sysreg_s(task->thread.gcspr_el0, ++ SYS_GCSPR_EL0); + } + + task->thread.gcs_el0_mode = arg; @@ -3755,13 +2549,13 @@ index 4a3ce8e3bdfb5..c6fae0eb9bd6e 100644 + return 0; +} -- -2.34.1 +2.25.1 -From a4d14ce3b48a9fbaf54f427724e236c4573e9e08 Mon Sep 17 00:00:00 2001 +From 1b862f36fbfa6199eded2c6a0d8c334353c230d3 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 12 Apr 2023 22:29:17 +0100 -Subject: [PATCH 33/50] arm64/mm: Implement map_shadow_stack() +Date: Thu, 29 Aug 2024 00:27:39 +0100 +Subject: [PATCH 23/39] arm64/mm: Implement map_shadow_stack() As discussed extensively in the changelog for the addition of this syscall on x86 ("x86/shstk: Introduce map_shadow_stack syscall") the @@ -3780,16 +2574,17 @@ NULL pointer it is indistinguishable from not initialising anything by itself. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - arch/arm64/mm/gcs.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 61 insertions(+) + arch/arm64/mm/gcs.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 64 insertions(+) diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c -index c6fae0eb9bd6e..918d50ba53c6e 100644 +index 979e02cece93..cdd4a9d7ff7d 100644 --- a/arch/arm64/mm/gcs.c +++ b/arch/arm64/mm/gcs.c -@@ -141,6 +141,67 @@ unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, +@@ -68,6 +68,70 @@ unsigned long gcs_alloc_thread_stack(struct task_struct *tsk, return addr; } @@ -3807,10 +2602,10 @@ index c6fae0eb9bd6e..918d50ba53c6e 100644 + if (flags & ~(SHADOW_STACK_SET_TOKEN | SHADOW_STACK_SET_MARKER)) + return -EINVAL; + -+ if (addr && (addr % PAGE_SIZE)) ++ if (!PAGE_ALIGNED(addr)) + return -EINVAL; + -+ if (size == 8 || size % 8) ++ if (size == 8 || !IS_ALIGNED(size, 8)) + return -EINVAL; + + /* @@ -3822,7 +2617,7 @@ index c6fae0eb9bd6e..918d50ba53c6e 100644 + if (alloc_size < size) + return -EOVERFLOW; + -+ addr = alloc_gcs(addr, alloc_size, 0, false); ++ addr = alloc_gcs(addr, alloc_size); + if (IS_ERR_VALUE(addr)) + return addr; + @@ -3847,7 +2642,10 @@ index c6fae0eb9bd6e..918d50ba53c6e 100644 + return -EFAULT; + } + -+ /* Ensure the new cap is viaible for GCS */ ++ /* ++ * Ensure the new cap is ordered before standard ++ * memory accesses to the same location. ++ */ + gcsb_dsync(); + } + @@ -3858,13 +2656,13 @@ index c6fae0eb9bd6e..918d50ba53c6e 100644 * Apply the GCS mode configured for the specified task to the * hardware. -- -2.34.1 +2.25.1 -From 2e78d70d45d8206fdb7a29907fbbad5055c8a0a3 Mon Sep 17 00:00:00 2001 +From 1df79dc2cbe7cae4b28b701dba6933b391ea1797 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 21 Jun 2023 01:28:09 +0100 -Subject: [PATCH 34/50] arm64/signal: Set up and restore the GCS context for +Date: Thu, 29 Aug 2024 00:27:40 +0100 +Subject: [PATCH 24/39] arm64/signal: Set up and restore the GCS context for signal handlers When invoking a signal handler we use the GCS configuration and stack @@ -3886,15 +2684,15 @@ bit being set and the token type mean that this can't be interpreted as a valid token or address. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- arch/arm64/include/asm/gcs.h | 1 + - arch/arm64/kernel/signal.c | 134 +++++++++++++++++++++++++++++++++-- - arch/arm64/mm/gcs.c | 1 + - 3 files changed, 131 insertions(+), 5 deletions(-) + arch/arm64/kernel/signal.c | 118 +++++++++++++++++++++++++++++++++-- + 2 files changed, 114 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/gcs.h b/arch/arm64/include/asm/gcs.h -index 48c97e63e56a1..f50660603ecf5 100644 +index 48c97e63e56a..f50660603ecf 100644 --- a/arch/arm64/include/asm/gcs.h +++ b/arch/arm64/include/asm/gcs.h @@ -9,6 +9,7 @@ @@ -3906,7 +2704,7 @@ index 48c97e63e56a1..f50660603ecf5 100644 static inline void gcsb_dsync(void) { diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c -index 4a77f4976e116..a1e0aa38bff9c 100644 +index 4a77f4976e11..3f52ce11f791 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -25,6 +25,7 @@ @@ -3917,52 +2715,31 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 #include #include #include -@@ -34,6 +35,37 @@ +@@ -34,6 +35,15 @@ #include #include +#ifdef CONFIG_ARM64_GCS -+/* Extra bit set in the address distinguishing a signal cap token. */ -+#define GCS_SIGNAL_CAP_FLAG BIT(63) -+ -+#define GCS_SIGNAL_CAP(addr) ((((unsigned long)addr) & GCS_CAP_ADDR_MASK) | \ -+ GCS_SIGNAL_CAP_FLAG) ++#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK) + +static bool gcs_signal_cap_valid(u64 addr, u64 val) +{ -+ /* -+ * The top bit should be set, this is an invalid address for -+ * EL0 and will only be set for caps created by signals. -+ */ -+ if (!(val & GCS_SIGNAL_CAP_FLAG)) -+ return false; -+ -+ /* The rest should be a standard architectural cap token. */ -+ val &= ~GCS_SIGNAL_CAP_FLAG; -+ -+ /* The cap must not have a token set */ -+ if (GCS_CAP_TOKEN(val) != 0) -+ return false; -+ -+ /* The cap must store the VA the cap was stored at */ -+ if (GCS_CAP_ADDR(addr) != GCS_CAP_ADDR(val)) -+ return false; -+ -+ return true; ++ return val == GCS_SIGNAL_CAP(addr); +} +#endif + /* * Do a signal return; undo the signal stack. These are aligned to 128-bit. */ -@@ -860,6 +892,50 @@ static int restore_sigframe(struct pt_regs *regs, +@@ -860,6 +870,58 @@ static int restore_sigframe(struct pt_regs *regs, return err; } +#ifdef CONFIG_ARM64_GCS +static int gcs_restore_signal(void) +{ -+ u64 gcspr_el0, cap; ++ unsigned long __user *gcspr_el0; ++ u64 cap; + int ret; + + if (!system_supports_gcs()) @@ -3971,21 +2748,29 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 + if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE)) + return 0; + -+ gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0); ++ gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0); + + /* -+ * GCSPR_EL0 should be pointing at a capped GCS, read the cap... ++ * Ensure that any changes to the GCS done via GCS operations ++ * are visible to the normal reads we do to validate the ++ * token. + */ + gcsb_dsync(); -+ ret = copy_from_user(&cap, (__user void*)gcspr_el0, sizeof(cap)); ++ ++ /* ++ * GCSPR_EL0 should be pointing at a capped GCS, read the cap. ++ * We don't enforce that this is in a GCS page, if it is not ++ * then faults will be generated on GCS operations - the main ++ * concern is to protect GCS pages. ++ */ ++ ret = copy_from_user(&cap, gcspr_el0, sizeof(cap)); + if (ret) + return -EFAULT; + + /* -+ * ...then check that the cap is the actual GCS before -+ * restoring it. ++ * Check that the cap is the actual GCS before replacing it. + */ -+ if (!gcs_signal_cap_valid(gcspr_el0, cap)) ++ if (!gcs_signal_cap_valid((u64)gcspr_el0, cap)) + return -EINVAL; + + /* Invalidate the token to prevent reuse */ @@ -3993,8 +2778,7 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 + if (ret != 0) + return -EFAULT; + -+ current->thread.gcspr_el0 = gcspr_el0 + sizeof(cap); -+ write_sysreg_s(current->thread.gcspr_el0, SYS_GCSPR_EL0); ++ write_sysreg_s(gcspr_el0 + 1, SYS_GCSPR_EL0); + + return 0; +} @@ -4006,17 +2790,17 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 SYSCALL_DEFINE0(rt_sigreturn) { struct pt_regs *regs = current_pt_regs(); -@@ -886,6 +962,9 @@ SYSCALL_DEFINE0(rt_sigreturn) - if (restore_altstack(&frame->uc.uc_stack)) +@@ -883,6 +945,9 @@ SYSCALL_DEFINE0(rt_sigreturn) + if (restore_sigframe(regs, frame)) goto badframe; + if (gcs_restore_signal()) + goto badframe; + - return regs->regs[0]; + if (restore_altstack(&frame->uc.uc_stack)) + goto badframe; - badframe: -@@ -1130,7 +1209,50 @@ static int get_sigframe(struct rt_sigframe_user_layout *user, +@@ -1130,7 +1195,48 @@ static int get_sigframe(struct rt_sigframe_user_layout *user, return 0; } @@ -4048,8 +2832,6 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 + if (ret != 0) + return ret; + -+ gcsb_dsync(); -+ + gcspr_el0 -= 2; + write_sysreg_s((unsigned long)gcspr_el0, SYS_GCSPR_EL0); + @@ -4068,7 +2850,7 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 struct rt_sigframe_user_layout *user, int usig) { __sigrestore_t sigtramp; -@@ -1138,7 +1260,7 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, +@@ -1138,7 +1244,7 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, regs->regs[0] = usig; regs->sp = (unsigned long)user->sigframe; regs->regs[29] = (unsigned long)&user->next_frame->fp; @@ -4077,7 +2859,7 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 /* * Signal delivery is a (wacky) indirect function call in -@@ -1178,12 +1300,14 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, +@@ -1178,12 +1284,14 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka, sme_smstop(); } @@ -4094,7 +2876,7 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 } static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, -@@ -1206,7 +1330,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, +@@ -1206,7 +1314,7 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set, err |= __save_altstack(&frame->uc.uc_stack, regs->sp); err |= setup_sigframe(&user, regs, set); if (err == 0) { @@ -4103,26 +2885,14 @@ index 4a77f4976e116..a1e0aa38bff9c 100644 if (ksig->ka.sa.sa_flags & SA_SIGINFO) { err |= copy_siginfo_to_user(&frame->info, &ksig->info); regs->regs[1] = (unsigned long)&frame->info; -diff --git a/arch/arm64/mm/gcs.c b/arch/arm64/mm/gcs.c -index 918d50ba53c6e..7429a4b3600ef 100644 ---- a/arch/arm64/mm/gcs.c -+++ b/arch/arm64/mm/gcs.c -@@ -6,6 +6,7 @@ - #include - - #include -+#include - #include - - static unsigned long alloc_gcs(unsigned long addr, unsigned long size, -- -2.34.1 +2.25.1 -From 5be3b7263dc3ba69030803a046e59269356afb6a Mon Sep 17 00:00:00 2001 +From 5555205dc78b9792577d5b25ce03fb166b9f41ba Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Thu, 1 Jun 2023 16:35:46 +0100 -Subject: [PATCH 35/50] arm64/signal: Expose GCS state in signal frames +Date: Thu, 29 Aug 2024 00:27:41 +0100 +Subject: [PATCH 25/39] arm64/signal: Expose GCS state in signal frames Add a context for the GCS state and include it in the signal context when running on a system that supports GCS. We reuse the same flags that the @@ -4134,15 +2904,14 @@ between specifying GCSPR_EL0 and allocation of a new GCS and this is not an ancticipated use case. We also enforce GCS configuration locking on signal return. -Reviewed-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- arch/arm64/include/uapi/asm/sigcontext.h | 9 ++ - arch/arm64/kernel/signal.c | 108 +++++++++++++++++++++++ - 2 files changed, 117 insertions(+) + arch/arm64/kernel/signal.c | 109 +++++++++++++++++++++++ + 2 files changed, 118 insertions(+) diff --git a/arch/arm64/include/uapi/asm/sigcontext.h b/arch/arm64/include/uapi/asm/sigcontext.h -index 8a45b7a411e04..c2d61e8efc846 100644 +index 8a45b7a411e0..c2d61e8efc84 100644 --- a/arch/arm64/include/uapi/asm/sigcontext.h +++ b/arch/arm64/include/uapi/asm/sigcontext.h @@ -176,6 +176,15 @@ struct zt_context { @@ -4162,10 +2931,10 @@ index 8a45b7a411e04..c2d61e8efc846 100644 #include diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c -index a1e0aa38bff9c..f034a1a1d194d 100644 +index 3f52ce11f791..dd2ed27b8bdd 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c -@@ -88,6 +88,7 @@ struct rt_sigframe_user_layout { +@@ -66,6 +66,7 @@ struct rt_sigframe_user_layout { unsigned long fpsimd_offset; unsigned long esr_offset; @@ -4173,7 +2942,7 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 unsigned long sve_offset; unsigned long tpidr2_offset; unsigned long za_offset; -@@ -217,6 +218,8 @@ struct user_ctxs { +@@ -195,6 +196,8 @@ struct user_ctxs { u32 zt_size; struct fpmr_context __user *fpmr; u32 fpmr_size; @@ -4182,7 +2951,7 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 }; static int preserve_fpsimd_context(struct fpsimd_context __user *ctx) -@@ -636,6 +639,83 @@ extern int restore_zt_context(struct user_ctxs *user); +@@ -614,6 +617,82 @@ extern int restore_zt_context(struct user_ctxs *user); #endif /* ! CONFIG_ARM64_SME */ @@ -4191,15 +2960,15 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 +static int preserve_gcs_context(struct gcs_context __user *ctx) +{ + int err = 0; -+ u64 gcspr; ++ u64 gcspr = read_sysreg_s(SYS_GCSPR_EL0); + + /* -+ * We will add a cap token to the frame, include it in the -+ * GCSPR_EL0 we report to support stack switching via -+ * sigreturn. ++ * If GCS is enabled we will add a cap token to the frame, ++ * include it in the GCSPR_EL0 we report to support stack ++ * switching via sigreturn if GCS is enabled. We do not allow ++ * enabling via sigreturn so the token is only relevant for ++ * threads with GCS enabled. + */ -+ gcs_preserve_current_state(); -+ gcspr = current->thread.gcspr_el0; + if (task_gcs_el0_enabled(current)) + gcspr -= 8; + @@ -4249,8 +3018,7 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 + * We let userspace set GCSPR_EL0 to anything here, we will + * validate later in gcs_restore_signal(). + */ -+ current->thread.gcspr_el0 = gcspr; -+ write_sysreg_s(current->thread.gcspr_el0, SYS_GCSPR_EL0); ++ write_sysreg_s(gcspr, SYS_GCSPR_EL0); + + return 0; +} @@ -4266,7 +3034,7 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 static int parse_user_sigframe(struct user_ctxs *user, struct rt_sigframe __user *sf) { -@@ -653,6 +733,7 @@ static int parse_user_sigframe(struct user_ctxs *user, +@@ -631,6 +710,7 @@ static int parse_user_sigframe(struct user_ctxs *user, user->za = NULL; user->zt = NULL; user->fpmr = NULL; @@ -4274,7 +3042,7 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 if (!IS_ALIGNED((unsigned long)base, 16)) goto invalid; -@@ -758,6 +839,17 @@ static int parse_user_sigframe(struct user_ctxs *user, +@@ -736,6 +816,17 @@ static int parse_user_sigframe(struct user_ctxs *user, user->fpmr_size = size; break; @@ -4292,7 +3060,7 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 case EXTRA_MAGIC: if (have_extra_context) goto invalid; -@@ -877,6 +969,9 @@ static int restore_sigframe(struct pt_regs *regs, +@@ -855,6 +946,9 @@ static int restore_sigframe(struct pt_regs *regs, err = restore_fpsimd_context(&user); } @@ -4302,21 +3070,23 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 if (err == 0 && system_supports_tpidr2() && user.tpidr2) err = restore_tpidr2_context(&user); -@@ -999,6 +1094,13 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, +@@ -985,6 +1079,15 @@ static int setup_sigframe_layout(struct rt_sigframe_user_layout *user, return err; } -+ if (system_supports_gcs()) { ++#ifdef CONFIG_ARM64_GCS ++ if (add_all || current->thread.gcspr_el0) { + err = sigframe_alloc(user, &user->gcs_offset, + sizeof(struct gcs_context)); + if (err) + return err; + } ++#endif + if (system_supports_sve() || system_supports_sme()) { unsigned int vq = 0; -@@ -1099,6 +1201,12 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, +@@ -1085,6 +1188,12 @@ static int setup_sigframe(struct rt_sigframe_user_layout *user, __put_user_error(current->thread.fault_code, &esr_ctx->esr, err); } @@ -4330,13 +3100,13 @@ index a1e0aa38bff9c..f034a1a1d194d 100644 if ((system_supports_sve() || system_supports_sme()) && err == 0 && user->sve_offset) { -- -2.34.1 +2.25.1 -From b48da28b3cdf986270a29a849cd069e5dfcf55c3 Mon Sep 17 00:00:00 2001 +From e36521a4ccbf7f808eebab83f26cb57a15b030d6 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 30 Jun 2023 17:32:38 +0100 -Subject: [PATCH 36/50] arm64/ptrace: Expose GCS via ptrace and core files +Date: Thu, 29 Aug 2024 00:27:42 +0100 +Subject: [PATCH 26/39] arm64/ptrace: Expose GCS via ptrace and core files Provide a new register type NT_ARM_GCS reporting the current GCS mode and pointer for EL0. Due to the interactions with allocation and @@ -4344,15 +3114,16 @@ deallocation of Guarded Control Stacks we do not permit any changes to the GCS mode via ptrace, only GCSPR_EL0 may be changed. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - arch/arm64/include/uapi/asm/ptrace.h | 8 ++++ - arch/arm64/kernel/ptrace.c | 59 ++++++++++++++++++++++++++++ + arch/arm64/include/uapi/asm/ptrace.h | 8 +++++ + arch/arm64/kernel/ptrace.c | 54 ++++++++++++++++++++++++++++ include/uapi/linux/elf.h | 1 + - 3 files changed, 68 insertions(+) + 3 files changed, 63 insertions(+) diff --git a/arch/arm64/include/uapi/asm/ptrace.h b/arch/arm64/include/uapi/asm/ptrace.h -index 7fa2f7036aa78..0f39ba4f3efd4 100644 +index 7fa2f7036aa7..0f39ba4f3efd 100644 --- a/arch/arm64/include/uapi/asm/ptrace.h +++ b/arch/arm64/include/uapi/asm/ptrace.h @@ -324,6 +324,14 @@ struct user_za_header { @@ -4371,7 +3142,7 @@ index 7fa2f7036aa78..0f39ba4f3efd4 100644 #endif /* _UAPI__ASM_PTRACE_H */ diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c -index 0d022599eb61b..9db0b669fee3c 100644 +index 0d022599eb61..88f525b0c4fb 100644 --- a/arch/arm64/kernel/ptrace.c +++ b/arch/arm64/kernel/ptrace.c @@ -34,6 +34,7 @@ @@ -4382,7 +3153,7 @@ index 0d022599eb61b..9db0b669fee3c 100644 #include #include #include -@@ -1440,6 +1441,51 @@ static int tagged_addr_ctrl_set(struct task_struct *target, const struct +@@ -1440,6 +1441,46 @@ static int tagged_addr_ctrl_set(struct task_struct *target, const struct } #endif @@ -4418,11 +3189,6 @@ index 0d022599eb61b..9db0b669fee3c 100644 + if (user_gcs.features_enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK) + return -EINVAL; + -+ /* Do not allow enable via ptrace */ -+ if ((user_gcs.features_enabled & PR_SHADOW_STACK_ENABLE) && -+ !(target->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE)) -+ return -EBUSY; -+ + target->thread.gcs_el0_mode = user_gcs.features_enabled; + target->thread.gcs_el0_locked = user_gcs.features_locked; + target->thread.gcspr_el0 = user_gcs.gcspr_el0; @@ -4434,7 +3200,7 @@ index 0d022599eb61b..9db0b669fee3c 100644 enum aarch64_regset { REGSET_GPR, REGSET_FPR, -@@ -1469,6 +1515,9 @@ enum aarch64_regset { +@@ -1469,6 +1510,9 @@ enum aarch64_regset { #ifdef CONFIG_ARM64_TAGGED_ADDR_ABI REGSET_TAGGED_ADDR_CTRL, #endif @@ -4444,7 +3210,7 @@ index 0d022599eb61b..9db0b669fee3c 100644 }; static const struct user_regset aarch64_regsets[] = { -@@ -1628,6 +1677,16 @@ static const struct user_regset aarch64_regsets[] = { +@@ -1628,6 +1672,16 @@ static const struct user_regset aarch64_regsets[] = { .set = tagged_addr_ctrl_set, }, #endif @@ -4462,7 +3228,7 @@ index 0d022599eb61b..9db0b669fee3c 100644 static const struct user_regset_view user_aarch64_view = { diff --git a/include/uapi/linux/elf.h b/include/uapi/linux/elf.h -index b54b313bcf073..77d4910bbb9d4 100644 +index b54b313bcf07..77d4910bbb9d 100644 --- a/include/uapi/linux/elf.h +++ b/include/uapi/linux/elf.h @@ -441,6 +441,7 @@ typedef struct elf64_shdr { @@ -4474,28 +3240,29 @@ index b54b313bcf073..77d4910bbb9d4 100644 #define NT_VMCOREDD 0x700 /* Vmcore Device Dump Note */ #define NT_MIPS_DSP 0x800 /* MIPS DSP ASE registers */ -- -2.34.1 +2.25.1 -From f6f628d7c414048386c57f0870496b27acaa8da1 Mon Sep 17 00:00:00 2001 +From f688007f56a31dd255a1c05a3e374dffb6288e96 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Tue, 7 Mar 2023 22:34:05 +0000 -Subject: [PATCH 37/50] arm64: Add Kconfig for Guarded Control Stack (GCS) +Date: Thu, 29 Aug 2024 00:27:43 +0100 +Subject: [PATCH 27/39] arm64: Add Kconfig for Guarded Control Stack (GCS) Provide a Kconfig option allowing the user to select if GCS support is built into the kernel. Reviewed-by: Thiago Jung Bauermann +Reviewed-by: Catalin Marinas Signed-off-by: Mark Brown --- - arch/arm64/Kconfig | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) + arch/arm64/Kconfig | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig -index 5d91259ee7b53..248697a29d78f 100644 +index a2f8ff354ca6..3fa682151c8f 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig -@@ -2140,6 +2140,26 @@ config ARM64_EPAN +@@ -2137,6 +2137,27 @@ config ARM64_EPAN if the cpu does not implement the feature. endmenu # "ARMv8.7 architectural features" @@ -4506,6 +3273,7 @@ index 5d91259ee7b53..248697a29d78f 100644 + default y + select ARCH_HAS_USER_SHADOW_STACK + select ARCH_USES_HIGH_VMA_FLAGS ++ depends on !UPROBES + help + Guarded Control Stack (GCS) provides support for a separate + stack with restricted access which contains only return @@ -4523,25 +3291,26 @@ index 5d91259ee7b53..248697a29d78f 100644 bool "ARM Scalable Vector Extension support" default y -- -2.34.1 +2.25.1 -From c956d4219534a96438827172ade46716d821183d Mon Sep 17 00:00:00 2001 +From a6a3aaa7a78f7dfcee004e1323dd3b1f9f1bcd9b Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Mon, 20 Mar 2023 18:24:51 +0000 -Subject: [PATCH 38/50] kselftest/arm64: Verify the GCS hwcap +Date: Thu, 29 Aug 2024 00:27:44 +0100 +Subject: [PATCH 28/39] kselftest/arm64: Verify the GCS hwcap Add coverage of the GCS hwcap to the hwcap selftest, using a read of GCSPR_EL0 to generate SIGILL without having to worry about enabling GCS. Reviewed-by: Thiago Jung Bauermann +Tested-by: Thiago Jung Bauermann Signed-off-by: Mark Brown --- tools/testing/selftests/arm64/abi/hwcap.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tools/testing/selftests/arm64/abi/hwcap.c b/tools/testing/selftests/arm64/abi/hwcap.c -index d8909b2b535a0..dc54ae894fe52 100644 +index d8909b2b535a..dc54ae894fe5 100644 --- a/tools/testing/selftests/arm64/abi/hwcap.c +++ b/tools/testing/selftests/arm64/abi/hwcap.c @@ -98,6 +98,17 @@ static void fpmr_sigill(void) @@ -4578,133 +3347,13 @@ index d8909b2b535a0..dc54ae894fe52 100644 .name = "JSCVT", .at_hwcap = AT_HWCAP, -- -2.34.1 +2.25.1 -From 6924204da3520cd2d6a9548b1806f6146372a8bb Mon Sep 17 00:00:00 2001 +From d232591797d14e9c8accbd2bb3a6c105e8733224 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Mon, 29 Jan 2024 22:45:01 +0000 -Subject: [PATCH 39/50] kselftest: Provide shadow stack enable helpers for - arm64 - -Allow test programs to use the shadow stack helpers on arm64. - -Reviewed-by: Thiago Jung Bauermann -Signed-off-by: Mark Brown ---- - tools/testing/selftests/ksft_shstk.h | 37 ++++++++++++++++++++++++++++ - 1 file changed, 37 insertions(+) - -diff --git a/tools/testing/selftests/ksft_shstk.h b/tools/testing/selftests/ksft_shstk.h -index 85d0747c18022..302957a0bbd5f 100644 ---- a/tools/testing/selftests/ksft_shstk.h -+++ b/tools/testing/selftests/ksft_shstk.h -@@ -50,6 +50,43 @@ static inline __attribute__((always_inline)) void enable_shadow_stack(void) - - #endif - -+#ifdef __aarch64__ -+#define PR_SET_SHADOW_STACK_STATUS 75 -+# define PR_SHADOW_STACK_ENABLE (1UL << 0) -+ -+#define my_syscall2(num, arg1, arg2) \ -+({ \ -+ register long _num __asm__ ("x8") = (num); \ -+ register long _arg1 __asm__ ("x0") = (long)(arg1); \ -+ register long _arg2 __asm__ ("x1") = (long)(arg2); \ -+ register long _arg3 __asm__ ("x2") = 0; \ -+ register long _arg4 __asm__ ("x3") = 0; \ -+ register long _arg5 __asm__ ("x4") = 0; \ -+ \ -+ __asm__ volatile ( \ -+ "svc #0\n" \ -+ : "=r"(_arg1) \ -+ : "r"(_arg1), "r"(_arg2), \ -+ "r"(_arg3), "r"(_arg4), \ -+ "r"(_arg5), "r"(_num) \ -+ : "memory", "cc" \ -+ ); \ -+ _arg1; \ -+}) -+ -+#define ENABLE_SHADOW_STACK -+static inline __attribute__((always_inline)) void enable_shadow_stack(void) -+{ -+ int ret; -+ -+ ret = my_syscall2(__NR_prctl, PR_SET_SHADOW_STACK_STATUS, -+ PR_SHADOW_STACK_ENABLE); -+ if (ret == 0) -+ shadow_stack_enabled = true; -+} -+ -+#endif -+ - #ifndef __NR_map_shadow_stack - #define __NR_map_shadow_stack 453 - #endif --- -2.34.1 - - -From 0fa89bf3d122e8b4f2aa34b2e108ec4bbfdc5fab Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 19 Jun 2024 19:11:03 +0100 -Subject: [PATCH 40/50] selftests/clone3: Enable arm64 shadow stack testing - -In order to test shadow stack support in clone3() the clone3() selftests -need to have a fully inline clone3() call, provide one for arm64. - -Signed-off-by: Mark Brown ---- - .../selftests/clone3/clone3_selftests.h | 26 +++++++++++++++++++ - 1 file changed, 26 insertions(+) - -diff --git a/tools/testing/selftests/clone3/clone3_selftests.h b/tools/testing/selftests/clone3/clone3_selftests.h -index 38d82934668a8..e329150853335 100644 ---- a/tools/testing/selftests/clone3/clone3_selftests.h -+++ b/tools/testing/selftests/clone3/clone3_selftests.h -@@ -69,6 +69,32 @@ static pid_t __always_inline sys_clone3(struct __clone_args *args, size_t size) - - return ret; - } -+#elif defined(__aarch64__) -+static pid_t __always_inline sys_clone3(struct __clone_args *args, size_t size) -+{ -+ register long _num __asm__ ("x8") = __NR_clone3; -+ register long _args __asm__ ("x0") = (long)(args); -+ register long _size __asm__ ("x1") = (long)(size); -+ register long arg2 __asm__ ("x2") = 0; -+ register long arg3 __asm__ ("x3") = 0; -+ register long arg4 __asm__ ("x4") = 0; -+ -+ __asm__ volatile ( -+ "svc #0\n" -+ : "=r"(_args) -+ : "r"(_args), "r"(_size), -+ "r"(_num), "r"(arg2), -+ "r"(arg3), "r"(arg4) -+ : "memory", "cc" -+ ); -+ -+ if ((int)_args < 0) { -+ errno = -((int)_args); -+ return -1; -+ } -+ -+ return _args; -+} - #else - static pid_t sys_clone3(struct __clone_args *args, size_t size) - { --- -2.34.1 - - -From 4b7b22a1e1f5de060cdc9b5cf3719314c32c5467 Mon Sep 17 00:00:00 2001 -From: Mark Brown -Date: Wed, 26 Apr 2023 19:05:43 +0100 -Subject: [PATCH 41/50] kselftest/arm64: Add GCS as a detected feature in the +Date: Thu, 29 Aug 2024 00:27:45 +0100 +Subject: [PATCH 29/39] kselftest/arm64: Add GCS as a detected feature in the signal tests In preparation for testing GCS related signal handling add it as a feature @@ -4718,7 +3367,7 @@ Signed-off-by: Mark Brown 2 files changed, 5 insertions(+) diff --git a/tools/testing/selftests/arm64/signal/test_signals.h b/tools/testing/selftests/arm64/signal/test_signals.h -index 1e6273d815759..7ada43688c024 100644 +index 1e6273d81575..7ada43688c02 100644 --- a/tools/testing/selftests/arm64/signal/test_signals.h +++ b/tools/testing/selftests/arm64/signal/test_signals.h @@ -35,6 +35,7 @@ enum { @@ -4738,7 +3387,7 @@ index 1e6273d815759..7ada43688c024 100644 /* * A descriptor used to describe and configure a test case. diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c -index 0dc948db3a4a4..89ef95c1af0eb 100644 +index 0dc948db3a4a..89ef95c1af0e 100644 --- a/tools/testing/selftests/arm64/signal/test_signals_utils.c +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c @@ -30,6 +30,7 @@ static char const *const feats_names[FMAX_END] = { @@ -4759,13 +3408,13 @@ index 0dc948db3a4a4..89ef95c1af0eb 100644 if (td->feats_required & td->feats_supported) fprintf(stderr, -- -2.34.1 +2.25.1 -From 76863aabcb6b172447f6d85b01496a5971c83c4e Mon Sep 17 00:00:00 2001 +From 35c142cde687d6c5b06707c19dd8bc4aeee50366 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Thu, 1 Jun 2023 17:52:08 +0100 -Subject: [PATCH 42/50] kselftest/arm64: Add framework support for GCS to +Date: Thu, 29 Aug 2024 00:27:46 +0100 +Subject: [PATCH 30/39] kselftest/arm64: Add framework support for GCS to signal handling tests Teach the framework about the GCS signal context, avoiding warnings on @@ -4779,7 +3428,7 @@ Signed-off-by: Mark Brown 2 files changed, 8 insertions(+) diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.c b/tools/testing/selftests/arm64/signal/testcases/testcases.c -index 674b88cc8c394..49d036e979964 100644 +index 674b88cc8c39..49d036e97996 100644 --- a/tools/testing/selftests/arm64/signal/testcases/testcases.c +++ b/tools/testing/selftests/arm64/signal/testcases/testcases.c @@ -217,6 +217,13 @@ bool validate_reserved(ucontext_t *uc, size_t resv_sz, char **err) @@ -4797,7 +3446,7 @@ index 674b88cc8c394..49d036e979964 100644 if (flags & EXTRA_CTX) *err = "Multiple EXTRA_MAGIC"; diff --git a/tools/testing/selftests/arm64/signal/testcases/testcases.h b/tools/testing/selftests/arm64/signal/testcases/testcases.h -index 7727126347e0b..dc3cf777dafe4 100644 +index 7727126347e0..dc3cf777dafe 100644 --- a/tools/testing/selftests/arm64/signal/testcases/testcases.h +++ b/tools/testing/selftests/arm64/signal/testcases/testcases.h @@ -20,6 +20,7 @@ @@ -4809,13 +3458,13 @@ index 7727126347e0b..dc3cf777dafe4 100644 #define KSFT_BAD_MAGIC 0xdeadbeef -- -2.34.1 +2.25.1 -From cda93f3a97a6a71c2fad11becac0309814a749e9 Mon Sep 17 00:00:00 2001 +From 8e26520d1cc8af9f6e133b69e387712aa5ebd853 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 5 Jul 2023 17:40:22 +0100 -Subject: [PATCH 43/50] kselftest/arm64: Allow signals tests to specify an +Date: Thu, 29 Aug 2024 00:27:47 +0100 +Subject: [PATCH 31/39] kselftest/arm64: Allow signals tests to specify an expected si_code Currently we ignore si_code unless the expected signal is a SIGSEGV, in @@ -4831,7 +3480,7 @@ Signed-off-by: Mark Brown 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/arm64/signal/test_signals.h b/tools/testing/selftests/arm64/signal/test_signals.h -index 7ada43688c024..ee75a2c25ce7e 100644 +index 7ada43688c02..ee75a2c25ce7 100644 --- a/tools/testing/selftests/arm64/signal/test_signals.h +++ b/tools/testing/selftests/arm64/signal/test_signals.h @@ -71,6 +71,10 @@ struct tdescr { @@ -4846,7 +3495,7 @@ index 7ada43688c024..ee75a2c25ce7e 100644 int sig_unsupp; /* a timeout in second for test completion */ diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.c b/tools/testing/selftests/arm64/signal/test_signals_utils.c -index 89ef95c1af0eb..63deca32b0dff 100644 +index 89ef95c1af0e..63deca32b0df 100644 --- a/tools/testing/selftests/arm64/signal/test_signals_utils.c +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.c @@ -143,16 +143,25 @@ static bool handle_signal_ok(struct tdescr *td, @@ -4886,13 +3535,13 @@ index 89ef95c1af0eb..63deca32b0dff 100644 td->pass = 1; /* -- -2.34.1 +2.25.1 -From 5455426403d03db242b6ea92ac8175704c07165e Mon Sep 17 00:00:00 2001 +From 2a49d76fc0470d7689179f9bd30e66bf1bf48484 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 5 Jul 2023 14:43:32 +0100 -Subject: [PATCH 44/50] kselftest/arm64: Always run signals tests with GCS +Date: Thu, 29 Aug 2024 00:27:48 +0100 +Subject: [PATCH 32/39] kselftest/arm64: Always run signals tests with GCS enabled Since it is not possible to return from the function that enabled GCS @@ -4911,7 +3560,7 @@ Signed-off-by: Mark Brown 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/arm64/signal/test_signals.c b/tools/testing/selftests/arm64/signal/test_signals.c -index 00051b40d71ea..30e95f50db19b 100644 +index 00051b40d71e..30e95f50db19 100644 --- a/tools/testing/selftests/arm64/signal/test_signals.c +++ b/tools/testing/selftests/arm64/signal/test_signals.c @@ -7,6 +7,10 @@ @@ -4951,7 +3600,7 @@ index 00051b40d71ea..30e95f50db19b 100644 + exit(current->result); } diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.h b/tools/testing/selftests/arm64/signal/test_signals_utils.h -index 762c8fe9c54ad..1e80808ee105d 100644 +index 762c8fe9c54a..1e80808ee105 100644 --- a/tools/testing/selftests/arm64/signal/test_signals_utils.h +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.h @@ -18,6 +18,35 @@ void test_cleanup(struct tdescr *td); @@ -4991,13 +3640,13 @@ index 762c8fe9c54ad..1e80808ee105d 100644 { if (td->feats_incompatible & td->feats_supported) -- -2.34.1 +2.25.1 -From b7a723b546791f570fbc055e195af0cccd87de1a Mon Sep 17 00:00:00 2001 +From 60f350965b6b222de8152f18a4f46b55744828e8 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Thu, 6 Apr 2023 00:35:19 +0100 -Subject: [PATCH 45/50] kselftest/arm64: Add very basic GCS test program +Date: Thu, 29 Aug 2024 00:27:49 +0100 +Subject: [PATCH 33/39] kselftest/arm64: Add very basic GCS test program This test program just covers the basic GCS ABI, covering aspects of the ABI as standalone features without attempting to integrate things. @@ -5017,7 +3666,7 @@ Signed-off-by: Mark Brown create mode 100644 tools/testing/selftests/arm64/gcs/gcs-util.h diff --git a/tools/testing/selftests/arm64/Makefile b/tools/testing/selftests/arm64/Makefile -index 28b93cab8c0dd..22029e60eff39 100644 +index 28b93cab8c0d..22029e60eff3 100644 --- a/tools/testing/selftests/arm64/Makefile +++ b/tools/testing/selftests/arm64/Makefile @@ -4,7 +4,7 @@ @@ -5031,14 +3680,14 @@ index 28b93cab8c0dd..22029e60eff39 100644 endif diff --git a/tools/testing/selftests/arm64/gcs/.gitignore b/tools/testing/selftests/arm64/gcs/.gitignore new file mode 100644 -index 0000000000000..0e5e695ecba59 +index 000000000000..0e5e695ecba5 --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/.gitignore @@ -0,0 +1 @@ +basic-gcs diff --git a/tools/testing/selftests/arm64/gcs/Makefile b/tools/testing/selftests/arm64/gcs/Makefile new file mode 100644 -index 0000000000000..61a30f483429c +index 000000000000..61a30f483429 --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/Makefile @@ -0,0 +1,18 @@ @@ -5062,7 +3711,7 @@ index 0000000000000..61a30f483429c + -ffreestanding -Wall $^ -o $@ -lgcc diff --git a/tools/testing/selftests/arm64/gcs/basic-gcs.c b/tools/testing/selftests/arm64/gcs/basic-gcs.c new file mode 100644 -index 0000000000000..3fb9742342a34 +index 000000000000..3fb9742342a3 --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/basic-gcs.c @@ -0,0 +1,357 @@ @@ -5425,7 +4074,7 @@ index 0000000000000..3fb9742342a34 +} diff --git a/tools/testing/selftests/arm64/gcs/gcs-util.h b/tools/testing/selftests/arm64/gcs/gcs-util.h new file mode 100644 -index 0000000000000..1ae6864d3f86a +index 000000000000..1ae6864d3f86 --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/gcs-util.h @@ -0,0 +1,90 @@ @@ -5520,13 +4169,13 @@ index 0000000000000..1ae6864d3f86a + +#endif -- -2.34.1 +2.25.1 -From a1d9c2596cb40d8bde8b9a30c0599e1a9991c5f0 Mon Sep 17 00:00:00 2001 +From a935acdf515a62b3c79728bd9ea9fc2b4c262420 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 28 Apr 2023 18:06:06 +0100 -Subject: [PATCH 46/50] kselftest/arm64: Add a GCS test program built with the +Date: Thu, 29 Aug 2024 00:27:50 +0100 +Subject: [PATCH 34/39] kselftest/arm64: Add a GCS test program built with the system libc There are things like threads which nolibc struggles with which we want @@ -5540,19 +4189,19 @@ Signed-off-by: Mark Brown tools/testing/selftests/arm64/gcs/.gitignore | 1 + tools/testing/selftests/arm64/gcs/Makefile | 4 +- tools/testing/selftests/arm64/gcs/gcs-util.h | 10 + - tools/testing/selftests/arm64/gcs/libc-gcs.c | 736 +++++++++++++++++++ - 4 files changed, 750 insertions(+), 1 deletion(-) + tools/testing/selftests/arm64/gcs/libc-gcs.c | 728 +++++++++++++++++++ + 4 files changed, 742 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/arm64/gcs/libc-gcs.c diff --git a/tools/testing/selftests/arm64/gcs/.gitignore b/tools/testing/selftests/arm64/gcs/.gitignore -index 0e5e695ecba59..5810c4a163d44 100644 +index 0e5e695ecba5..5810c4a163d4 100644 --- a/tools/testing/selftests/arm64/gcs/.gitignore +++ b/tools/testing/selftests/arm64/gcs/.gitignore @@ -1 +1,2 @@ basic-gcs +libc-gcs diff --git a/tools/testing/selftests/arm64/gcs/Makefile b/tools/testing/selftests/arm64/gcs/Makefile -index 61a30f483429c..a8fdf21e9a471 100644 +index 61a30f483429..a8fdf21e9a47 100644 --- a/tools/testing/selftests/arm64/gcs/Makefile +++ b/tools/testing/selftests/arm64/gcs/Makefile @@ -6,7 +6,9 @@ @@ -5567,7 +4216,7 @@ index 61a30f483429c..a8fdf21e9a471 100644 include ../../lib.mk diff --git a/tools/testing/selftests/arm64/gcs/gcs-util.h b/tools/testing/selftests/arm64/gcs/gcs-util.h -index 1ae6864d3f86a..8ac37dc3c78ea 100644 +index 1ae6864d3f86..8ac37dc3c78e 100644 --- a/tools/testing/selftests/arm64/gcs/gcs-util.h +++ b/tools/testing/selftests/arm64/gcs/gcs-util.h @@ -16,6 +16,16 @@ @@ -5589,10 +4238,10 @@ index 1ae6864d3f86a..8ac37dc3c78ea 100644 #define PR_SET_SHADOW_STACK_STATUS 75 diff --git a/tools/testing/selftests/arm64/gcs/libc-gcs.c b/tools/testing/selftests/arm64/gcs/libc-gcs.c new file mode 100644 -index 0000000000000..937f8bee7bdde +index 000000000000..5060fdc110f5 --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/libc-gcs.c -@@ -0,0 +1,736 @@ +@@ -0,0 +1,728 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2023 ARM Limited. @@ -5669,7 +4318,7 @@ index 0000000000000..937f8bee7bdde + } + + if (!(mode & PR_SHADOW_STACK_ENABLE)) { -+ ksft_print_msg("GCS not enabled in thread, mode is %u\n", ++ ksft_print_msg("GCS not enabled in thread, mode is %lu\n", + mode); + return NULL; + } @@ -5751,10 +4400,12 @@ index 0000000000000..937f8bee7bdde + */ + gcs_recurse(0); + if (ptrace(PTRACE_TRACEME, -1, NULL, NULL)) -+ ksft_exit_fail_msg("PTRACE_TRACEME", strerror(errno)); ++ ksft_exit_fail_msg("PTRACE_TRACEME %s", ++ strerror(errno)); + + if (raise(SIGSTOP)) -+ ksft_exit_fail_msg("raise(SIGSTOP)", strerror(errno)); ++ ksft_exit_fail_msg("raise(SIGSTOP) %s", ++ strerror(errno)); + + return; + } @@ -5837,7 +4488,7 @@ index 0000000000000..937f8bee7bdde + } + + gcspr = child_gcs.gcspr_el0; -+ ksft_print_msg("Child GCSPR 0x%lx, flags %x, locked %x\n", ++ ksft_print_msg("Child GCSPR 0x%lx, flags %llx, locked %llx\n", + gcspr, child_gcs.features_enabled, + child_gcs.features_locked); + @@ -6029,7 +4680,7 @@ index 0000000000000..937f8bee7bdde + variant->flags); + ASSERT_FALSE(self->stack == MAP_FAILED); + ksft_print_msg("Allocated stack from %p-%p\n", self->stack, -+ (unsigned long)self->stack + variant->stack_size); ++ self->stack + variant->stack_size); +} + +FIXTURE_TEARDOWN(map_gcs) @@ -6126,7 +4777,7 @@ index 0000000000000..937f8bee7bdde + (unsigned long)self->stack + variant->stack_size); + + /* We should be able to use all but 2 slots of the new stack */ -+ ksft_print_msg("Recursing %d levels\n", cap_index - 1); ++ ksft_print_msg("Recursing %zu levels\n", cap_index - 1); + gcs_recurse(cap_index - 1); + + /* Pivot back to the original GCS */ @@ -6134,7 +4785,7 @@ index 0000000000000..937f8bee7bdde + pivot_gcspr_el0 = gcsss2(); + + gcs_recurse(0); -+ ksft_print_msg("Pivoted back to GCSPR_EL0 0x%lx\n", get_gcspr()); ++ ksft_print_msg("Pivoted back to GCSPR_EL0 0x%p\n", get_gcspr()); +} + +/* We fault if we try to go beyond the end of the stack */ @@ -6179,14 +4830,14 @@ index 0000000000000..937f8bee7bdde + (unsigned long)self->stack + variant->stack_size); + + /* Now try to recurse, we should fault doing this. */ -+ ksft_print_msg("Recursing %d levels...\n", cap_index + 1); ++ ksft_print_msg("Recursing %zu levels...\n", cap_index + 1); + gcs_recurse(cap_index + 1); + ksft_print_msg("...done\n"); + + /* Clean up properly to try to guard against spurious passes. */ + gcsss1(orig_gcspr_el0); + pivot_gcspr_el0 = gcsss2(); -+ ksft_print_msg("Pivoted back to GCSPR_EL0 0x%lx\n", get_gcspr()); ++ ksft_print_msg("Pivoted back to GCSPR_EL0 0x%p\n", get_gcspr()); +} + +FIXTURE(map_invalid_gcs) @@ -6250,7 +4901,7 @@ index 0000000000000..937f8bee7bdde + self->stack_size, 0); + ASSERT_FALSE(self->stack == MAP_FAILED); + ksft_print_msg("Allocated stack from %p-%p\n", self->stack, -+ (unsigned long)self->stack + self->stack_size); ++ self->stack + self->stack_size); +} + +FIXTURE_TEARDOWN(invalid_mprotect) @@ -6268,16 +4919,6 @@ index 0000000000000..937f8bee7bdde + .flags = PROT_EXEC, +}; + -+FIXTURE_VARIANT_ADD(invalid_mprotect, bti) -+{ -+ .flags = PROT_BTI, -+}; -+ -+FIXTURE_VARIANT_ADD(invalid_mprotect, exec_bti) -+{ -+ .flags = PROT_EXEC | PROT_BTI, -+}; -+ +TEST_F(invalid_mprotect, do_map) +{ + int ret; @@ -6330,13 +4971,13 @@ index 0000000000000..937f8bee7bdde + exit(test_harness_run(argc, argv)); +} -- -2.34.1 +2.25.1 -From e3d146167717756a3143982048ed8791bd779ae6 Mon Sep 17 00:00:00 2001 +From 85182687c3b906142ddae92182f7dc6c490ef108 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 21 Jul 2023 14:21:32 +0100 -Subject: [PATCH 47/50] kselftest/arm64: Add test coverage for GCS mode locking +Date: Thu, 29 Aug 2024 00:27:51 +0100 +Subject: [PATCH 35/39] kselftest/arm64: Add test coverage for GCS mode locking Verify that we can lock individual GCS mode bits, that other modes aren't affected and as a side effect also that every combination of @@ -6362,7 +5003,7 @@ Signed-off-by: Mark Brown create mode 100644 tools/testing/selftests/arm64/gcs/gcs-locking.c diff --git a/tools/testing/selftests/arm64/gcs/.gitignore b/tools/testing/selftests/arm64/gcs/.gitignore -index 5810c4a163d44..0c86f53f68ad2 100644 +index 5810c4a163d4..0c86f53f68ad 100644 --- a/tools/testing/selftests/arm64/gcs/.gitignore +++ b/tools/testing/selftests/arm64/gcs/.gitignore @@ -1,2 +1,3 @@ @@ -6370,7 +5011,7 @@ index 5810c4a163d44..0c86f53f68ad2 100644 libc-gcs +gcs-locking diff --git a/tools/testing/selftests/arm64/gcs/Makefile b/tools/testing/selftests/arm64/gcs/Makefile -index a8fdf21e9a471..2173d6275956d 100644 +index a8fdf21e9a47..2173d6275956 100644 --- a/tools/testing/selftests/arm64/gcs/Makefile +++ b/tools/testing/selftests/arm64/gcs/Makefile @@ -6,7 +6,7 @@ @@ -6384,7 +5025,7 @@ index a8fdf21e9a471..2173d6275956d 100644 diff --git a/tools/testing/selftests/arm64/gcs/gcs-locking.c b/tools/testing/selftests/arm64/gcs/gcs-locking.c new file mode 100644 -index 0000000000000..f6a73254317e8 +index 000000000000..f6a73254317e --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/gcs-locking.c @@ -0,0 +1,200 @@ @@ -6589,13 +5230,13 @@ index 0000000000000..f6a73254317e8 + return test_harness_run(argc, argv); +} -- -2.34.1 +2.25.1 -From 00b44ec8fa0aeccaebbdd5112a6187c1a7181e0d Mon Sep 17 00:00:00 2001 +From 47def94241b2c6749d2d621dea1e25590e57cd29 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Fri, 16 Jun 2023 22:13:44 +0100 -Subject: [PATCH 48/50] kselftest/arm64: Add GCS signal tests +Date: Thu, 29 Aug 2024 00:27:52 +0100 +Subject: [PATCH 36/39] kselftest/arm64: Add GCS signal tests Do some testing of the signal handling for GCS, checking that a GCS frame has the expected information in it and that the expected signals @@ -6615,7 +5256,7 @@ Signed-off-by: Mark Brown create mode 100644 tools/testing/selftests/arm64/signal/testcases/gcs_write_fault.c diff --git a/tools/testing/selftests/arm64/signal/.gitignore b/tools/testing/selftests/arm64/signal/.gitignore -index 1ce5b5eac3866..75d691c132077 100644 +index 1ce5b5eac386..75d691c13207 100644 --- a/tools/testing/selftests/arm64/signal/.gitignore +++ b/tools/testing/selftests/arm64/signal/.gitignore @@ -2,6 +2,7 @@ @@ -6627,7 +5268,7 @@ index 1ce5b5eac3866..75d691c132077 100644 ssve_* sve_* diff --git a/tools/testing/selftests/arm64/signal/test_signals_utils.h b/tools/testing/selftests/arm64/signal/test_signals_utils.h -index 1e80808ee105d..36fc12b3cd604 100644 +index 1e80808ee105..36fc12b3cd60 100644 --- a/tools/testing/selftests/arm64/signal/test_signals_utils.h +++ b/tools/testing/selftests/arm64/signal/test_signals_utils.h @@ -6,6 +6,7 @@ @@ -6656,7 +5297,7 @@ index 1e80808ee105d..36fc12b3cd604 100644 if (td->feats_incompatible & td->feats_supported) diff --git a/tools/testing/selftests/arm64/signal/testcases/gcs_exception_fault.c b/tools/testing/selftests/arm64/signal/testcases/gcs_exception_fault.c new file mode 100644 -index 0000000000000..6228448b2ae79 +index 000000000000..6228448b2ae7 --- /dev/null +++ b/tools/testing/selftests/arm64/signal/testcases/gcs_exception_fault.c @@ -0,0 +1,62 @@ @@ -6724,7 +5365,7 @@ index 0000000000000..6228448b2ae79 +}; diff --git a/tools/testing/selftests/arm64/signal/testcases/gcs_frame.c b/tools/testing/selftests/arm64/signal/testcases/gcs_frame.c new file mode 100644 -index 0000000000000..b405d82321daf +index 000000000000..b405d82321da --- /dev/null +++ b/tools/testing/selftests/arm64/signal/testcases/gcs_frame.c @@ -0,0 +1,88 @@ @@ -6818,7 +5459,7 @@ index 0000000000000..b405d82321daf +}; diff --git a/tools/testing/selftests/arm64/signal/testcases/gcs_write_fault.c b/tools/testing/selftests/arm64/signal/testcases/gcs_write_fault.c new file mode 100644 -index 0000000000000..faeabb18c4b2f +index 000000000000..faeabb18c4b2 --- /dev/null +++ b/tools/testing/selftests/arm64/signal/testcases/gcs_write_fault.c @@ -0,0 +1,67 @@ @@ -6890,13 +5531,13 @@ index 0000000000000..faeabb18c4b2f + .run = gcs_write_fault_signal, +}; -- -2.34.1 +2.25.1 -From e81b987237ca8903571306020cf208a02e75d42a Mon Sep 17 00:00:00 2001 +From ad28d01ce03a429d5b5cf9cca41882894863e873 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 26 Jul 2023 22:27:08 +0100 -Subject: [PATCH 49/50] kselftest/arm64: Add a GCS stress test +Date: Thu, 29 Aug 2024 00:27:53 +0100 +Subject: [PATCH 37/39] kselftest/arm64: Add a GCS stress test Add a stress test which runs one more process than we have CPUs spinning through a very recursive function with frequent syscalls immediately prior @@ -6912,14 +5553,14 @@ Signed-off-by: Mark Brown tools/testing/selftests/arm64/gcs/Makefile | 6 +- .../testing/selftests/arm64/gcs/asm-offsets.h | 0 .../selftests/arm64/gcs/gcs-stress-thread.S | 311 ++++++++++ - .../testing/selftests/arm64/gcs/gcs-stress.c | 532 ++++++++++++++++++ - 5 files changed, 850 insertions(+), 1 deletion(-) + .../testing/selftests/arm64/gcs/gcs-stress.c | 530 ++++++++++++++++++ + 5 files changed, 848 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/arm64/gcs/asm-offsets.h create mode 100644 tools/testing/selftests/arm64/gcs/gcs-stress-thread.S create mode 100644 tools/testing/selftests/arm64/gcs/gcs-stress.c diff --git a/tools/testing/selftests/arm64/gcs/.gitignore b/tools/testing/selftests/arm64/gcs/.gitignore -index 0c86f53f68ad2..1e8d1f6b27f2b 100644 +index 0c86f53f68ad..1e8d1f6b27f2 100644 --- a/tools/testing/selftests/arm64/gcs/.gitignore +++ b/tools/testing/selftests/arm64/gcs/.gitignore @@ -1,3 +1,5 @@ @@ -6929,7 +5570,7 @@ index 0c86f53f68ad2..1e8d1f6b27f2b 100644 +gcs-stress +gcs-stress-thread diff --git a/tools/testing/selftests/arm64/gcs/Makefile b/tools/testing/selftests/arm64/gcs/Makefile -index 2173d6275956d..d8b06ca51e22a 100644 +index 2173d6275956..d8b06ca51e22 100644 --- a/tools/testing/selftests/arm64/gcs/Makefile +++ b/tools/testing/selftests/arm64/gcs/Makefile @@ -6,7 +6,8 @@ @@ -6951,10 +5592,10 @@ index 2173d6275956d..d8b06ca51e22a 100644 + $(CC) -nostdlib $^ -o $@ diff --git a/tools/testing/selftests/arm64/gcs/asm-offsets.h b/tools/testing/selftests/arm64/gcs/asm-offsets.h new file mode 100644 -index 0000000000000..e69de29bb2d1d +index 000000000000..e69de29bb2d1 diff --git a/tools/testing/selftests/arm64/gcs/gcs-stress-thread.S b/tools/testing/selftests/arm64/gcs/gcs-stress-thread.S new file mode 100644 -index 0000000000000..2a08d6bf1cedd +index 000000000000..b88b25217da5 --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/gcs-stress-thread.S @@ -0,0 +1,311 @@ @@ -6984,7 +5625,7 @@ index 0000000000000..2a08d6bf1cedd +#define SA_SIGINFO 4 +#define ucontext_regs 184 + -+#define PR_SET_SHADOW_STACK_STATUS 72 ++#define PR_SET_SHADOW_STACK_STATUS 75 +# define PR_SHADOW_STACK_ENABLE (1UL << 0) + +#define GCSPR_EL0 S3_3_C2_C5_1 @@ -7271,10 +5912,10 @@ index 0000000000000..2a08d6bf1cedd + svc #0 diff --git a/tools/testing/selftests/arm64/gcs/gcs-stress.c b/tools/testing/selftests/arm64/gcs/gcs-stress.c new file mode 100644 -index 0000000000000..23fd8ec37bdcf +index 000000000000..a81417cd6f5c --- /dev/null +++ b/tools/testing/selftests/arm64/gcs/gcs-stress.c -@@ -0,0 +1,532 @@ +@@ -0,0 +1,530 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2022-3 ARM Limited. @@ -7803,18 +6444,16 @@ index 0000000000000..23fd8ec37bdcf + + drain_output(true); + -+ ksft_print_cnts(); -+ -+ return 0; ++ ksft_finished(); +} -- -2.34.1 +2.25.1 -From 450d848f1ea499c6985d4d9e66c6da3209cc300b Mon Sep 17 00:00:00 2001 +From 52b5a5ef74e62998871a5a048b5fbd6ad6e74e02 Mon Sep 17 00:00:00 2001 From: Mark Brown -Date: Wed, 21 Jun 2023 17:53:57 +0100 -Subject: [PATCH 50/50] kselftest/arm64: Enable GCS for the FP stress tests +Date: Thu, 29 Aug 2024 00:27:54 +0100 +Subject: [PATCH 38/39] kselftest/arm64: Enable GCS for the FP stress tests While it's a bit off topic for them the floating point stress tests do give us some coverage of context thrashing cases, and also of active signal @@ -7833,7 +6472,7 @@ Signed-off-by: Mark Brown 5 files changed, 23 insertions(+) diff --git a/tools/testing/selftests/arm64/fp/assembler.h b/tools/testing/selftests/arm64/fp/assembler.h -index 9b38a0da407d8..1fc46a5642c29 100644 +index 9b38a0da407d..1fc46a5642c2 100644 --- a/tools/testing/selftests/arm64/fp/assembler.h +++ b/tools/testing/selftests/arm64/fp/assembler.h @@ -65,4 +65,19 @@ endfunction @@ -7857,7 +6496,7 @@ index 9b38a0da407d8..1fc46a5642c29 100644 + #endif /* ! ASSEMBLER_H */ diff --git a/tools/testing/selftests/arm64/fp/fpsimd-test.S b/tools/testing/selftests/arm64/fp/fpsimd-test.S -index 8b960d01ed2e0..b16fb7f42e3e4 100644 +index 8b960d01ed2e..b16fb7f42e3e 100644 --- a/tools/testing/selftests/arm64/fp/fpsimd-test.S +++ b/tools/testing/selftests/arm64/fp/fpsimd-test.S @@ -215,6 +215,8 @@ endfunction @@ -7870,7 +6509,7 @@ index 8b960d01ed2e0..b16fb7f42e3e4 100644 mov w0, #SIGINT diff --git a/tools/testing/selftests/arm64/fp/sve-test.S b/tools/testing/selftests/arm64/fp/sve-test.S -index fff60e2a25add..2fb4f0b84476b 100644 +index fff60e2a25ad..2fb4f0b84476 100644 --- a/tools/testing/selftests/arm64/fp/sve-test.S +++ b/tools/testing/selftests/arm64/fp/sve-test.S @@ -378,6 +378,8 @@ endfunction @@ -7883,7 +6522,7 @@ index fff60e2a25add..2fb4f0b84476b 100644 mov w0, #SIGINT diff --git a/tools/testing/selftests/arm64/fp/za-test.S b/tools/testing/selftests/arm64/fp/za-test.S -index 095b455316409..b2603aba99de8 100644 +index 095b45531640..b2603aba99de 100644 --- a/tools/testing/selftests/arm64/fp/za-test.S +++ b/tools/testing/selftests/arm64/fp/za-test.S @@ -231,6 +231,8 @@ endfunction @@ -7896,7 +6535,7 @@ index 095b455316409..b2603aba99de8 100644 mov w0, #SIGINT diff --git a/tools/testing/selftests/arm64/fp/zt-test.S b/tools/testing/selftests/arm64/fp/zt-test.S -index b5c81e81a3794..8d9609a490085 100644 +index b5c81e81a379..8d9609a49008 100644 --- a/tools/testing/selftests/arm64/fp/zt-test.S +++ b/tools/testing/selftests/arm64/fp/zt-test.S @@ -200,6 +200,8 @@ endfunction @@ -7909,5 +6548,84 @@ index b5c81e81a3794..8d9609a490085 100644 mov w0, #SIGINT -- -2.34.1 +2.25.1 + + +From 502b0fa0a962040e2547eae8ef7caa4a08ad0ba6 Mon Sep 17 00:00:00 2001 +From: Mark Brown +Date: Thu, 29 Aug 2024 00:27:55 +0100 +Subject: [PATCH 39/39] KVM: selftests: arm64: Add GCS registers to + get-reg-list + +GCS adds new registers GCSCR_EL1, GCSCRE0_EL1, GCSPR_EL1 and GCSPR_EL0. Add +these to those validated by get-reg-list. + +Reviewed-by: Thiago Jung Bauermann +Signed-off-by: Mark Brown +--- + .../selftests/kvm/aarch64/get-reg-list.c | 28 +++++++++++++++++++ + 1 file changed, 28 insertions(+) + +diff --git a/tools/testing/selftests/kvm/aarch64/get-reg-list.c b/tools/testing/selftests/kvm/aarch64/get-reg-list.c +index 709d7d721760..9785f41e6042 100644 +--- a/tools/testing/selftests/kvm/aarch64/get-reg-list.c ++++ b/tools/testing/selftests/kvm/aarch64/get-reg-list.c +@@ -29,6 +29,24 @@ static struct feature_id_reg feat_id_regs[] = { + 0, + 1 + }, ++ { ++ ARM64_SYS_REG(3, 0, 2, 5, 0), /* GCSCR_EL1 */ ++ ARM64_SYS_REG(3, 0, 0, 4, 1), /* ID_AA64PFR1_EL1 */ ++ 44, ++ 1 ++ }, ++ { ++ ARM64_SYS_REG(3, 0, 2, 5, 1), /* GCSPR_EL1 */ ++ ARM64_SYS_REG(3, 0, 0, 4, 1), /* ID_AA64PFR1_EL1 */ ++ 44, ++ 1 ++ }, ++ { ++ ARM64_SYS_REG(3, 0, 2, 5, 2), /* GCSCRE0_EL1 */ ++ ARM64_SYS_REG(3, 0, 0, 4, 1), /* ID_AA64PFR1_EL1 */ ++ 44, ++ 1 ++ }, + { + ARM64_SYS_REG(3, 0, 10, 2, 2), /* PIRE0_EL1 */ + ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */ +@@ -40,6 +58,12 @@ static struct feature_id_reg feat_id_regs[] = { + ARM64_SYS_REG(3, 0, 0, 7, 3), /* ID_AA64MMFR3_EL1 */ + 4, + 1 ++ }, ++ { ++ ARM64_SYS_REG(3, 3, 2, 5, 1), /* GCSPR_EL0 */ ++ ARM64_SYS_REG(3, 0, 0, 4, 1), /* ID_AA64PFR1_EL1 */ ++ 44, ++ 1 + } + }; + +@@ -460,6 +484,9 @@ static __u64 base_regs[] = { + ARM64_SYS_REG(3, 0, 2, 0, 1), /* TTBR1_EL1 */ + ARM64_SYS_REG(3, 0, 2, 0, 2), /* TCR_EL1 */ + ARM64_SYS_REG(3, 0, 2, 0, 3), /* TCR2_EL1 */ ++ ARM64_SYS_REG(3, 0, 2, 5, 0), /* GCSCR_EL1 */ ++ ARM64_SYS_REG(3, 0, 2, 5, 1), /* GCSPR_EL1 */ ++ ARM64_SYS_REG(3, 0, 2, 5, 2), /* GCSCRE0_EL1 */ + ARM64_SYS_REG(3, 0, 5, 1, 0), /* AFSR0_EL1 */ + ARM64_SYS_REG(3, 0, 5, 1, 1), /* AFSR1_EL1 */ + ARM64_SYS_REG(3, 0, 5, 2, 0), /* ESR_EL1 */ +@@ -475,6 +502,7 @@ static __u64 base_regs[] = { + ARM64_SYS_REG(3, 0, 13, 0, 4), /* TPIDR_EL1 */ + ARM64_SYS_REG(3, 0, 14, 1, 0), /* CNTKCTL_EL1 */ + ARM64_SYS_REG(3, 2, 0, 0, 0), /* CSSELR_EL1 */ ++ ARM64_SYS_REG(3, 3, 2, 5, 1), /* GCSPR_EL0 */ + ARM64_SYS_REG(3, 3, 13, 0, 2), /* TPIDR_EL0 */ + ARM64_SYS_REG(3, 3, 13, 0, 3), /* TPIDRRO_EL0 */ + ARM64_SYS_REG(3, 3, 14, 0, 1), /* CNTPCT_EL0 */ +-- +2.25.1 diff --git a/meta-arm-gcs/recipes-kernel/linux/linux-yocto-dev.bbappend b/meta-arm-gcs/recipes-kernel/linux/linux-yocto-dev.bbappend index 28bcc63c..2be406a0 100644 --- a/meta-arm-gcs/recipes-kernel/linux/linux-yocto-dev.bbappend +++ b/meta-arm-gcs/recipes-kernel/linux/linux-yocto-dev.bbappend @@ -1,11 +1,11 @@ FILESEXTRAPATHS:prepend := "${THISDIR}/files:" -KBRANCH = "v6.10/base" -SRCREV_machine = "83a7eefedc9b56fe7bfeff13b6c7356688ffa670" +KBRANCH = "v6.11/standard/base" +SRCREV_machine = "7c626ce4bae1ac14f60076d00eafe71af30450ba" SRCREV_meta = "66aec68f0ba1d15ba0e9c19f1ec0d2b4a75c5333" -LINUX_VERSION = "6.10.0" +LINUX_VERSION = "6.11.0" -SRC_URI += "file://gcs.patch" +SRC_URI += "file://gcs.patch file://disable_uprobe.cfg" # TMPDIR references in: # /usr/src/debug/linux-yocto-dev/6.8.0+git/drivers/tty/vt/consolemap_deftbl.c