commit: 3cf228ef3b389e949f1242512c85121af823b397 Author: Mike Pagano <mpagano <AT> gentoo <DOT> org> AuthorDate: Wed Dec 11 21:01:01 2024 +0000 Commit: Mike Pagano <mpagano <AT> gentoo <DOT> org> CommitDate: Wed Dec 11 21:01:01 2024 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=3cf228ef
Add x86/pkeys fixes Bug: https://bugs.gentoo.org/946182 Signed-off-by: Mike Pagano <mpagano <AT> gentoo.org> 0000_README | 8 ++ ...-change-caller-of-update_pkru_in_sigframe.patch | 107 +++++++++++++++++++++ ...eys-ensure-updated-pkru-value-is-xrstor-d.patch | 96 ++++++++++++++++++ 3 files changed, 211 insertions(+) diff --git a/0000_README b/0000_README index b2e6beb3..81375872 100644 --- a/0000_README +++ b/0000_README @@ -71,6 +71,14 @@ Patch: 1730_parisc-Disable-prctl.patch From: https://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux.git Desc: prctl: Temporarily disable prctl(PR_SET_MDWE) on parisc +Patch: 1740_x86-pkeys-change-caller-of-update_pkru_in_sigframe.patch +From: https://git.kernel.org/ +Desc: x86/pkeys: Change caller of update_pkru_in_sigframe() + +Patch: 1741_x86-pkeys-ensure-updated-pkru-value-is-xrstor-d.patch +From: https://git.kernel.org/ +Desc: x86/pkeys: Ensure updated PKRU value is XRSTOR'd + Patch: 2000_BT-Check-key-sizes-only-if-Secure-Simple-Pairing-enabled.patch From: https://lore.kernel.org/linux-bluetooth/[email protected]/raw Desc: Bluetooth: Check key sizes only when Secure Simple Pairing is enabled. See bug #686758 diff --git a/1740_x86-pkeys-change-caller-of-update_pkru_in_sigframe.patch b/1740_x86-pkeys-change-caller-of-update_pkru_in_sigframe.patch new file mode 100644 index 00000000..3a1fbd82 --- /dev/null +++ b/1740_x86-pkeys-change-caller-of-update_pkru_in_sigframe.patch @@ -0,0 +1,107 @@ +From 5683d0ce8fb46f36315a2b508f90ec6221cda018 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <[email protected]> +Date: Tue, 19 Nov 2024 17:45:19 +0000 +Subject: x86/pkeys: Change caller of update_pkru_in_sigframe() + +From: Aruna Ramakrishna <[email protected]> + +[ Upstream commit 6a1853bdf17874392476b552398df261f75503e0 ] + +update_pkru_in_sigframe() will shortly need some information which +is only available inside xsave_to_user_sigframe(). Move +update_pkru_in_sigframe() inside the other function to make it +easier to provide it that information. + +No functional changes. + +Signed-off-by: Aruna Ramakrishna <[email protected]> +Signed-off-by: Dave Hansen <[email protected]> +Link: https://lore.kernel.org/all/20241119174520.3987538-2-aruna.ramakrishna%40oracle.com +Stable-dep-of: ae6012d72fa6 ("x86/pkeys: Ensure updated PKRU value is XRSTOR'd") +Signed-off-by: Sasha Levin <[email protected]> +--- + arch/x86/kernel/fpu/signal.c | 20 ++------------------ + arch/x86/kernel/fpu/xstate.h | 15 ++++++++++++++- + 2 files changed, 16 insertions(+), 19 deletions(-) + +diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c +index 1065ab995305c..8f62e0666dea5 100644 +--- a/arch/x86/kernel/fpu/signal.c ++++ b/arch/x86/kernel/fpu/signal.c +@@ -63,16 +63,6 @@ static inline bool check_xstate_in_sigframe(struct fxregs_state __user *fxbuf, + return true; + } + +-/* +- * Update the value of PKRU register that was already pushed onto the signal frame. +- */ +-static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pkru) +-{ +- if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE))) +- return 0; +- return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); +-} +- + /* + * Signal frame handlers. + */ +@@ -168,14 +158,8 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame, + + static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf, u32 pkru) + { +- int err = 0; +- +- if (use_xsave()) { +- err = xsave_to_user_sigframe(buf); +- if (!err) +- err = update_pkru_in_sigframe(buf, pkru); +- return err; +- } ++ if (use_xsave()) ++ return xsave_to_user_sigframe(buf, pkru); + + if (use_fxsr()) + return fxsave_to_user_sigframe((struct fxregs_state __user *) buf); +diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h +index 0b86a5002c846..6b2924fbe5b8d 100644 +--- a/arch/x86/kernel/fpu/xstate.h ++++ b/arch/x86/kernel/fpu/xstate.h +@@ -69,6 +69,16 @@ static inline u64 xfeatures_mask_independent(void) + return fpu_kernel_cfg.independent_features; + } + ++/* ++ * Update the value of PKRU register that was already pushed onto the signal frame. ++ */ ++static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pkru) ++{ ++ if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE))) ++ return 0; ++ return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); ++} ++ + /* XSAVE/XRSTOR wrapper functions */ + + #ifdef CONFIG_X86_64 +@@ -256,7 +266,7 @@ static inline u64 xfeatures_need_sigframe_write(void) + * The caller has to zero buf::header before calling this because XSAVE* + * does not touch the reserved fields in the header. + */ +-static inline int xsave_to_user_sigframe(struct xregs_state __user *buf) ++static inline int xsave_to_user_sigframe(struct xregs_state __user *buf, u32 pkru) + { + /* + * Include the features which are not xsaved/rstored by the kernel +@@ -281,6 +291,9 @@ static inline int xsave_to_user_sigframe(struct xregs_state __user *buf) + XSTATE_OP(XSAVE, buf, lmask, hmask, err); + clac(); + ++ if (!err) ++ err = update_pkru_in_sigframe(buf, pkru); ++ + return err; + } + +-- +2.43.0 + diff --git a/1741_x86-pkeys-ensure-updated-pkru-value-is-xrstor-d.patch b/1741_x86-pkeys-ensure-updated-pkru-value-is-xrstor-d.patch new file mode 100644 index 00000000..11b1f768 --- /dev/null +++ b/1741_x86-pkeys-ensure-updated-pkru-value-is-xrstor-d.patch @@ -0,0 +1,96 @@ +From 24fedf2768fd57e0d767137044c4f7493357b325 Mon Sep 17 00:00:00 2001 +From: Sasha Levin <[email protected]> +Date: Tue, 19 Nov 2024 17:45:20 +0000 +Subject: x86/pkeys: Ensure updated PKRU value is XRSTOR'd + +From: Aruna Ramakrishna <[email protected]> + +[ Upstream commit ae6012d72fa60c9ff92de5bac7a8021a47458e5b ] + +When XSTATE_BV[i] is 0, and XRSTOR attempts to restore state component +'i' it ignores any value in the XSAVE buffer and instead restores the +state component's init value. + +This means that if XSAVE writes XSTATE_BV[PKRU]=0 then XRSTOR will +ignore the value that update_pkru_in_sigframe() writes to the XSAVE buffer. + +XSTATE_BV[PKRU] only gets written as 0 if PKRU is in its init state. On +Intel CPUs, basically never happens because the kernel usually +overwrites the init value (aside: this is why we didn't notice this bug +until now). But on AMD, the init tracker is more aggressive and will +track PKRU as being in its init state upon any wrpkru(0x0). +Unfortunately, sig_prepare_pkru() does just that: wrpkru(0x0). + +This writes XSTATE_BV[PKRU]=0 which makes XRSTOR ignore the PKRU value +in the sigframe. + +To fix this, always overwrite the sigframe XSTATE_BV with a value that +has XSTATE_BV[PKRU]==1. This ensures that XRSTOR will not ignore what +update_pkru_in_sigframe() wrote. + +The problematic sequence of events is something like this: + +Userspace does: + * wrpkru(0xffff0000) (or whatever) + * Hardware sets: XINUSE[PKRU]=1 +Signal happens, kernel is entered: + * sig_prepare_pkru() => wrpkru(0x00000000) + * Hardware sets: XINUSE[PKRU]=0 (aggressive AMD init tracker) + * XSAVE writes most of XSAVE buffer, including + XSTATE_BV[PKRU]=XINUSE[PKRU]=0 + * update_pkru_in_sigframe() overwrites PKRU in XSAVE buffer +... signal handling + * XRSTOR sees XSTATE_BV[PKRU]==0, ignores just-written value + from update_pkru_in_sigframe() + +Fixes: 70044df250d0 ("x86/pkeys: Update PKRU to enable all pkeys before XSAVE") +Suggested-by: Rudi Horn <[email protected]> +Signed-off-by: Aruna Ramakrishna <[email protected]> +Signed-off-by: Dave Hansen <[email protected]> +Acked-by: Dave Hansen <[email protected]> +Link: https://lore.kernel.org/all/20241119174520.3987538-3-aruna.ramakrishna%40oracle.com +Signed-off-by: Sasha Levin <[email protected]> +--- + arch/x86/kernel/fpu/xstate.h | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h +index 6b2924fbe5b8d..aa16f1a1bbcf1 100644 +--- a/arch/x86/kernel/fpu/xstate.h ++++ b/arch/x86/kernel/fpu/xstate.h +@@ -72,10 +72,22 @@ static inline u64 xfeatures_mask_independent(void) + /* + * Update the value of PKRU register that was already pushed onto the signal frame. + */ +-static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pkru) ++static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u64 mask, u32 pkru) + { ++ u64 xstate_bv; ++ int err; ++ + if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE))) + return 0; ++ ++ /* Mark PKRU as in-use so that it is restored correctly. */ ++ xstate_bv = (mask & xfeatures_in_use()) | XFEATURE_MASK_PKRU; ++ ++ err = __put_user(xstate_bv, &buf->header.xfeatures); ++ if (err) ++ return err; ++ ++ /* Update PKRU value in the userspace xsave buffer. */ + return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU)); + } + +@@ -292,7 +304,7 @@ static inline int xsave_to_user_sigframe(struct xregs_state __user *buf, u32 pkr + clac(); + + if (!err) +- err = update_pkru_in_sigframe(buf, pkru); ++ err = update_pkru_in_sigframe(buf, mask, pkru); + + return err; + } +-- +2.43.0 +
