]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.11-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 28 Oct 2024 01:39:21 +0000 (02:39 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 28 Oct 2024 01:39:21 +0000 (02:39 +0100)
added patches:
platform-x86-dell-wmi-ignore-suspend-notifications.patch
x86-fix-user-address-masking-non-canonical-speculation-issue.patch
x86-fix-whitespace-in-runtime-const-assembler-output.patch
x86-support-user-address-masking-instead-of-non-speculative-conditional.patch

queue-6.11/platform-x86-dell-wmi-ignore-suspend-notifications.patch [new file with mode: 0644]
queue-6.11/series
queue-6.11/x86-fix-user-address-masking-non-canonical-speculation-issue.patch [new file with mode: 0644]
queue-6.11/x86-fix-whitespace-in-runtime-const-assembler-output.patch [new file with mode: 0644]
queue-6.11/x86-support-user-address-masking-instead-of-non-speculative-conditional.patch [new file with mode: 0644]

diff --git a/queue-6.11/platform-x86-dell-wmi-ignore-suspend-notifications.patch b/queue-6.11/platform-x86-dell-wmi-ignore-suspend-notifications.patch
new file mode 100644 (file)
index 0000000..a6675ca
--- /dev/null
@@ -0,0 +1,44 @@
+From a7990957fa53326fe9b47f0349373ed99bb69aaa Mon Sep 17 00:00:00 2001
+From: Armin Wolf <W_Armin@gmx.de>
+Date: Tue, 15 Oct 2024 00:05:29 +0200
+Subject: platform/x86: dell-wmi: Ignore suspend notifications
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Armin Wolf <W_Armin@gmx.de>
+
+commit a7990957fa53326fe9b47f0349373ed99bb69aaa upstream.
+
+Some machines like the Dell G15 5155 emit WMI events when
+suspending/resuming. Ignore those WMI events.
+
+Tested-by: siddharth.manthan@gmail.com
+Signed-off-by: Armin Wolf <W_Armin@gmx.de>
+Acked-by: Pali Rohár <pali@kernel.org>
+Link: https://lore.kernel.org/r/20241014220529.397390-1-W_Armin@gmx.de
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/platform/x86/dell/dell-wmi-base.c |    9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/drivers/platform/x86/dell/dell-wmi-base.c
++++ b/drivers/platform/x86/dell/dell-wmi-base.c
+@@ -264,6 +264,15 @@ static const struct key_entry dell_wmi_k
+       /*Speaker Mute*/
+       { KE_KEY, 0x109, { KEY_MUTE} },
++      /* S2Idle screen off */
++      { KE_IGNORE, 0x120, { KEY_RESERVED }},
++
++      /* Leaving S4 or S2Idle suspend */
++      { KE_IGNORE, 0x130, { KEY_RESERVED }},
++
++      /* Entering S2Idle suspend */
++      { KE_IGNORE, 0x140, { KEY_RESERVED }},
++
+       /* Mic mute */
+       { KE_KEY, 0x150, { KEY_MICMUTE } },
index 6d47cd3e4157481871b78189cfdccc9d0e41121d..1df88ddf4f463569e76690a674b69c26e7671f15 100644 (file)
@@ -251,3 +251,7 @@ revert-fs-9p-remove-redundant-pointer-v9ses.patch
 revert-fs-9p-fix-uaf-in-in-v9fs_stat2inode_dotl.patch
 revert-fs-9p-simplify-iget-to-remove-unnecessary-paths.patch
 soundwire-intel_ace2x-send-pdi-stream-number-during-prepare.patch
+x86-support-user-address-masking-instead-of-non-speculative-conditional.patch
+x86-fix-whitespace-in-runtime-const-assembler-output.patch
+x86-fix-user-address-masking-non-canonical-speculation-issue.patch
+platform-x86-dell-wmi-ignore-suspend-notifications.patch
diff --git a/queue-6.11/x86-fix-user-address-masking-non-canonical-speculation-issue.patch b/queue-6.11/x86-fix-user-address-masking-non-canonical-speculation-issue.patch
new file mode 100644 (file)
index 0000000..4680401
--- /dev/null
@@ -0,0 +1,186 @@
+From 86e6b1547b3d013bc392adf775b89318441403c2 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Wed, 23 Oct 2024 18:17:46 -0700
+Subject: x86: fix user address masking non-canonical speculation issue
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 86e6b1547b3d013bc392adf775b89318441403c2 upstream.
+
+It turns out that AMD has a "Meltdown Lite(tm)" issue with non-canonical
+accesses in kernel space.  And so using just the high bit to decide
+whether an access is in user space or kernel space ends up with the good
+old "leak speculative data" if you have the right gadget using the
+result:
+
+  CVE-2020-12965 “Transient Execution of Non-Canonical Accesses“
+
+Now, the kernel surrounds the access with a STAC/CLAC pair, and those
+instructions end up serializing execution on older Zen architectures,
+which closes the speculation window.
+
+But that was true only up until Zen 5, which renames the AC bit [1].
+That improves performance of STAC/CLAC a lot, but also means that the
+speculation window is now open.
+
+Note that this affects not just the new address masking, but also the
+regular valid_user_address() check used by access_ok(), and the asm
+version of the sign bit check in the get_user() helpers.
+
+It does not affect put_user() or clear_user() variants, since there's no
+speculative result to be used in a gadget for those operations.
+
+Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
+Link: https://lore.kernel.org/all/80d94591-1297-4afb-b510-c665efd37f10@citrix.com/
+Link: https://lore.kernel.org/all/20241023094448.GAZxjFkEOOF_DM83TQ@fat_crate.local/ [1]
+Link: https://www.amd.com/en/resources/product-security/bulletin/amd-sb-1010.html
+Link: https://arxiv.org/pdf/2108.10771
+Cc: Josh Poimboeuf <jpoimboe@kernel.org>
+Cc: Borislav Petkov <bp@alien8.de>
+Tested-by: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com> # LAM case
+Fixes: 2865baf54077 ("x86: support user address masking instead of non-speculative conditional")
+Fixes: 6014bc27561f ("x86-64: make access_ok() independent of LAM")
+Fixes: b19b74bc99b1 ("x86/mm: Rework address range check in get_user() and put_user()")
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/uaccess_64.h |   43 +++++++++++++++++++++-----------------
+ arch/x86/kernel/cpu/common.c      |   10 ++++++++
+ arch/x86/kernel/vmlinux.lds.S     |    1 
+ arch/x86/lib/getuser.S            |    9 ++++++-
+ 4 files changed, 42 insertions(+), 21 deletions(-)
+
+--- a/arch/x86/include/asm/uaccess_64.h
++++ b/arch/x86/include/asm/uaccess_64.h
+@@ -12,6 +12,13 @@
+ #include <asm/cpufeatures.h>
+ #include <asm/page.h>
+ #include <asm/percpu.h>
++#include <asm/runtime-const.h>
++
++/*
++ * Virtual variable: there's no actual backing store for this,
++ * it can purely be used as 'runtime_const_ptr(USER_PTR_MAX)'
++ */
++extern unsigned long USER_PTR_MAX;
+ #ifdef CONFIG_ADDRESS_MASKING
+ /*
+@@ -46,19 +53,24 @@ static inline unsigned long __untagged_a
+ #endif
+-/*
+- * The virtual address space space is logically divided into a kernel
+- * half and a user half.  When cast to a signed type, user pointers
+- * are positive and kernel pointers are negative.
+- */
+-#define valid_user_address(x) ((__force long)(x) >= 0)
++#define valid_user_address(x) \
++      ((__force unsigned long)(x) <= runtime_const_ptr(USER_PTR_MAX))
+ /*
+  * Masking the user address is an alternative to a conditional
+  * user_access_begin that can avoid the fencing. This only works
+  * for dense accesses starting at the address.
+  */
+-#define mask_user_address(x) ((typeof(x))((long)(x)|((long)(x)>>63)))
++static inline void __user *mask_user_address(const void __user *ptr)
++{
++      unsigned long mask;
++      asm("cmp %1,%0\n\t"
++          "sbb %0,%0"
++              :"=r" (mask)
++              :"r" (ptr),
++               "0" (runtime_const_ptr(USER_PTR_MAX)));
++      return (__force void __user *)(mask | (__force unsigned long)ptr);
++}
+ #define masked_user_access_begin(x) ({ __uaccess_begin(); mask_user_address(x); })
+ /*
+@@ -66,23 +78,16 @@ static inline unsigned long __untagged_a
+  * arbitrary values in those bits rather then masking them off.
+  *
+  * Enforce two rules:
+- * 1. 'ptr' must be in the user half of the address space
++ * 1. 'ptr' must be in the user part of the address space
+  * 2. 'ptr+size' must not overflow into kernel addresses
+  *
+- * Note that addresses around the sign change are not valid addresses,
+- * and will GP-fault even with LAM enabled if the sign bit is set (see
+- * "CR3.LAM_SUP" that can narrow the canonicality check if we ever
+- * enable it, but not remove it entirely).
+- *
+- * So the "overflow into kernel addresses" does not imply some sudden
+- * exact boundary at the sign bit, and we can allow a lot of slop on the
+- * size check.
++ * Note that we always have at least one guard page between the
++ * max user address and the non-canonical gap, allowing us to
++ * ignore small sizes entirely.
+  *
+  * In fact, we could probably remove the size check entirely, since
+  * any kernel accesses will be in increasing address order starting
+- * at 'ptr', and even if the end might be in kernel space, we'll
+- * hit the GP faults for non-canonical accesses before we ever get
+- * there.
++ * at 'ptr'.
+  *
+  * That's a separate optimization, for now just handle the small
+  * constant case.
+--- a/arch/x86/kernel/cpu/common.c
++++ b/arch/x86/kernel/cpu/common.c
+@@ -69,6 +69,7 @@
+ #include <asm/sev.h>
+ #include <asm/tdx.h>
+ #include <asm/posted_intr.h>
++#include <asm/runtime-const.h>
+ #include "cpu.h"
+@@ -2371,6 +2372,15 @@ void __init arch_cpu_finalize_init(void)
+       alternative_instructions();
+       if (IS_ENABLED(CONFIG_X86_64)) {
++              unsigned long USER_PTR_MAX = TASK_SIZE_MAX-1;
++
++              /*
++               * Enable this when LAM is gated on LASS support
++              if (cpu_feature_enabled(X86_FEATURE_LAM))
++                      USER_PTR_MAX = (1ul << 63) - PAGE_SIZE - 1;
++               */
++              runtime_const_init(ptr, USER_PTR_MAX);
++
+               /*
+                * Make sure the first 2MB area is not mapped by huge pages
+                * There are typically fixed size MTRRs in there and overlapping
+--- a/arch/x86/kernel/vmlinux.lds.S
++++ b/arch/x86/kernel/vmlinux.lds.S
+@@ -359,6 +359,7 @@ SECTIONS
+       RUNTIME_CONST(shift, d_hash_shift)
+       RUNTIME_CONST(ptr, dentry_hashtable)
++      RUNTIME_CONST(ptr, USER_PTR_MAX)
+       . = ALIGN(PAGE_SIZE);
+--- a/arch/x86/lib/getuser.S
++++ b/arch/x86/lib/getuser.S
+@@ -39,8 +39,13 @@
+ .macro check_range size:req
+ .if IS_ENABLED(CONFIG_X86_64)
+-      mov %rax, %rdx
+-      sar $63, %rdx
++      movq $0x0123456789abcdef,%rdx
++  1:
++  .pushsection runtime_ptr_USER_PTR_MAX,"a"
++      .long 1b - 8 - .
++  .popsection
++      cmp %rax, %rdx
++      sbb %rdx, %rdx
+       or %rdx, %rax
+ .else
+       cmp $TASK_SIZE_MAX-\size+1, %eax
diff --git a/queue-6.11/x86-fix-whitespace-in-runtime-const-assembler-output.patch b/queue-6.11/x86-fix-whitespace-in-runtime-const-assembler-output.patch
new file mode 100644 (file)
index 0000000..9222d59
--- /dev/null
@@ -0,0 +1,39 @@
+From 4dc1f31ec3f13a065c7ae2ccdec562b0123e21bb Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Thu, 24 Oct 2024 13:23:56 -0700
+Subject: x86: fix whitespace in runtime-const assembler output
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 4dc1f31ec3f13a065c7ae2ccdec562b0123e21bb upstream.
+
+The x86 user pointer validation changes made me look at compiler output
+a lot, and the wrong indentation for the ".popsection" in the generated
+assembler triggered me.
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/runtime-const.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/x86/include/asm/runtime-const.h
++++ b/arch/x86/include/asm/runtime-const.h
+@@ -6,7 +6,7 @@
+       typeof(sym) __ret;                                      \
+       asm_inline("mov %1,%0\n1:\n"                            \
+               ".pushsection runtime_ptr_" #sym ",\"a\"\n\t"   \
+-              ".long 1b - %c2 - .\n\t"                        \
++              ".long 1b - %c2 - .\n"                          \
+               ".popsection"                                   \
+               :"=r" (__ret)                                   \
+               :"i" ((unsigned long)0x0123456789abcdefull),    \
+@@ -20,7 +20,7 @@
+       typeof(0u+(val)) __ret = (val);                         \
+       asm_inline("shrl $12,%k0\n1:\n"                         \
+               ".pushsection runtime_shift_" #sym ",\"a\"\n\t" \
+-              ".long 1b - 1 - .\n\t"                          \
++              ".long 1b - 1 - .\n"                            \
+               ".popsection"                                   \
+               :"+r" (__ret));                                 \
+       __ret; })
diff --git a/queue-6.11/x86-support-user-address-masking-instead-of-non-speculative-conditional.patch b/queue-6.11/x86-support-user-address-masking-instead-of-non-speculative-conditional.patch
new file mode 100644 (file)
index 0000000..1a0346d
--- /dev/null
@@ -0,0 +1,147 @@
+From 2865baf54077aa98fcdb478cefe6a42c417b9374 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Mon, 8 Apr 2024 20:04:58 -0700
+Subject: x86: support user address masking instead of non-speculative conditional
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 2865baf54077aa98fcdb478cefe6a42c417b9374 upstream.
+
+The Spectre-v1 mitigations made "access_ok()" much more expensive, since
+it has to serialize execution with the test for a valid user address.
+
+All the normal user copy routines avoid this by just masking the user
+address with a data-dependent mask instead, but the fast
+"unsafe_user_read()" kind of patterms that were supposed to be a fast
+case got slowed down.
+
+This introduces a notion of using
+
+       src = masked_user_access_begin(src);
+
+to do the user address sanity using a data-dependent mask instead of the
+more traditional conditional
+
+       if (user_read_access_begin(src, len)) {
+
+model.
+
+This model only works for dense accesses that start at 'src' and on
+architectures that have a guard region that is guaranteed to fault in
+between the user space and the kernel space area.
+
+With this, the user access doesn't need to be manually checked, because
+a bad address is guaranteed to fault (by some architecture masking
+trick: on x86-64 this involves just turning an invalid user address into
+all ones, since we don't map the top of address space).
+
+This only converts a couple of examples for now.  Example x86-64 code
+generation for loading two words from user space:
+
+        stac
+        mov    %rax,%rcx
+        sar    $0x3f,%rcx
+        or     %rax,%rcx
+        mov    (%rcx),%r13
+        mov    0x8(%rcx),%r14
+        clac
+
+where all the error handling and -EFAULT is now purely handled out of
+line by the exception path.
+
+Of course, if the micro-architecture does badly at 'clac' and 'stac',
+the above is still pitifully slow.  But at least we did as well as we
+could.
+
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/include/asm/uaccess_64.h |    8 ++++++++
+ fs/select.c                       |    4 +++-
+ include/linux/uaccess.h           |    7 +++++++
+ lib/strncpy_from_user.c           |    9 +++++++++
+ lib/strnlen_user.c                |    9 +++++++++
+ 5 files changed, 36 insertions(+), 1 deletion(-)
+
+--- a/arch/x86/include/asm/uaccess_64.h
++++ b/arch/x86/include/asm/uaccess_64.h
+@@ -54,6 +54,14 @@ static inline unsigned long __untagged_a
+ #define valid_user_address(x) ((__force long)(x) >= 0)
+ /*
++ * Masking the user address is an alternative to a conditional
++ * user_access_begin that can avoid the fencing. This only works
++ * for dense accesses starting at the address.
++ */
++#define mask_user_address(x) ((typeof(x))((long)(x)|((long)(x)>>63)))
++#define masked_user_access_begin(x) ({ __uaccess_begin(); mask_user_address(x); })
++
++/*
+  * User pointers can have tag bits on x86-64.  This scheme tolerates
+  * arbitrary values in those bits rather then masking them off.
+  *
+--- a/fs/select.c
++++ b/fs/select.c
+@@ -780,7 +780,9 @@ static inline int get_sigset_argpack(str
+ {
+       // the path is hot enough for overhead of copy_from_user() to matter
+       if (from) {
+-              if (!user_read_access_begin(from, sizeof(*from)))
++              if (can_do_masked_user_access())
++                      from = masked_user_access_begin(from);
++              else if (!user_read_access_begin(from, sizeof(*from)))
+                       return -EFAULT;
+               unsafe_get_user(to->p, &from->p, Efault);
+               unsafe_get_user(to->size, &from->size, Efault);
+--- a/include/linux/uaccess.h
++++ b/include/linux/uaccess.h
+@@ -33,6 +33,13 @@
+ })
+ #endif
++#ifdef masked_user_access_begin
++ #define can_do_masked_user_access() 1
++#else
++ #define can_do_masked_user_access() 0
++ #define masked_user_access_begin(src) NULL
++#endif
++
+ /*
+  * Architectures should provide two primitives (raw_copy_{to,from}_user())
+  * and get rid of their private instances of copy_{to,from}_user() and
+--- a/lib/strncpy_from_user.c
++++ b/lib/strncpy_from_user.c
+@@ -120,6 +120,15 @@ long strncpy_from_user(char *dst, const
+       if (unlikely(count <= 0))
+               return 0;
++      if (can_do_masked_user_access()) {
++              long retval;
++
++              src = masked_user_access_begin(src);
++              retval = do_strncpy_from_user(dst, src, count, count);
++              user_read_access_end();
++              return retval;
++      }
++
+       max_addr = TASK_SIZE_MAX;
+       src_addr = (unsigned long)untagged_addr(src);
+       if (likely(src_addr < max_addr)) {
+--- a/lib/strnlen_user.c
++++ b/lib/strnlen_user.c
+@@ -96,6 +96,15 @@ long strnlen_user(const char __user *str
+       if (unlikely(count <= 0))
+               return 0;
++      if (can_do_masked_user_access()) {
++              long retval;
++
++              str = masked_user_access_begin(str);
++              retval = do_strnlen_user(str, count, count);
++              user_read_access_end();
++              return retval;
++      }
++
+       max_addr = TASK_SIZE_MAX;
+       src_addr = (unsigned long)untagged_addr(str);
+       if (likely(src_addr < max_addr)) {