View Issue Details

IDProjectCategoryView StatusLast Update
0015374CentOS-7kernel-pluspublic2019-09-14 00:50
Reporterkabe 
PrioritynormalSeveritymajorReproducibilityalways
Status resolvedResolutionfixed 
Product Version7.5.1804 
Target VersionFixed in Version 
Summary0015374: kernel-3.10.0-862.11.6.el7.centos.plus and after will not boot on Hyper-V
Descriptionkernel-3.10.0-862.11.6.el7.centos.plus and after will not boot on Hyper-V

boot kernel-3.10.0-862.11.6.el7.centos.plus.1.i686 on Hyper-V:

[ OK ] Started Tell Plymouth To Write Out Runtime Data.
[ OK ] Started Create Volatile Files and Directories.
         Starting Security Auditing Service...
         Mounting RPC Pipe File System...
[ 9.821271] RPC: Registered named UNIX socket transport module.
[ 9.823125] RPC: Registered udp transport module.
[ 9.824392] RPC: Registered tcp transport module.
[ 9.825467] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ OK ] Mounted RPC Pipe File System.
[ OK ] Reached target rpc_pipefs.target.
[ 9.934740] type=1305 audit(1539402565.382:4): audit_pid=320 old=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:auditd_t:s0 res=1

then freezes.
Newer kernel-3.10.862.14.4.el7.centos.plus.i686 freezes on the same location.
Older kernel-3.10.862.9.1.el7.centos.plus.i686 is the latest kernel which boots.

adding "l1tf=off nosmt" kernel option doesn't change things (cannot boot).
Steps To ReproduceInstall kernel-3.10.0-862.11.6.el6.centos.plus.1 on Client Hyper-V on Windows 10.
Additional InformationTo see more diagnostics, boot with kernel options:
single console=ttyS0 init=/bin/sh

After dropping to shell, invoking a command will make the init (/bin/sh)
SIGSEGV (exitcode=0x0000000b).
There's not much information in the backtrace.

Since the latest kernel is working flawlessly on real machine,
it could be regression on Hyper-V related drivers,
but drivers/hv and arch/x86/hyperv has only trivial changes.


[ OK ] Started Plymouth switch root service.
[ 3.029778] systemd-journald[74]: Received SIGTERM from PID 1 (systemd).
sh-4.2# [ 5.137207] psmouse serio1: trackpoint: IBM TrackPoint firmware: 0x01, buttons: 0/0
[ 5.147197] input: TPPS/2 IBM TrackPoint as /devices/platform/i8042/serio1/input/input3
[ 5.155562] input: AT Translated Set 2 keyboard as /devices/LNXSYSTM:00/device:00/PNP0A03:00/device:08/VMBUS:01/d34b2567-b9b6-42b9-8778-0a4ec0b955bf/serio2/input/input4

