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
+

Reply via email to