Jiri Slaby 2e024a
From: Dave Hansen <dave.hansen@linux.intel.com>
Jiri Slaby 2e024a
Date: Tue, 21 Feb 2023 12:30:15 -0800
Jiri Slaby 2e024a
Subject: [PATCH] uaccess: Add speculation barrier to copy_from_user()
Jiri Slaby 2e024a
References: bsc#1012628
Jiri Slaby 2e024a
Patch-mainline: 6.2.1
Jiri Slaby 2e024a
Git-commit: 74e19ef0ff8061ef55957c3abd71614ef0f42f47
Jiri Slaby 2e024a
Jiri Slaby 2e024a
commit 74e19ef0ff8061ef55957c3abd71614ef0f42f47 upstream.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
The results of "access_ok()" can be mis-speculated.  The result is that
Jiri Slaby 2e024a
you can end speculatively:
Jiri Slaby 2e024a
Jiri Slaby 2e024a
	if (access_ok(from, size))
Jiri Slaby 2e024a
		// Right here
Jiri Slaby 2e024a
Jiri Slaby 2e024a
even for bad from/size combinations.  On first glance, it would be ideal
Jiri Slaby 2e024a
to just add a speculation barrier to "access_ok()" so that its results
Jiri Slaby 2e024a
can never be mis-speculated.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
But there are lots of system calls just doing access_ok() via
Jiri Slaby 2e024a
"copy_to_user()" and friends (example: fstat() and friends).  Those are
Jiri Slaby 2e024a
generally not problematic because they do not _consume_ data from
Jiri Slaby 2e024a
userspace other than the pointer.  They are also very quick and common
Jiri Slaby 2e024a
system calls that should not be needlessly slowed down.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
"copy_from_user()" on the other hand uses a user-controller pointer and
Jiri Slaby 2e024a
is frequently followed up with code that might affect caches.  Take
Jiri Slaby 2e024a
something like this:
Jiri Slaby 2e024a
Jiri Slaby 2e024a
	if (!copy_from_user(&kernelvar, uptr, size))
Jiri Slaby 2e024a
		do_something_with(kernelvar);
Jiri Slaby 2e024a
Jiri Slaby 2e024a
If userspace passes in an evil 'uptr' that *actually* points to a kernel
Jiri Slaby 2e024a
addresses, and then do_something_with() has cache (or other)
Jiri Slaby 2e024a
side-effects, it could allow userspace to infer kernel data values.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
Add a barrier to the common copy_from_user() code to prevent
Jiri Slaby 2e024a
mis-speculated values which happen after the copy.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
Also add a stub for architectures that do not define barrier_nospec().
Jiri Slaby 2e024a
This makes the macro usable in generic code.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
Since the barrier is now usable in generic code, the x86 #ifdef in the
Jiri Slaby 2e024a
BPF code can also go away.
Jiri Slaby 2e024a
Jiri Slaby 2e024a
Reported-by: Jordy Zomer <jordyzomer@google.com>
Jiri Slaby 2e024a
Suggested-by: Linus Torvalds <torvalds@linuxfoundation.org>
Jiri Slaby 2e024a
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Jiri Slaby 2e024a
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Jiri Slaby 2e024a
Acked-by: Daniel Borkmann <daniel@iogearbox.net>   # BPF bits
Jiri Slaby 2e024a
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Jiri Slaby 2e024a
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Jiri Slaby 2e024a
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Jiri Slaby 2e024a
---
Jiri Slaby 2e024a
 include/linux/nospec.h | 4 ++++
Jiri Slaby 2e024a
 kernel/bpf/core.c      | 2 --
Jiri Slaby 2e024a
 lib/usercopy.c         | 7 +++++++
Jiri Slaby 2e024a
 3 files changed, 11 insertions(+), 2 deletions(-)
