From 52b4f51f80b054e45bb18f6dfa0d462bbe6cc9d7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 12 Jan 2023 13:17:52 +0100 Subject: [PATCH] 5.15-stable patches added patches: parisc-align-parisc-madv_xxx-constants-with-all-other-architectures.patch selftests-vm-pkeys-add-a-regression-test-for-setting-pkru-through-ptrace.patch series x86-fpu-add-a-pkru-argument-to-copy_uabi_from_kernel_to_xstate.patch x86-fpu-add-a-pkru-argument-to-copy_uabi_to_xstate.patch x86-fpu-allow-pkru-to-be-once-again-written-by-ptrace.patch x86-fpu-emulate-xrstor-s-behavior-if-the-xfeatures-pkru-bit-is-not-set.patch x86-fpu-take-task_struct-in-copy_sigframe_from_user_to_xstate.patch --- ...nstants-with-all-other-architectures.patch | 177 +++++++++++++++ ...test-for-setting-pkru-through-ptrace.patch | 205 ++++++++++++++++++ queue-5.15/series | 7 + ...t-to-copy_uabi_from_kernel_to_xstate.patch | 61 ++++++ ...pkru-argument-to-copy_uabi_to_xstate.patch | 58 +++++ ...u-to-be-once-again-written-by-ptrace.patch | 77 +++++++ ...if-the-xfeatures-pkru-bit-is-not-set.patch | 41 ++++ ...in-copy_sigframe_from_user_to_xstate.patch | 64 ++++++ 8 files changed, 690 insertions(+) create mode 100644 queue-5.15/parisc-align-parisc-madv_xxx-constants-with-all-other-architectures.patch create mode 100644 queue-5.15/selftests-vm-pkeys-add-a-regression-test-for-setting-pkru-through-ptrace.patch create mode 100644 queue-5.15/series create mode 100644 queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_from_kernel_to_xstate.patch create mode 100644 queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_to_xstate.patch create mode 100644 queue-5.15/x86-fpu-allow-pkru-to-be-once-again-written-by-ptrace.patch create mode 100644 queue-5.15/x86-fpu-emulate-xrstor-s-behavior-if-the-xfeatures-pkru-bit-is-not-set.patch create mode 100644 queue-5.15/x86-fpu-take-task_struct-in-copy_sigframe_from_user_to_xstate.patch diff --git a/queue-5.15/parisc-align-parisc-madv_xxx-constants-with-all-other-architectures.patch b/queue-5.15/parisc-align-parisc-madv_xxx-constants-with-all-other-architectures.patch new file mode 100644 index 00000000000..e9d9a1de45a --- /dev/null +++ b/queue-5.15/parisc-align-parisc-madv_xxx-constants-with-all-other-architectures.patch @@ -0,0 +1,177 @@ +From 71bdea6f798b425bc0003780b13e3fdecb16a010 Mon Sep 17 00:00:00 2001 +From: Helge Deller +Date: Sun, 11 Dec 2022 19:50:20 +0100 +Subject: parisc: Align parisc MADV_XXX constants with all other architectures + +From: Helge Deller + +commit 71bdea6f798b425bc0003780b13e3fdecb16a010 upstream. + +Adjust some MADV_XXX constants to be in sync what their values are on +all other platforms. There is currently no reason to have an own +numbering on parisc, but it requires workarounds in many userspace +sources (e.g. glibc, qemu, ...) - which are often forgotten and thus +introduce bugs and different behaviour on parisc. + +A wrapper avoids an ABI breakage for existing userspace applications by +translating any old values to the new ones, so this change allows us to +move over all programs to the new ABI over time. + +Signed-off-by: Helge Deller +Signed-off-by: Greg Kroah-Hartman +--- + arch/parisc/include/uapi/asm/mman.h | 27 +++++++++++++-------------- + arch/parisc/kernel/sys_parisc.c | 27 +++++++++++++++++++++++++++ + arch/parisc/kernel/syscalls/syscall.tbl | 2 +- + tools/arch/parisc/include/uapi/asm/mman.h | 12 ++++++------ + tools/perf/bench/bench.h | 12 ------------ + 5 files changed, 47 insertions(+), 33 deletions(-) + +--- a/arch/parisc/include/uapi/asm/mman.h ++++ b/arch/parisc/include/uapi/asm/mman.h +@@ -49,31 +49,30 @@ + #define MADV_DONTFORK 10 /* don't inherit across fork */ + #define MADV_DOFORK 11 /* do inherit across fork */ + +-#define MADV_COLD 20 /* deactivate these pages */ +-#define MADV_PAGEOUT 21 /* reclaim these pages */ ++#define MADV_MERGEABLE 12 /* KSM may merge identical pages */ ++#define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages */ + +-#define MADV_POPULATE_READ 22 /* populate (prefault) page tables readable */ +-#define MADV_POPULATE_WRITE 23 /* populate (prefault) page tables writable */ ++#define MADV_HUGEPAGE 14 /* Worth backing with hugepages */ ++#define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages */ + +-#define MADV_MERGEABLE 65 /* KSM may merge identical pages */ +-#define MADV_UNMERGEABLE 66 /* KSM may not merge identical pages */ ++#define MADV_DONTDUMP 16 /* Explicity exclude from the core dump, ++ overrides the coredump filter bits */ ++#define MADV_DODUMP 17 /* Clear the MADV_NODUMP flag */ + +-#define MADV_HUGEPAGE 67 /* Worth backing with hugepages */ +-#define MADV_NOHUGEPAGE 68 /* Not worth backing with hugepages */ ++#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */ ++#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */ + +-#define MADV_DONTDUMP 69 /* Explicity exclude from the core dump, +- overrides the coredump filter bits */ +-#define MADV_DODUMP 70 /* Clear the MADV_NODUMP flag */ ++#define MADV_COLD 20 /* deactivate these pages */ ++#define MADV_PAGEOUT 21 /* reclaim these pages */ + +-#define MADV_WIPEONFORK 71 /* Zero memory on fork, child only */ +-#define MADV_KEEPONFORK 72 /* Undo MADV_WIPEONFORK */ ++#define MADV_POPULATE_READ 22 /* populate (prefault) page tables readable */ ++#define MADV_POPULATE_WRITE 23 /* populate (prefault) page tables writable */ + + #define MADV_HWPOISON 100 /* poison a page for testing */ + #define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */ + + /* compatibility flags */ + #define MAP_FILE 0 +-#define MAP_VARIABLE 0 + + #define PKEY_DISABLE_ACCESS 0x1 + #define PKEY_DISABLE_WRITE 0x2 +--- a/arch/parisc/kernel/sys_parisc.c ++++ b/arch/parisc/kernel/sys_parisc.c +@@ -463,3 +463,30 @@ asmlinkage long parisc_inotify_init1(int + flags = FIX_O_NONBLOCK(flags); + return sys_inotify_init1(flags); + } ++ ++/* ++ * madvise() wrapper ++ * ++ * Up to kernel v6.1 parisc has different values than all other ++ * platforms for the MADV_xxx flags listed below. ++ * To keep binary compatibility with existing userspace programs ++ * translate the former values to the new values. ++ * ++ * XXX: Remove this wrapper in year 2025 (or later) ++ */ ++ ++asmlinkage notrace long parisc_madvise(unsigned long start, size_t len_in, int behavior) ++{ ++ switch (behavior) { ++ case 65: behavior = MADV_MERGEABLE; break; ++ case 66: behavior = MADV_UNMERGEABLE; break; ++ case 67: behavior = MADV_HUGEPAGE; break; ++ case 68: behavior = MADV_NOHUGEPAGE; break; ++ case 69: behavior = MADV_DONTDUMP; break; ++ case 70: behavior = MADV_DODUMP; break; ++ case 71: behavior = MADV_WIPEONFORK; break; ++ case 72: behavior = MADV_KEEPONFORK; break; ++ } ++ ++ return sys_madvise(start, len_in, behavior); ++} +--- a/arch/parisc/kernel/syscalls/syscall.tbl ++++ b/arch/parisc/kernel/syscalls/syscall.tbl +@@ -131,7 +131,7 @@ + 116 common sysinfo sys_sysinfo compat_sys_sysinfo + 117 common shutdown sys_shutdown + 118 common fsync sys_fsync +-119 common madvise sys_madvise ++119 common madvise parisc_madvise + 120 common clone sys_clone_wrapper + 121 common setdomainname sys_setdomainname + 122 common sendfile sys_sendfile compat_sys_sendfile +--- a/tools/arch/parisc/include/uapi/asm/mman.h ++++ b/tools/arch/parisc/include/uapi/asm/mman.h +@@ -1,20 +1,20 @@ + /* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ + #ifndef TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H + #define TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H +-#define MADV_DODUMP 70 ++#define MADV_DODUMP 17 + #define MADV_DOFORK 11 +-#define MADV_DONTDUMP 69 ++#define MADV_DONTDUMP 16 + #define MADV_DONTFORK 10 + #define MADV_DONTNEED 4 + #define MADV_FREE 8 +-#define MADV_HUGEPAGE 67 +-#define MADV_MERGEABLE 65 +-#define MADV_NOHUGEPAGE 68 ++#define MADV_HUGEPAGE 14 ++#define MADV_MERGEABLE 12 ++#define MADV_NOHUGEPAGE 15 + #define MADV_NORMAL 0 + #define MADV_RANDOM 1 + #define MADV_REMOVE 9 + #define MADV_SEQUENTIAL 2 +-#define MADV_UNMERGEABLE 66 ++#define MADV_UNMERGEABLE 13 + #define MADV_WILLNEED 3 + #define MAP_ANONYMOUS 0x10 + #define MAP_DENYWRITE 0x0800 +--- a/tools/perf/bench/bench.h ++++ b/tools/perf/bench/bench.h +@@ -10,25 +10,13 @@ extern struct timeval bench__start, benc + * The madvise transparent hugepage constants were added in glibc + * 2.13. For compatibility with older versions of glibc, define these + * tokens if they are not already defined. +- * +- * PA-RISC uses different madvise values from other architectures and +- * needs to be special-cased. + */ +-#ifdef __hppa__ +-# ifndef MADV_HUGEPAGE +-# define MADV_HUGEPAGE 67 +-# endif +-# ifndef MADV_NOHUGEPAGE +-# define MADV_NOHUGEPAGE 68 +-# endif +-#else + # ifndef MADV_HUGEPAGE + # define MADV_HUGEPAGE 14 + # endif + # ifndef MADV_NOHUGEPAGE + # define MADV_NOHUGEPAGE 15 + # endif +-#endif + + int bench_numa(int argc, const char **argv); + int bench_sched_messaging(int argc, const char **argv); diff --git a/queue-5.15/selftests-vm-pkeys-add-a-regression-test-for-setting-pkru-through-ptrace.patch b/queue-5.15/selftests-vm-pkeys-add-a-regression-test-for-setting-pkru-through-ptrace.patch new file mode 100644 index 00000000000..01fa7210954 --- /dev/null +++ b/queue-5.15/selftests-vm-pkeys-add-a-regression-test-for-setting-pkru-through-ptrace.patch @@ -0,0 +1,205 @@ +From me@kylehuey.com Mon Jan 9 22:02:41 2023 +From: Kyle Huey +Date: Mon, 9 Jan 2023 13:02:14 -0800 +Subject: selftests/vm/pkeys: Add a regression test for setting PKRU through ptrace +To: stable@vger.kernel.org, Greg KH +Cc: Dave Hansen , Thomas Gleixner , Borislav Petkov , Ingo Molnar , x86@kernel.org, "H. Peter Anvin" , Paolo Bonzini , Andy Lutomirski , Peter Zijlstra , Sean Christopherson , Robert O'Callahan , David Manouchehri , Kyle Huey +Message-ID: <20230109210214.71068-7-khuey@kylehuey.com> + +From: Kyle Huey + +From: Kyle Huey + +commit 6ea25770b043 upstream + +This tests PTRACE_SETREGSET with NT_X86_XSTATE modifying PKRU directly and +removing the PKRU bit from XSTATE_BV. + +Signed-off-by: Kyle Huey +Signed-off-by: Dave Hansen +Link: https://lore.kernel.org/all/20221115230932.7126-7-khuey%40kylehuey.com +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/vm/pkey-x86.h | 12 ++ + tools/testing/selftests/vm/protection_keys.c | 131 ++++++++++++++++++++++++++- + 2 files changed, 141 insertions(+), 2 deletions(-) + +--- a/tools/testing/selftests/vm/pkey-x86.h ++++ b/tools/testing/selftests/vm/pkey-x86.h +@@ -119,6 +119,18 @@ static inline int cpu_has_pkeys(void) + return 1; + } + ++static inline int cpu_max_xsave_size(void) ++{ ++ unsigned long XSTATE_CPUID = 0xd; ++ unsigned int eax; ++ unsigned int ebx; ++ unsigned int ecx; ++ unsigned int edx; ++ ++ __cpuid_count(XSTATE_CPUID, 0, eax, ebx, ecx, edx); ++ return ecx; ++} ++ + static inline u32 pkey_bit_position(int pkey) + { + return pkey * PKEY_BITS_PER_PKEY; +--- a/tools/testing/selftests/vm/protection_keys.c ++++ b/tools/testing/selftests/vm/protection_keys.c +@@ -18,12 +18,13 @@ + * do a plain mprotect() to a mprotect_pkey() area and make sure the pkey sticks + * + * Compile like this: +- * gcc -o protection_keys -O2 -g -std=gnu99 -pthread -Wall protection_keys.c -lrt -ldl -lm +- * gcc -m32 -o protection_keys_32 -O2 -g -std=gnu99 -pthread -Wall protection_keys.c -lrt -ldl -lm ++ * gcc -mxsave -o protection_keys -O2 -g -std=gnu99 -pthread -Wall protection_keys.c -lrt -ldl -lm ++ * gcc -mxsave -m32 -o protection_keys_32 -O2 -g -std=gnu99 -pthread -Wall protection_keys.c -lrt -ldl -lm + */ + #define _GNU_SOURCE + #define __SANE_USERSPACE_TYPES__ + #include ++#include + #include + #include + #include +@@ -1550,6 +1551,129 @@ void test_implicit_mprotect_exec_only_me + do_not_expect_pkey_fault("plain read on recently PROT_EXEC area"); + } + ++#if defined(__i386__) || defined(__x86_64__) ++void test_ptrace_modifies_pkru(int *ptr, u16 pkey) ++{ ++ u32 new_pkru; ++ pid_t child; ++ int status, ret; ++ int pkey_offset = pkey_reg_xstate_offset(); ++ size_t xsave_size = cpu_max_xsave_size(); ++ void *xsave; ++ u32 *pkey_register; ++ u64 *xstate_bv; ++ struct iovec iov; ++ ++ new_pkru = ~read_pkey_reg(); ++ /* Don't make PROT_EXEC mappings inaccessible */ ++ new_pkru &= ~3; ++ ++ child = fork(); ++ pkey_assert(child >= 0); ++ dprintf3("[%d] fork() ret: %d\n", getpid(), child); ++ if (!child) { ++ ptrace(PTRACE_TRACEME, 0, 0, 0); ++ /* Stop and allow the tracer to modify PKRU directly */ ++ raise(SIGSTOP); ++ ++ /* ++ * need __read_pkey_reg() version so we do not do shadow_pkey_reg ++ * checking ++ */ ++ if (__read_pkey_reg() != new_pkru) ++ exit(1); ++ ++ /* Stop and allow the tracer to clear XSTATE_BV for PKRU */ ++ raise(SIGSTOP); ++ ++ if (__read_pkey_reg() != 0) ++ exit(1); ++ ++ /* Stop and allow the tracer to examine PKRU */ ++ raise(SIGSTOP); ++ ++ exit(0); ++ } ++ ++ pkey_assert(child == waitpid(child, &status, 0)); ++ dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status); ++ pkey_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); ++ ++ xsave = (void *)malloc(xsave_size); ++ pkey_assert(xsave > 0); ++ ++ /* Modify the PKRU register directly */ ++ iov.iov_base = xsave; ++ iov.iov_len = xsave_size; ++ ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ ++ pkey_register = (u32 *)(xsave + pkey_offset); ++ pkey_assert(*pkey_register == read_pkey_reg()); ++ ++ *pkey_register = new_pkru; ++ ++ ret = ptrace(PTRACE_SETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ ++ /* Test that the modification is visible in ptrace before any execution */ ++ memset(xsave, 0xCC, xsave_size); ++ ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ pkey_assert(*pkey_register == new_pkru); ++ ++ /* Execute the tracee */ ++ ret = ptrace(PTRACE_CONT, child, 0, 0); ++ pkey_assert(ret == 0); ++ ++ /* Test that the tracee saw the PKRU value change */ ++ pkey_assert(child == waitpid(child, &status, 0)); ++ dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status); ++ pkey_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); ++ ++ /* Test that the modification is visible in ptrace after execution */ ++ memset(xsave, 0xCC, xsave_size); ++ ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ pkey_assert(*pkey_register == new_pkru); ++ ++ /* Clear the PKRU bit from XSTATE_BV */ ++ xstate_bv = (u64 *)(xsave + 512); ++ *xstate_bv &= ~(1 << 9); ++ ++ ret = ptrace(PTRACE_SETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ ++ /* Test that the modification is visible in ptrace before any execution */ ++ memset(xsave, 0xCC, xsave_size); ++ ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ pkey_assert(*pkey_register == 0); ++ ++ ret = ptrace(PTRACE_CONT, child, 0, 0); ++ pkey_assert(ret == 0); ++ ++ /* Test that the tracee saw the PKRU value go to 0 */ ++ pkey_assert(child == waitpid(child, &status, 0)); ++ dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status); ++ pkey_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP); ++ ++ /* Test that the modification is visible in ptrace after execution */ ++ memset(xsave, 0xCC, xsave_size); ++ ret = ptrace(PTRACE_GETREGSET, child, (void *)NT_X86_XSTATE, &iov); ++ pkey_assert(ret == 0); ++ pkey_assert(*pkey_register == 0); ++ ++ ret = ptrace(PTRACE_CONT, child, 0, 0); ++ pkey_assert(ret == 0); ++ pkey_assert(child == waitpid(child, &status, 0)); ++ dprintf3("[%d] waitpid(%d) status: %x\n", getpid(), child, status); ++ pkey_assert(WIFEXITED(status)); ++ pkey_assert(WEXITSTATUS(status) == 0); ++ free(xsave); ++} ++#endif ++ + void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey) + { + int size = PAGE_SIZE; +@@ -1585,6 +1709,9 @@ void (*pkey_tests[])(int *ptr, u16 pkey) + test_pkey_syscalls_bad_args, + test_pkey_alloc_exhaust, + test_pkey_alloc_free_attach_pkey0, ++#if defined(__i386__) || defined(__x86_64__) ++ test_ptrace_modifies_pkru, ++#endif + }; + + void run_tests_once(void) diff --git a/queue-5.15/series b/queue-5.15/series new file mode 100644 index 00000000000..d74ee0a8d3b --- /dev/null +++ b/queue-5.15/series @@ -0,0 +1,7 @@ +parisc-align-parisc-madv_xxx-constants-with-all-other-architectures.patch +x86-fpu-take-task_struct-in-copy_sigframe_from_user_to_xstate.patch +x86-fpu-add-a-pkru-argument-to-copy_uabi_from_kernel_to_xstate.patch +x86-fpu-add-a-pkru-argument-to-copy_uabi_to_xstate.patch +x86-fpu-allow-pkru-to-be-once-again-written-by-ptrace.patch +x86-fpu-emulate-xrstor-s-behavior-if-the-xfeatures-pkru-bit-is-not-set.patch +selftests-vm-pkeys-add-a-regression-test-for-setting-pkru-through-ptrace.patch diff --git a/queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_from_kernel_to_xstate.patch b/queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_from_kernel_to_xstate.patch new file mode 100644 index 00000000000..d9e6fdb8855 --- /dev/null +++ b/queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_from_kernel_to_xstate.patch @@ -0,0 +1,61 @@ +From me@kylehuey.com Mon Jan 9 22:02:34 2023 +From: Kyle Huey +Date: Mon, 9 Jan 2023 13:02:10 -0800 +Subject: x86/fpu: Add a pkru argument to copy_uabi_from_kernel_to_xstate(). +To: stable@vger.kernel.org, Greg KH +Cc: Dave Hansen , Thomas Gleixner , Borislav Petkov , Ingo Molnar , x86@kernel.org, "H. Peter Anvin" , Paolo Bonzini , Andy Lutomirski , Peter Zijlstra , Sean Christopherson , Robert O'Callahan , David Manouchehri , Kyle Huey +Message-ID: <20230109210214.71068-3-khuey@kylehuey.com> + +From: Kyle Huey + +From: Kyle Huey + +commit 1c813ce03055 upstream + +ptrace (through PTRACE_SETREGSET with NT_X86_XSTATE) ultimately calls +copy_uabi_from_kernel_to_xstate(). In preparation for eventually handling +PKRU in copy_uabi_to_xstate, pass in a pointer to the PKRU location. + +Signed-off-by: Kyle Huey +Signed-off-by: Dave Hansen +Link: https://lore.kernel.org/all/20221115230932.7126-3-khuey%40kylehuey.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/fpu/xstate.h | 2 +- + arch/x86/kernel/fpu/regset.c | 2 +- + arch/x86/kernel/fpu/xstate.c | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/include/asm/fpu/xstate.h ++++ b/arch/x86/include/asm/fpu/xstate.h +@@ -136,7 +136,7 @@ extern void __init update_regset_xstate_ + + void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr); + int xfeature_size(int xfeature_nr); +-int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf); ++int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf, u32 *pkru); + int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, const void __user *ubuf); + + void xsaves(struct xregs_state *xsave, u64 mask); +--- a/arch/x86/kernel/fpu/regset.c ++++ b/arch/x86/kernel/fpu/regset.c +@@ -163,7 +163,7 @@ int xstateregs_set(struct task_struct *t + } + + fpu_force_restore(fpu); +- ret = copy_uabi_from_kernel_to_xstate(&fpu->state.xsave, kbuf ?: tmpbuf); ++ ret = copy_uabi_from_kernel_to_xstate(&fpu->state.xsave, kbuf ?: tmpbuf, &target->thread.pkru); + + out: + vfree(tmpbuf); +--- a/arch/x86/kernel/fpu/xstate.c ++++ b/arch/x86/kernel/fpu/xstate.c +@@ -1159,7 +1159,7 @@ static int copy_uabi_to_xstate(struct xr + * format and copy to the target thread. This is called from + * xstateregs_set(). + */ +-int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf) ++int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf, u32 *pkru) + { + return copy_uabi_to_xstate(xsave, kbuf, NULL); + } diff --git a/queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_to_xstate.patch b/queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_to_xstate.patch new file mode 100644 index 00000000000..3647345a54a --- /dev/null +++ b/queue-5.15/x86-fpu-add-a-pkru-argument-to-copy_uabi_to_xstate.patch @@ -0,0 +1,58 @@ +From me@kylehuey.com Mon Jan 9 22:02:36 2023 +From: Kyle Huey +Date: Mon, 9 Jan 2023 13:02:11 -0800 +Subject: x86/fpu: Add a pkru argument to copy_uabi_to_xstate() +To: stable@vger.kernel.org, Greg KH +Cc: Dave Hansen , Thomas Gleixner , Borislav Petkov , Ingo Molnar , x86@kernel.org, "H. Peter Anvin" , Paolo Bonzini , Andy Lutomirski , Peter Zijlstra , Sean Christopherson , Robert O'Callahan , David Manouchehri , Kyle Huey +Message-ID: <20230109210214.71068-4-khuey@kylehuey.com> + +From: Kyle Huey + +From: Kyle Huey + +commit 2c87767c35ee upstream + +In preparation for adding PKRU handling code into copy_uabi_to_xstate(), +add an argument that copy_uabi_from_kernel_to_xstate() can use to pass the +canonical location of the PKRU value. For +copy_sigframe_from_user_to_xstate() the kernel will actually restore the +PKRU value from the fpstate, but pass in the thread_struct's pkru location +anyways for consistency. + +Signed-off-by: Kyle Huey +Signed-off-by: Dave Hansen +Link: https://lore.kernel.org/all/20221115230932.7126-4-khuey%40kylehuey.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/fpu/xstate.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/kernel/fpu/xstate.c ++++ b/arch/x86/kernel/fpu/xstate.c +@@ -1092,7 +1092,7 @@ static int copy_from_buffer(void *dst, u + + + static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf, +- const void __user *ubuf) ++ const void __user *ubuf, u32 *pkru) + { + unsigned int offset, size; + struct xstate_header hdr; +@@ -1161,7 +1161,7 @@ static int copy_uabi_to_xstate(struct xr + */ + int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf, u32 *pkru) + { +- return copy_uabi_to_xstate(xsave, kbuf, NULL); ++ return copy_uabi_to_xstate(xsave, kbuf, NULL, pkru); + } + + /* +@@ -1172,7 +1172,7 @@ int copy_uabi_from_kernel_to_xstate(stru + int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, + const void __user *ubuf) + { +- return copy_uabi_to_xstate(&tsk->thread.fpu.state.xsave, NULL, ubuf); ++ return copy_uabi_to_xstate(&tsk->thread.fpu.state.xsave, NULL, ubuf, &tsk->thread.pkru); + } + + static bool validate_xsaves_xrstors(u64 mask) diff --git a/queue-5.15/x86-fpu-allow-pkru-to-be-once-again-written-by-ptrace.patch b/queue-5.15/x86-fpu-allow-pkru-to-be-once-again-written-by-ptrace.patch new file mode 100644 index 00000000000..7544095c340 --- /dev/null +++ b/queue-5.15/x86-fpu-allow-pkru-to-be-once-again-written-by-ptrace.patch @@ -0,0 +1,77 @@ +From me@kylehuey.com Mon Jan 9 22:02:38 2023 +From: Kyle Huey +Date: Mon, 9 Jan 2023 13:02:12 -0800 +Subject: x86/fpu: Allow PKRU to be (once again) written by ptrace. +To: stable@vger.kernel.org, Greg KH +Cc: Dave Hansen , Thomas Gleixner , Borislav Petkov , Ingo Molnar , x86@kernel.org, "H. Peter Anvin" , Paolo Bonzini , Andy Lutomirski , Peter Zijlstra , Sean Christopherson , Robert O'Callahan , David Manouchehri , Kyle Huey +Message-ID: <20230109210214.71068-5-khuey@kylehuey.com> + +From: Kyle Huey + +From: Kyle Huey + +commit 4a804c4f8356 upstream + +Handle PKRU in copy_uabi_to_xstate() for the benefit of APIs that write +the XSTATE such as PTRACE_SETREGSET with NT_X86_XSTATE. + +This restores the pre-5.14 behavior of ptrace. The regression can be seen +by running gdb and executing `p $pkru`, `set $pkru = 42`, and `p $pkru`. +On affected kernels (5.14+) the write to the PKRU register (which gdb +performs through ptrace) is ignored. + +Fixes: e84ba47e313d ("x86/fpu: Hook up PKRU into ptrace()") +Signed-off-by: Kyle Huey +Signed-off-by: Dave Hansen +Link: https://lore.kernel.org/all/20221115230932.7126-5-khuey%40kylehuey.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/fpu/xstate.c | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +--- a/arch/x86/kernel/fpu/xstate.c ++++ b/arch/x86/kernel/fpu/xstate.c +@@ -1091,6 +1091,29 @@ static int copy_from_buffer(void *dst, u + } + + ++/** ++ * copy_uabi_to_xstate - Copy a UABI format buffer to the kernel xstate ++ * @fpstate: The fpstate buffer to copy to ++ * @kbuf: The UABI format buffer, if it comes from the kernel ++ * @ubuf: The UABI format buffer, if it comes from userspace ++ * @pkru: The location to write the PKRU value to ++ * ++ * Converts from the UABI format into the kernel internal hardware ++ * dependent format. ++ * ++ * This function ultimately has two different callers with distinct PKRU ++ * behavior. ++ * 1. When called from sigreturn the PKRU register will be restored from ++ * @fpstate via an XRSTOR. Correctly copying the UABI format buffer to ++ * @fpstate is sufficient to cover this case, but the caller will also ++ * pass a pointer to the thread_struct's pkru field in @pkru and updating ++ * it is harmless. ++ * 2. When called from ptrace the PKRU register will be restored from the ++ * thread_struct's pkru field. A pointer to that is passed in @pkru. ++ * The kernel will restore it manually, so the XRSTOR behavior that resets ++ * the PKRU register to the hardware init value (0) if the corresponding ++ * xfeatures bit is not set is emulated here. ++ */ + static int copy_uabi_to_xstate(struct xregs_state *xsave, const void *kbuf, + const void __user *ubuf, u32 *pkru) + { +@@ -1140,6 +1163,13 @@ static int copy_uabi_to_xstate(struct xr + } + } + ++ if (hdr.xfeatures & XFEATURE_MASK_PKRU) { ++ struct pkru_state *xpkru; ++ ++ xpkru = __raw_xsave_addr(xsave, XFEATURE_PKRU); ++ *pkru = xpkru->pkru; ++ } ++ + /* + * The state that came in from userspace was user-state only. + * Mask all the user states out of 'xfeatures': diff --git a/queue-5.15/x86-fpu-emulate-xrstor-s-behavior-if-the-xfeatures-pkru-bit-is-not-set.patch b/queue-5.15/x86-fpu-emulate-xrstor-s-behavior-if-the-xfeatures-pkru-bit-is-not-set.patch new file mode 100644 index 00000000000..1a436a368d4 --- /dev/null +++ b/queue-5.15/x86-fpu-emulate-xrstor-s-behavior-if-the-xfeatures-pkru-bit-is-not-set.patch @@ -0,0 +1,41 @@ +From me@kylehuey.com Mon Jan 9 22:02:39 2023 +From: Kyle Huey +Date: Mon, 9 Jan 2023 13:02:13 -0800 +Subject: x86/fpu: Emulate XRSTOR's behavior if the xfeatures PKRU bit is not set +To: stable@vger.kernel.org, Greg KH +Cc: Dave Hansen , Thomas Gleixner , Borislav Petkov , Ingo Molnar , x86@kernel.org, "H. Peter Anvin" , Paolo Bonzini , Andy Lutomirski , Peter Zijlstra , Sean Christopherson , Robert O'Callahan , David Manouchehri , Kyle Huey +Message-ID: <20230109210214.71068-6-khuey@kylehuey.com> + +From: Kyle Huey + +From: Kyle Huey + +commit d7e5aceace51 upstream + +The hardware XRSTOR instruction resets the PKRU register to its hardware +init value (namely 0) if the PKRU bit is not set in the xfeatures mask. +Emulating that here restores the pre-5.14 behavior for PTRACE_SET_REGSET +with NT_X86_XSTATE, and makes sigreturn (which still uses XRSTOR) and +behave identically. + +Fixes: e84ba47e313d ("x86/fpu: Hook up PKRU into ptrace()") +Signed-off-by: Kyle Huey +Signed-off-by: Dave Hansen +Link: https://lore.kernel.org/all/20221115230932.7126-6-khuey%40kylehuey.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/fpu/xstate.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/arch/x86/kernel/fpu/xstate.c ++++ b/arch/x86/kernel/fpu/xstate.c +@@ -1168,7 +1168,8 @@ static int copy_uabi_to_xstate(struct xr + + xpkru = __raw_xsave_addr(xsave, XFEATURE_PKRU); + *pkru = xpkru->pkru; +- } ++ } else ++ *pkru = 0; + + /* + * The state that came in from userspace was user-state only. diff --git a/queue-5.15/x86-fpu-take-task_struct-in-copy_sigframe_from_user_to_xstate.patch b/queue-5.15/x86-fpu-take-task_struct-in-copy_sigframe_from_user_to_xstate.patch new file mode 100644 index 00000000000..3eef25b3a3d --- /dev/null +++ b/queue-5.15/x86-fpu-take-task_struct-in-copy_sigframe_from_user_to_xstate.patch @@ -0,0 +1,64 @@ +From me@kylehuey.com Mon Jan 9 22:02:33 2023 +From: Kyle Huey +Date: Mon, 9 Jan 2023 13:02:09 -0800 +Subject: x86/fpu: Take task_struct* in copy_sigframe_from_user_to_xstate() +To: stable@vger.kernel.org, Greg KH +Cc: Dave Hansen , Thomas Gleixner , Borislav Petkov , Ingo Molnar , x86@kernel.org, "H. Peter Anvin" , Paolo Bonzini , Andy Lutomirski , Peter Zijlstra , Sean Christopherson , Robert O'Callahan , David Manouchehri , Kyle Huey +Message-ID: <20230109210214.71068-2-khuey@kylehuey.com> + +From: Kyle Huey + +From: Kyle Huey + +commit 6a877d2450ac upstream + +This will allow copy_sigframe_from_user_to_xstate() to grab the address of +thread_struct's pkru value in a later patch. + +Signed-off-by: Kyle Huey +Signed-off-by: Dave Hansen +Link: https://lore.kernel.org/all/20221115230932.7126-2-khuey%40kylehuey.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/fpu/xstate.h | 2 +- + arch/x86/kernel/fpu/signal.c | 2 +- + arch/x86/kernel/fpu/xstate.c | 4 ++-- + 3 files changed, 4 insertions(+), 4 deletions(-) + +--- a/arch/x86/include/asm/fpu/xstate.h ++++ b/arch/x86/include/asm/fpu/xstate.h +@@ -137,7 +137,7 @@ extern void __init update_regset_xstate_ + void *get_xsave_addr(struct xregs_state *xsave, int xfeature_nr); + int xfeature_size(int xfeature_nr); + int copy_uabi_from_kernel_to_xstate(struct xregs_state *xsave, const void *kbuf); +-int copy_sigframe_from_user_to_xstate(struct xregs_state *xsave, const void __user *ubuf); ++int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, const void __user *ubuf); + + void xsaves(struct xregs_state *xsave, u64 mask); + void xrstors(struct xregs_state *xsave, u64 mask); +--- a/arch/x86/kernel/fpu/signal.c ++++ b/arch/x86/kernel/fpu/signal.c +@@ -370,7 +370,7 @@ static int __fpu_restore_sig(void __user + fpregs_unlock(); + + if (use_xsave() && !fx_only) { +- ret = copy_sigframe_from_user_to_xstate(&fpu->state.xsave, buf_fx); ++ ret = copy_sigframe_from_user_to_xstate(tsk, buf_fx); + if (ret) + return ret; + } else { +--- a/arch/x86/kernel/fpu/xstate.c ++++ b/arch/x86/kernel/fpu/xstate.c +@@ -1169,10 +1169,10 @@ int copy_uabi_from_kernel_to_xstate(stru + * XSAVE[S] format and copy to the target thread. This is called from the + * sigreturn() and rt_sigreturn() system calls. + */ +-int copy_sigframe_from_user_to_xstate(struct xregs_state *xsave, ++int copy_sigframe_from_user_to_xstate(struct task_struct *tsk, + const void __user *ubuf) + { +- return copy_uabi_to_xstate(xsave, NULL, ubuf); ++ return copy_uabi_to_xstate(&tsk->thread.fpu.state.xsave, NULL, ubuf); + } + + static bool validate_xsaves_xrstors(u64 mask) -- 2.47.3