sh-4.2#
sh-4.2#
sh-4.2# echo *
bin boot dev etc export home lib lost+found media mnt opt proc root run sbin srv sys tmp usr var
sh-4.2#
sh-4.2#
sh-4.2# ls
bin dev export lib media opt root sbin sys usr
boot [ 12.437659] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 12.437659]
[ 12.438580] CPU: 0 PID: 1 Comm: sh Tainted: G W ------------ 3.10.0-862.11.6.el7.centos.plus.1.i686 #1
[ 12.438580] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS 090006 05/23/2012
[ 12.438580] Call Trace:
[ 12.438580] [<d59d81e3>] dump_stack+0x16/0x18
[ 12.438580] [<d59d418b>] panic+0x98/0x1b7
[ 12.438580] [<d545cc0b>] do_exit+0x8eb/0x8f0
[ 12.438580] [<d5468a17>] ? recalc_sigpending+0x17/0x50
[ 12.438580] [<d545cc84>] do_group_exit+0x34/0xa0
[ 12.438580] [<d546b319>] get_signal_to_deliver+0x189/0x590
[ 12.438580] [<d5416e95>] do_signal+0x45/0x960
[ 12.438580] [<d5468a17>] ? recalc_sigpending+0x17/0x50
[ 12.438580] [<d546945c>] ? __set_task_blocked+0x3c/0x90
[ 12.438580] [<d546b8c7>] ? __set_current_blocked+0x37/0x70
[ 12.438580] [<d546ba9f>] ? sigprocmask+0x7f/0xc0
[ 12.438580] [<d5417817>] do_notify_resume+0x67/0x80
[ 12.438580] [<d59df6b9>] work_notifysig+0x30/0x37
[ 12.438580] Kernel Offset: 0x14400000 from 0xc1000000 (relocation range: 0xc0000000-0xf7ffdfff)
[ 12.480357] ------------[ cut here ]------------
[ 12.481351] WARNING: CPU: 0 PID: 1 at arch/x86/kernel/smp.c:127 native_smp_send_reschedule+0x50/0x60
[ 12.481351] Modules linked in: ext4 mbcache jbd2 sr_mod cdrom ata_generic pata_acpi sd_mod crc_t10dif crct10dif_generic crct10dif_common hv_netvsc hv_storvsc scsi_transport_fc hyperv_keyboard hid_hyperv scsi_tgt ata_piix hyperv_fb crc32c_intel serio_raw libata floppy hv_vmbus
[ 12.481351] CPU: 0 PID: 1 Comm: sh Tainted: G W ------------ 3.10.0-862.11.6.el7.centos.plus.1.i686 #1
[ 12.481351] Hardware name: Microsoft Corporation Virtual Machine/Virtual Machine, BIOS 090006 05/23/2012
[ 12.481351] Call Trace:
[ 12.481351] [<d59d81e3>] dump_stack+0x16/0x18
[ 12.481351] [<d545645a>] __warn+0xea/0x110
[ 12.481351] [<d5438910>] ? native_smp_send_reschedule+0x50/0x60
[ 12.481351] [<d545656a>] warn_slowpath_null+0x2a/0x30
[ 12.481351] [<d5438910>] native_smp_send_reschedule+0x50/0x60
[ 12.481351] [<d5498d1d>] trigger_load_balance+0x13d/0x210
[ 12.481351] [<d5494420>] ? check_preempt_wakeup+0x210/0x210
[ 12.481351] [<d548b233>] scheduler_tick+0xe3/0x120
[ 12.481351] [<d5494420>] ? check_preempt_wakeup+0x210/0x210
[ 12.481351] [<d5467a78>] update_process_times+0x58/0x70
[ 12.481351] [<d54b9d99>] tick_sched_handle+0x29/0x70
[ 12.481351] [<d54ba5b3>] tick_sched_timer+0x33/0x80
[ 12.481351] [<d547de38>] ? __remove_hrtimer+0x38/0x90
[ 12.481351] [<d547e36c>] __hrtimer_run_queues+0xec/0x240
[ 12.481351] [<d54154d3>] ? read_hv_clock_msr+0x23/0x40
[ 12.481351] [<d54ba580>] ? tick_sched_do_timer+0x30/0x30
[ 12.481351] [<d547e7cd>] hrtimer_interrupt+0x9d/0x1d0
[ 12.481351] [<f805ccf4>] ? hv_ce_set_next_event+0x34/0x50 [hv_vmbus]
[ 12.481351] [<f805c78e>] vmbus_isr+0x1ce/0x250 [hv_vmbus]
[ 12.481351] [<d5437370>] hyperv_vector_handler+0x30/0x60
[ 12.481351] [<d59e76ec>] hyperv_callback_vector+0x34/0x3c
[ 12.481351] [<d56bbb89>] ? delay_tsc+0x59/0x90
[ 12.481351] [<d56bbac3>] __const_udelay+0x23/0x30
[ 12.481351] [<d5840eed>] i8042_panic_blink+0x7d/0x140
[ 12.481351] [<d54500d8>] ? iounmap_atomic+0x48/0x90
[ 12.481351] [<d59d4289>] panic+0x196/0x1b7
[ 12.481351] [<d545cc0b>] do_exit+0x8eb/0x8f0
[ 12.481351] [<d5468a17>] ? recalc_sigpending+0x17/0x50
[ 12.481351] [<d545cc84>] do_group_exit+0x34/0xa0
[ 12.481351] [<d546b319>] get_signal_to_deliver+0x189/0x590
[ 12.481351] [<d5416e95>] do_signal+0x45/0x960
[ 12.481351] [<d5468a17>] ? recalc_sigpending+0x17/0x50
[ 12.481351] [<d546945c>] ? __set_task_blocked+0x3c/0x90
[ 12.481351] [<d546b8c7>] ? __set_current_blocked+0x37/0x70
[ 12.481351] [<d546ba9f>] ? sigprocmask+0x7f/0xc0
[ 12.481351] [<d5417817>] do_notify_resume+0x67/0x80
[ 12.481351] [<d59df6b9>] work_notifysig+0x30/0x37
[ 12.481351] ---[ end trace f68728a0d3053b54 ]---
Tagsi386
abrt_hash
URL

