]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.4/selftests-x86-sigreturn-64-fix-spurious-failures-on-amd-cpus.patch
Linux 4.9.124
[thirdparty/kernel/stable-queue.git] / queue-4.4 / selftests-x86-sigreturn-64-fix-spurious-failures-on-amd-cpus.patch
1 From foo@baz Wed Aug 22 10:28:26 CEST 2018
2 From: Andy Lutomirski <luto@kernel.org>
3 Date: Tue, 26 Jun 2018 22:17:17 -0700
4 Subject: selftests/x86/sigreturn/64: Fix spurious failures on AMD CPUs
5
6 From: Andy Lutomirski <luto@kernel.org>
7
8 [ Upstream commit ec348020566009d3da9b99f07c05814d13969c78 ]
9
10 When I wrote the sigreturn test, I didn't realize that AMD's busted
11 IRET behavior was different from Intel's busted IRET behavior:
12
13 On AMD CPUs, the CPU leaks the high 32 bits of the kernel stack pointer
14 to certain userspace contexts. Gee, thanks. There's very little
15 the kernel can do about it. Modify the test so it passes.
16
17 Signed-off-by: Andy Lutomirski <luto@kernel.org>
18 Cc: Borislav Petkov <bp@alien8.de>
19 Cc: Linus Torvalds <torvalds@linux-foundation.org>
20 Cc: Peter Zijlstra <peterz@infradead.org>
21 Cc: Thomas Gleixner <tglx@linutronix.de>
22 Link: http://lkml.kernel.org/r/86e7fd3564497f657de30a36da4505799eebef01.1530076529.git.luto@kernel.org
23 Signed-off-by: Ingo Molnar <mingo@kernel.org>
24 Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
25 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
26 ---
27 tools/testing/selftests/x86/sigreturn.c | 46 ++++++++++++++++++++------------
28 1 file changed, 29 insertions(+), 17 deletions(-)
29
30 --- a/tools/testing/selftests/x86/sigreturn.c
31 +++ b/tools/testing/selftests/x86/sigreturn.c
32 @@ -456,19 +456,38 @@ static int test_valid_sigreturn(int cs_b
33 greg_t req = requested_regs[i], res = resulting_regs[i];
34 if (i == REG_TRAPNO || i == REG_IP)
35 continue; /* don't care */
36 - if (i == REG_SP) {
37 - printf("\tSP: %llx -> %llx\n", (unsigned long long)req,
38 - (unsigned long long)res);
39
40 + if (i == REG_SP) {
41 /*
42 - * In many circumstances, the high 32 bits of rsp
43 - * are zeroed. For example, we could be a real
44 - * 32-bit program, or we could hit any of a number
45 - * of poorly-documented IRET or segmented ESP
46 - * oddities. If this happens, it's okay.
47 + * If we were using a 16-bit stack segment, then
48 + * the kernel is a bit stuck: IRET only restores
49 + * the low 16 bits of ESP/RSP if SS is 16-bit.
50 + * The kernel uses a hack to restore bits 31:16,
51 + * but that hack doesn't help with bits 63:32.
52 + * On Intel CPUs, bits 63:32 end up zeroed, and, on
53 + * AMD CPUs, they leak the high bits of the kernel
54 + * espfix64 stack pointer. There's very little that
55 + * the kernel can do about it.
56 + *
57 + * Similarly, if we are returning to a 32-bit context,
58 + * the CPU will often lose the high 32 bits of RSP.
59 */
60 - if (res == (req & 0xFFFFFFFF))
61 - continue; /* OK; not expected to work */
62 +
63 + if (res == req)
64 + continue;
65 +
66 + if (cs_bits != 64 && ((res ^ req) & 0xFFFFFFFF) == 0) {
67 + printf("[NOTE]\tSP: %llx -> %llx\n",
68 + (unsigned long long)req,
69 + (unsigned long long)res);
70 + continue;
71 + }
72 +
73 + printf("[FAIL]\tSP mismatch: requested 0x%llx; got 0x%llx\n",
74 + (unsigned long long)requested_regs[i],
75 + (unsigned long long)resulting_regs[i]);
76 + nerrs++;
77 + continue;
78 }
79
80 bool ignore_reg = false;
81 @@ -507,13 +526,6 @@ static int test_valid_sigreturn(int cs_b
82 }
83
84 if (requested_regs[i] != resulting_regs[i] && !ignore_reg) {
85 - /*
86 - * SP is particularly interesting here. The
87 - * usual cause of failures is that we hit the
88 - * nasty IRET case of returning to a 16-bit SS,
89 - * in which case bits 16:31 of the *kernel*
90 - * stack pointer persist in ESP.
91 - */
92 printf("[FAIL]\tReg %d mismatch: requested 0x%llx; got 0x%llx\n",
93 i, (unsigned long long)requested_regs[i],
94 (unsigned long long)resulting_regs[i]);