Jiri Slaby 2e024a
Jiri Slaby 2e024a
diff --git a/include/linux/nospec.h b/include/linux/nospec.h
Jiri Slaby 2e024a
index c1e79f72..9f0af4f1 100644
Jiri Slaby 2e024a
--- a/include/linux/nospec.h
Jiri Slaby 2e024a
+++ b/include/linux/nospec.h
Jiri Slaby 2e024a
@@ -11,6 +11,10 @@
Jiri Slaby 2e024a
 
Jiri Slaby 2e024a
 struct task_struct;
Jiri Slaby 2e024a
 
Jiri Slaby 2e024a
+#ifndef barrier_nospec
Jiri Slaby 2e024a
+# define barrier_nospec() do { } while (0)
Jiri Slaby 2e024a
+#endif
Jiri Slaby 2e024a
+
Jiri Slaby 2e024a
 /**
Jiri Slaby 2e024a
  * array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
Jiri Slaby 2e024a
  * @index: array element index
Jiri Slaby 2e024a
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
Jiri Slaby 2e024a
index ba3fff17..430c66d5 100644
Jiri Slaby 2e024a
--- a/kernel/bpf/core.c
Jiri Slaby 2e024a
+++ b/kernel/bpf/core.c
Jiri Slaby 2e024a
@@ -1910,9 +1910,7 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
Jiri Slaby 2e024a
 		 * reuse preexisting logic from Spectre v1 mitigation that
Jiri Slaby 2e024a
 		 * happens to produce the required code on x86 for v4 as well.
Jiri Slaby 2e024a
 		 */
Jiri Slaby 2e024a
-#ifdef CONFIG_X86
Jiri Slaby 2e024a
 		barrier_nospec();
Jiri Slaby 2e024a
-#endif
Jiri Slaby 2e024a
 		CONT;
Jiri Slaby 2e024a
 #define LDST(SIZEOP, SIZE)						\
Jiri Slaby 2e024a
 	STX_MEM_##SIZEOP:						\
Jiri Slaby 2e024a
diff --git a/lib/usercopy.c b/lib/usercopy.c
Jiri Slaby 2e024a
index 1505a52f..d29fe29c 100644
Jiri Slaby 2e024a
--- a/lib/usercopy.c
Jiri Slaby 2e024a
+++ b/lib/usercopy.c
Jiri Slaby 2e024a
@@ -3,6 +3,7 @@
Jiri Slaby 2e024a
 #include <linux/fault-inject-usercopy.h>
Jiri Slaby 2e024a
 #include <linux/instrumented.h>
Jiri Slaby 2e024a
 #include <linux/uaccess.h>
Jiri Slaby 2e024a
+#include <linux/nospec.h>
Jiri Slaby 2e024a
 
Jiri Slaby 2e024a
 /* out-of-line parts */
Jiri Slaby 2e024a
 
Jiri Slaby 2e024a
@@ -12,6 +13,12 @@ unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n
Jiri Slaby 2e024a
 	unsigned long res = n;
Jiri Slaby 2e024a
 	might_fault();
Jiri Slaby 2e024a
 	if (!should_fail_usercopy() && likely(access_ok(from, n))) {
Jiri Slaby 2e024a
+		/*
Jiri Slaby 2e024a
+		 * Ensure that bad access_ok() speculation will not
Jiri Slaby 2e024a
+		 * lead to nasty side effects *after* the copy is
Jiri Slaby 2e024a
+		 * finished:
Jiri Slaby 2e024a
+		 */
Jiri Slaby 2e024a
+		barrier_nospec();
Jiri Slaby 2e024a
 		instrument_copy_from_user_before(to, from, n);
Jiri Slaby 2e024a
 		res = raw_copy_from_user(to, from, n);
Jiri Slaby 2e024a
 		instrument_copy_from_user_after(to, from, n, res);
Jiri Slaby 2e024a
-- 
Jiri Slaby 2e024a
2.35.3
Jiri Slaby 2e024a