Activities

pgreco

pgreco

2018-10-15 12:11

developer   ~0032920

@kabe
I agree with your analysis, but trivial or not, chances are, the problem is in the hv code.
I don't have access to Hyper-V, can you try reverting this patch https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?h=next-20181015&id=7fa32e5ec28b1609abc0b797b58267f725fc3964 ?
Thanks.
kabe

kabe

2018-10-16 02:16

reporter   ~0032924

I tried reverting whole drivers/hv/ (which is essentially same as the commit) but the symptom is same (cannot boot, init SIGSEGV).
arch/x86/hyperv/ is same in 862.9.1.el7 and 862.11.6.el7.
Other hv* and *hyperv* files are suprisingly identical.

My current thinking is that entry_32.S isn't updated properly for hypervisored code.
pgreco

pgreco

2018-10-17 09:56

developer   ~0032933

something like the first part of this commmit https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/arch/x86/kernel/entry_32.S?h=v3.16.59&id=8c34712ac217fff16d0d225bd48d68af40c33038 ?
Please remember that my assembler is close to nil ;)
kabe

kabe

2018-10-18 03:12

reporter   ~0032937

Tried that, no banana.
Things I've tried:
revert drivers/hv/ (no effect)
update entry_32.S resembling linux-3.16.y (no effect)
revert whole mm/ (no effect)
add struct hv_do_fcopy padding patch (a1a676a29b18f3870098a327702349371292afb0) (no effect, file copy service not in use anyway)

Something related to l1tf/tlb flush not updated for 32bit code? That'll be hard to track...
kabe

kabe

2018-10-18 10:32

reporter   ~0032939

Got the solution:
arch/x86/include/asm/uaccess_32.h wasn't updated in sync with uaccess_64.h.
This patch fixed the issue; kernel-3.10.0-862.11.6.el7.centos.plus.1.i686 booted successfully on Hyper-V.

I'll check back it this applies to the latest kernel.

patch-update-uaccess_32-h.patch (2,133 bytes)
--- ./arch/x86/include/asm/uaccess_32.h	2018-06-27 16:59:12.000000000 +0900
+++ /home/kabe/kernel.org/linux-stable/arch/x86/include/asm/uaccess_32.h	2018-10-15 19:16:00.817837747 +0900
@@ -48,16 +48,22 @@ __copy_to_user_inatomic(void __user *to,
 
 		switch (n) {
 		case 1:
+			__uaccess_begin_nospec();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin_nospec();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin_nospec();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -98,13 +104,19 @@ __copy_from_user_inatomic(void *to, cons
 
 		switch (n) {
 		case 1:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -142,13 +154,19 @@ __copy_from_user(void *to, const void __
 
 		switch (n) {
 		case 1:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -164,13 +182,19 @@ static __always_inline unsigned long __c
 
 		switch (n) {
 		case 1:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
pgreco

pgreco

2018-10-18 12:10

developer   ~0032940

@kabe, good!!, thanks for doing this.
If I understand correctly, your patch is a mix of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/arch/x86/include/asm/uaccess_32.h?h=v3.16.59&id=0a2d7d9b1e63dd28baf6c8e1416b64a33f89c900
and
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/arch/x86/include/asm/uaccess_32.h?h=v3.16.59&id=98ce99aa23b43c3dc736cd0354537fca029d69cb
I think we should also add https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v3.16.59&id=8f483696e8edb46461472afa27a764ac6a11929e and also apply the usercopy_32.c from commit 98ce99aa23b43c3dc736cd0354537fca029d69cb.

The end result should be something like the attachment. Can you check? Thanks!!

centos-3.10-i686-l1tfupdate.patch (12,446 bytes)
From 0a2d7d9b1e63dd28baf6c8e1416b64a33f89c900 Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Tue, 23 Feb 2016 14:58:52 -0800
Subject: x86: fix SMAP in 32-bit environments

commit de9e478b9d49f3a0214310d921450cf5bb4a21e6 upstream.

In commit 11f1a4b9755f ("x86: reorganize SMAP handling in user space
accesses") I changed how the stac/clac instructions were generated
around the user space accesses, which then made it possible to do
batched accesses efficiently for user string copies etc.

However, in doing so, I completely spaced out, and didn't even think
about the 32-bit case.  And nobody really even seemed to notice, because
SMAP doesn't even exist until modern Skylake processors, and you'd have
to be crazy to run 32-bit kernels on a modern CPU.

Which brings us to Andy Lutomirski.

He actually tested the 32-bit kernel on new hardware, and noticed that
it doesn't work.  My bad.  The trivial fix is to add the required
uaccess begin/end markers around the raw accesses in <asm/uaccess_32.h>.

I feel a bit bad about this patch, just because that header file really
should be cleaned up to avoid all the duplicated code in it, and this
commit just expands on the problem.  But this just fixes the bug without
any bigger cleanup surgery.

Reported-and-tested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 3.16: There's no 'case 8' in __copy_to_user_inatomic()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 3c03a5de64d3..b25d109fb95a 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -48,16 +48,22 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -98,13 +104,19 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -142,13 +154,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -164,13 +182,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
-- 
cgit 1.2-0.3.lf.el7

From 8f483696e8edb46461472afa27a764ac6a11929e Mon Sep 17 00:00:00 2001
From: Dan Williams <dan.j.williams@intel.com>
Date: Mon, 29 Jan 2018 17:02:44 -0800
Subject: x86/usercopy: Replace open coded stac/clac with __uaccess_{begin,
 end}

commit b5c4ae4f35325d520b230bab6eb3310613b72ac1 upstream.

In preparation for converting some __uaccess_begin() instances to
__uacess_begin_nospec(), make sure all 'from user' uaccess paths are
using the _begin(), _end() helpers rather than open-coded stac() and
clac().

No functional changes.

Suggested-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: torvalds@linux-foundation.org
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727416438.33451.17309465232057176966.stgit@dwillia2-desk3.amr.corp.intel.com
[bwh: Backported to 3.16:
 - Convert several more functions to use __uaccess_begin_nospec(), that
   are just wrappers in mainline
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/lib/usercopy_32.c | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index e2f5e21c03b3..7f6e7dd46215 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -570,12 +570,12 @@ do {									\
 unsigned long __copy_to_user_ll(void __user *to, const void *from,
 				unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
 		n = __copy_user_intel(to, from, n);
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_to_user_ll);
@@ -583,12 +583,12 @@ EXPORT_SYMBOL(__copy_to_user_ll);
 unsigned long __copy_from_user_ll(void *to, const void __user *from,
 					unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 	if (movsl_is_ok(to, from, n))
 		__copy_user_zeroing(to, from, n);
 	else
 		n = __copy_user_zeroing_intel(to, from, n);
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll);
@@ -596,13 +596,13 @@ EXPORT_SYMBOL(__copy_from_user_ll);
 unsigned long __copy_from_user_ll_nozero(void *to, const void __user *from,
 					 unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
 		n = __copy_user_intel((void __user *)to,
 				      (const void *)from, n);
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nozero);
@@ -610,7 +610,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozero);
 unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
 					unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && cpu_has_xmm2)
 		n = __copy_user_zeroing_intel_nocache(to, from, n);
@@ -619,7 +619,7 @@ unsigned long __copy_from_user_ll_nocache(void *to, const void __user *from,
 #else
 	__copy_user_zeroing(to, from, n);
 #endif
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache);
@@ -627,7 +627,7 @@ EXPORT_SYMBOL(__copy_from_user_ll_nocache);
 unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *from,
 					unsigned long n)
 {
-	stac();
+	__uaccess_begin();
 #ifdef CONFIG_X86_INTEL_USERCOPY
 	if (n > 64 && cpu_has_xmm2)
 		n = __copy_user_intel_nocache(to, from, n);
@@ -636,7 +636,7 @@ unsigned long __copy_from_user_ll_nocache_nozero(void *to, const void __user *fr
 #else
 	__copy_user(to, from, n);
 #endif
-	clac();
+	__uaccess_end();
 	return n;
 }
 EXPORT_SYMBOL(__copy_from_user_ll_nocache_nozero);
-- 
cgit 1.2-0.3.lf.el7

From 98ce99aa23b43c3dc736cd0354537fca029d69cb Mon Sep 17 00:00:00 2001
From: Dan Williams <dan.j.williams@intel.com>
Date: Mon, 29 Jan 2018 17:02:49 -0800
Subject: x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec

commit 304ec1b050310548db33063e567123fae8fd0301 upstream.

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

__uaccess_begin_nospec() covers __get_user() and copy_from_iter() where the
limit check is far away from the user pointer de-reference. In those cases
a barrier_nospec() prevents speculation with a potential pointer to
privileged memory. uaccess_try_nospec covers get_user_try.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727416953.33451.10508284228526170604.stgit@dwillia2-desk3.amr.corp.intel.com
[bwh: Backported to 3.16:
 - Convert several more functions to use __uaccess_begin_nospec(), that
   are just wrappers in mainline
 - There's no 'case 8' in __copy_to_user_inatomic()
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/uaccess.h    |  6 +++---
 arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++------------
 arch/x86/include/asm/uaccess_64.h | 20 ++++++++++----------
 arch/x86/lib/usercopy_32.c        | 10 +++++-----
 4 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index b25d109fb95a..c803818cedfb 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -48,19 +48,19 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
 			__uaccess_end();
@@ -104,17 +104,17 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
@@ -154,17 +154,17 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
@@ -182,17 +182,17 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
-- 
cgit 1.2-0.3.lf.el7

kabe

kabe

2018-10-19 06:06

reporter   ~0032942

Tested centos-3.10-i686-l1tfupdate.patch on latest kernel-3.10.0-862.14.4.el7.centos.plus kernel.
Didn't apply straight out of the box, but the resulting kernel is working well. Thanks for digging up the git log.
(I wan't sure the fix is related to L1TF, so I reverted the filename)

The usercopy_32.c fix was already applied for kernel-3.10.0-862.14.4.el7, so
the patch essentially disintegrates into same one as in https://bugs.centos.org/view.php?id=15374#c32939 .
Patching same file twice is ugly but having an upstream commit message is nice.

@toracat, can you consider including this patch for next i686 release?

centos-3.10-i686-uaccess_32-h.patch (8,585 bytes)
From 0a2d7d9b1e63dd28baf6c8e1416b64a33f89c900 Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Tue, 23 Feb 2016 14:58:52 -0800
Subject: x86: fix SMAP in 32-bit environments

commit de9e478b9d49f3a0214310d921450cf5bb4a21e6 upstream.

In commit 11f1a4b9755f ("x86: reorganize SMAP handling in user space
accesses") I changed how the stac/clac instructions were generated
around the user space accesses, which then made it possible to do
batched accesses efficiently for user string copies etc.

However, in doing so, I completely spaced out, and didn't even think
about the 32-bit case.  And nobody really even seemed to notice, because
SMAP doesn't even exist until modern Skylake processors, and you'd have
to be crazy to run 32-bit kernels on a modern CPU.

Which brings us to Andy Lutomirski.

He actually tested the 32-bit kernel on new hardware, and noticed that
it doesn't work.  My bad.  The trivial fix is to add the required
uaccess begin/end markers around the raw accesses in <asm/uaccess_32.h>.

I feel a bit bad about this patch, just because that header file really
should be cleaned up to avoid all the duplicated code in it, and this
commit just expands on the problem.  But this just fixes the bug without
any bigger cleanup surgery.

Reported-and-tested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 3.16: There's no 'case 8' in __copy_to_user_inatomic()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 3c03a5de64d3..b25d109fb95a 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -48,16 +48,22 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -98,13 +104,19 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -142,13 +154,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -164,13 +182,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
-- 
cgit 1.2-0.3.lf.el7

From 98ce99aa23b43c3dc736cd0354537fca029d69cb Mon Sep 17 00:00:00 2001
From: Dan Williams <dan.j.williams@intel.com>
Date: Mon, 29 Jan 2018 17:02:49 -0800
Subject: x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec

commit 304ec1b050310548db33063e567123fae8fd0301 upstream.

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

__uaccess_begin_nospec() covers __get_user() and copy_from_iter() where the
limit check is far away from the user pointer de-reference. In those cases
a barrier_nospec() prevents speculation with a potential pointer to
privileged memory. uaccess_try_nospec covers get_user_try.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727416953.33451.10508284228526170604.stgit@dwillia2-desk3.amr.corp.intel.com
[bwh: Backported to 3.16:
 - Convert several more functions to use __uaccess_begin_nospec(), that
   are just wrappers in mainline
 - There's no 'case 8' in __copy_to_user_inatomic()
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/uaccess.h    |  6 +++---
 arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++------------
 arch/x86/include/asm/uaccess_64.h | 20 ++++++++++----------
 arch/x86/lib/usercopy_32.c        | 10 +++++-----
 4 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index b25d109fb95a..c803818cedfb 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -48,19 +48,19 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
 			__uaccess_end();
@@ -104,17 +104,17 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
@@ -154,17 +154,17 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
@@ -182,17 +182,17 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
-- 
cgit 1.2-0.3.lf.el7

toracat

toracat

2018-10-19 06:19

manager   ~0032943

@kabe

Certainly. Thank you guys for getting to the fix.
pgreco

pgreco

2018-10-19 10:21

developer   ~0032946

Last edited: 2018-10-19 23:21

View 2 revisions

@kabe,

I agree that patching twice is ugly, but you get the benefit, right ;)
Also, I think when RH backported commit https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/arch/x86/lib/usercopy_32.c?h=v3.16.59&id=98ce99aa23b43c3dc736cd0354537fca029d69cb , they missed the first part of the patch (function __copy_to_user_ll), so I'm uploading your last version of the patch with that added.
Do you agree?
Thanks!!!



centos-3.10-i686-uaccess_32-h-2.patch (9,005 bytes)
From 0a2d7d9b1e63dd28baf6c8e1416b64a33f89c900 Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Tue, 23 Feb 2016 14:58:52 -0800
Subject: x86: fix SMAP in 32-bit environments

commit de9e478b9d49f3a0214310d921450cf5bb4a21e6 upstream.

In commit 11f1a4b9755f ("x86: reorganize SMAP handling in user space
accesses") I changed how the stac/clac instructions were generated
around the user space accesses, which then made it possible to do
batched accesses efficiently for user string copies etc.

However, in doing so, I completely spaced out, and didn't even think
about the 32-bit case.  And nobody really even seemed to notice, because
SMAP doesn't even exist until modern Skylake processors, and you'd have
to be crazy to run 32-bit kernels on a modern CPU.

Which brings us to Andy Lutomirski.

He actually tested the 32-bit kernel on new hardware, and noticed that
it doesn't work.  My bad.  The trivial fix is to add the required
uaccess begin/end markers around the raw accesses in <asm/uaccess_32.h>.

I feel a bit bad about this patch, just because that header file really
should be cleaned up to avoid all the duplicated code in it, and this
commit just expands on the problem.  But this just fixes the bug without
any bigger cleanup surgery.

Reported-and-tested-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
[bwh: Backported to 3.16: There's no 'case 8' in __copy_to_user_inatomic()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index 3c03a5de64d3..b25d109fb95a 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -48,16 +48,22 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -98,13 +104,19 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -142,13 +154,19 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
@@ -164,13 +182,19 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
 		switch (n) {
 		case 1:
+			__uaccess_begin();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
+			__uaccess_end();
 			return ret;
 		case 2:
+			__uaccess_begin();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
+			__uaccess_end();
 			return ret;
 		case 4:
+			__uaccess_begin();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
+			__uaccess_end();
 			return ret;
 		}
 	}
-- 
cgit 1.2-0.3.lf.el7

From 98ce99aa23b43c3dc736cd0354537fca029d69cb Mon Sep 17 00:00:00 2001
From: Dan Williams <dan.j.williams@intel.com>
Date: Mon, 29 Jan 2018 17:02:49 -0800
Subject: x86/uaccess: Use __uaccess_begin_nospec() and uaccess_try_nospec

commit 304ec1b050310548db33063e567123fae8fd0301 upstream.

Quoting Linus:

    I do think that it would be a good idea to very expressly document
    the fact that it's not that the user access itself is unsafe. I do
    agree that things like "get_user()" want to be protected, but not
    because of any direct bugs or problems with get_user() and friends,
    but simply because get_user() is an excellent source of a pointer
    that is obviously controlled from a potentially attacking user
    space. So it's a prime candidate for then finding _subsequent_
    accesses that can then be used to perturb the cache.

__uaccess_begin_nospec() covers __get_user() and copy_from_iter() where the
limit check is far away from the user pointer de-reference. In those cases
a barrier_nospec() prevents speculation with a potential pointer to
privileged memory. uaccess_try_nospec covers get_user_try.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Suggested-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-arch@vger.kernel.org
Cc: Kees Cook <keescook@chromium.org>
Cc: kernel-hardening@lists.openwall.com
Cc: gregkh@linuxfoundation.org
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: alan@linux.intel.com
Link: https://lkml.kernel.org/r/151727416953.33451.10508284228526170604.stgit@dwillia2-desk3.amr.corp.intel.com
[bwh: Backported to 3.16:
 - Convert several more functions to use __uaccess_begin_nospec(), that
   are just wrappers in mainline
 - There's no 'case 8' in __copy_to_user_inatomic()
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
---
 arch/x86/include/asm/uaccess.h    |  6 +++---
 arch/x86/include/asm/uaccess_32.h | 24 ++++++++++++------------
 arch/x86/include/asm/uaccess_64.h | 20 ++++++++++----------
 arch/x86/lib/usercopy_32.c        | 10 +++++-----
 4 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/arch/x86/include/asm/uaccess_32.h b/arch/x86/include/asm/uaccess_32.h
index b25d109fb95a..c803818cedfb 100644
--- a/arch/x86/include/asm/uaccess_32.h
+++ b/arch/x86/include/asm/uaccess_32.h
@@ -48,19 +48,19 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u8 *)from, (u8 __user *)to,
 					1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u16 *)from, (u16 __user *)to,
 					2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__put_user_size(*(u32 *)from, (u32 __user *)to,
 					4, ret, 4);
 			__uaccess_end();
@@ -104,17 +104,17 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
@@ -154,17 +154,17 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
@@ -182,17 +182,17 @@ static __always_inline unsigned long __copy_from_user_nocache(void *to,
 
 		switch (n) {
 		case 1:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u8 *)to, from, 1, ret, 1);
 			__uaccess_end();
 			return ret;
 		case 2:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u16 *)to, from, 2, ret, 2);
 			__uaccess_end();
 			return ret;
 		case 4:
-			__uaccess_begin();
+			__uaccess_begin_nospec();
 			__get_user_size(*(u32 *)to, from, 4, ret, 4);
 			__uaccess_end();
 			return ret;
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 7f6e7dd46215..de848bc95a9f 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -570,7 +570,7 @@ do {									\
 unsigned long __copy_to_user_ll(void __user *to, const void *from,
 				unsigned long n)
 {
-	__uaccess_begin();
+	__uaccess_begin_nospec();
 	if (movsl_is_ok(to, from, n))
 		__copy_user(to, from, n);
 	else
-- 
cgit 1.2-0.3.lf.el7

kabe

kabe

2018-10-22 04:15

reporter   ~0032958

Confirmed that centos-3.10-i686-uaccess_32-h-2.patch will apply to latest kernel-3.10.0-862.14.4.el7.centos.plus kernel,
and does boot on Hyper-V.
I agree with the patch, although the added part is a protective patch rather than problem driven.
(There's only partial Spectre/Meltdown mitigation in CentOS 7 i686 anyway...)
There's several NOSPEC related patch RHEL missing in 32bit code, so I'll post those in seperate report.

@toracat, please replace the patch with centos-3.10-i686-uaccess_32-h-2.patch. Sorry for inconvenience.
toracat

toracat

2018-10-22 05:01

manager   ~0032959

@kabe

Will do. Your invaluable help much appreciated.
pgreco

pgreco

2018-10-22 10:28

developer   ~0032962

@kabe, correct, I added the last part of the patch to complete the part backported by RH.
If you manage to add those nospec patches, maybe we could include the usercopy_32 bits in that one.

Thanks for doing this!
toracat

toracat

2019-09-14 00:50

manager   ~0035100

Should have been closed long ago as 'resolved'. :)

Issue History

Date Modified Username Field Change
2018-10-15 01:36 kabe New Issue
2018-10-15 01:36 kabe Tag Attached: i386
2018-10-15 12:11 pgreco Note Added: 0032920
2018-10-16 02:16 kabe Note Added: 0032924
2018-10-17 09:56 pgreco Note Added: 0032933
2018-10-18 03:12 kabe Note Added: 0032937
2018-10-18 10:32 kabe File Added: patch-update-uaccess_32-h.patch
2018-10-18 10:32 kabe Note Added: 0032939
2018-10-18 12:10 pgreco File Added: centos-3.10-i686-l1tfupdate.patch
2018-10-18 12:10 pgreco Note Added: 0032940
2018-10-19 06:06 kabe File Added: centos-3.10-i686-uaccess_32-h.patch
2018-10-19 06:06 kabe Note Added: 0032942
2018-10-19 06:19 toracat Status new => assigned
2018-10-19 06:19 toracat Note Added: 0032943
2018-10-19 10:21 pgreco File Added: centos-3.10-i686-uaccess_32-h-2.patch
2018-10-19 10:21 pgreco Note Added: 0032946
2018-10-19 23:21 toracat Note Edited: 0032946 View Revisions
2018-10-22 04:15 kabe Note Added: 0032958
2018-10-22 05:01 toracat Note Added: 0032959
2018-10-22 10:28 pgreco Note Added: 0032962
2019-09-14 00:50 toracat Status assigned => resolved
2019-09-14 00:50 toracat Resolution open => fixed
2019-09-14 00:50 toracat Note Added: 0035100