diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-18 11:31:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-18 11:31:11 -0400 |
commit | 90d1c087861dcc3d1175993fc03492c137fd21bb (patch) | |
tree | ee90db200e3c5c249cf3150249c0f8c700e300d2 | |
parent | 96b90f27bcf22f1d06cc16d9475cefa6ea4c4718 (diff) | |
parent | a6dfa128ce5c414ab46b1d690f7a1b8decb8526d (diff) |
Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Ingo Molnar:
"This tree includes:
- an FPU related crash fix
- a ptrace fix (with matching testcase in tools/testing/selftests/)
- an x86 Kconfig DMA-config defaults tweak to better avoid
non-working drivers"
* 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
config: Enable NEED_DMA_MAP_STATE by default when SWIOTLB is selected
x86/fpu: Load xsave pointer *after* initialization
x86/ptrace: Fix the TIF_FORCED_TF logic in handle_signal()
x86, selftests: Add single_step_syscall test
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/kernel/i387.c | 8 | ||||
-rw-r--r-- | arch/x86/kernel/signal.c | 22 | ||||
-rw-r--r-- | tools/testing/selftests/x86/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/x86/run_x86_tests.sh | 2 | ||||
-rw-r--r-- | tools/testing/selftests/x86/single_step_syscall.c | 181 |
6 files changed, 202 insertions, 15 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d43e7e1c784b..937812b8e0b9 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -178,7 +178,7 @@ config SBUS | |||
178 | 178 | ||
179 | config NEED_DMA_MAP_STATE | 179 | config NEED_DMA_MAP_STATE |
180 | def_bool y | 180 | def_bool y |
181 | depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG | 181 | depends on X86_64 || INTEL_IOMMU || DMA_API_DEBUG || SWIOTLB |
182 | 182 | ||
183 | config NEED_SG_DMA_LENGTH | 183 | config NEED_SG_DMA_LENGTH |
184 | def_bool y | 184 | def_bool y |
diff --git a/arch/x86/kernel/i387.c b/arch/x86/kernel/i387.c index 367f39d35e9c..009183276bb7 100644 --- a/arch/x86/kernel/i387.c +++ b/arch/x86/kernel/i387.c | |||
@@ -341,7 +341,7 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset, | |||
341 | unsigned int pos, unsigned int count, | 341 | unsigned int pos, unsigned int count, |
342 | void *kbuf, void __user *ubuf) | 342 | void *kbuf, void __user *ubuf) |
343 | { | 343 | { |
344 | struct xsave_struct *xsave = &target->thread.fpu.state->xsave; | 344 | struct xsave_struct *xsave; |
345 | int ret; | 345 | int ret; |
346 | 346 | ||
347 | if (!cpu_has_xsave) | 347 | if (!cpu_has_xsave) |
@@ -351,6 +351,8 @@ int xstateregs_get(struct task_struct *target, const struct user_regset *regset, | |||
351 | if (ret) | 351 | if (ret) |
352 | return ret; | 352 | return ret; |
353 | 353 | ||
354 | xsave = &target->thread.fpu.state->xsave; | ||
355 | |||
354 | /* | 356 | /* |
355 | * Copy the 48bytes defined by the software first into the xstate | 357 | * Copy the 48bytes defined by the software first into the xstate |
356 | * memory layout in the thread struct, so that we can copy the entire | 358 | * memory layout in the thread struct, so that we can copy the entire |
@@ -369,7 +371,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, | |||
369 | unsigned int pos, unsigned int count, | 371 | unsigned int pos, unsigned int count, |
370 | const void *kbuf, const void __user *ubuf) | 372 | const void *kbuf, const void __user *ubuf) |
371 | { | 373 | { |
372 | struct xsave_struct *xsave = &target->thread.fpu.state->xsave; | 374 | struct xsave_struct *xsave; |
373 | int ret; | 375 | int ret; |
374 | 376 | ||
375 | if (!cpu_has_xsave) | 377 | if (!cpu_has_xsave) |
@@ -379,6 +381,8 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, | |||
379 | if (ret) | 381 | if (ret) |
380 | return ret; | 382 | return ret; |
381 | 383 | ||
384 | xsave = &target->thread.fpu.state->xsave; | ||
385 | |||
382 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); | 386 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, xsave, 0, -1); |
383 | /* | 387 | /* |
384 | * mxcsr reserved bits must be masked to zero for security reasons. | 388 | * mxcsr reserved bits must be masked to zero for security reasons. |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index f9804080ccb3..1ea14fd53933 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -616,7 +616,8 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) | |||
616 | static void | 616 | static void |
617 | handle_signal(struct ksignal *ksig, struct pt_regs *regs) | 617 | handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
618 | { | 618 | { |
619 | bool failed; | 619 | bool stepping, failed; |
620 | |||
620 | /* Are we from a system call? */ | 621 | /* Are we from a system call? */ |
621 | if (syscall_get_nr(current, regs) >= 0) { | 622 | if (syscall_get_nr(current, regs) >= 0) { |
622 | /* If so, check system call restarting.. */ | 623 | /* If so, check system call restarting.. */ |
@@ -640,12 +641,13 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
640 | } | 641 | } |
641 | 642 | ||
642 | /* | 643 | /* |
643 | * If TF is set due to a debugger (TIF_FORCED_TF), clear the TF | 644 | * If TF is set due to a debugger (TIF_FORCED_TF), clear TF now |
644 | * flag so that register information in the sigcontext is correct. | 645 | * so that register information in the sigcontext is correct and |
646 | * then notify the tracer before entering the signal handler. | ||
645 | */ | 647 | */ |
646 | if (unlikely(regs->flags & X86_EFLAGS_TF) && | 648 | stepping = test_thread_flag(TIF_SINGLESTEP); |
647 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 649 | if (stepping) |
648 | regs->flags &= ~X86_EFLAGS_TF; | 650 | user_disable_single_step(current); |
649 | 651 | ||
650 | failed = (setup_rt_frame(ksig, regs) < 0); | 652 | failed = (setup_rt_frame(ksig, regs) < 0); |
651 | if (!failed) { | 653 | if (!failed) { |
@@ -656,10 +658,8 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
656 | * it might disable possible debug exception from the | 658 | * it might disable possible debug exception from the |
657 | * signal handler. | 659 | * signal handler. |
658 | * | 660 | * |
659 | * Clear TF when entering the signal handler, but | 661 | * Clear TF for the case when it wasn't set by debugger to |
660 | * notify any tracer that was single-stepping it. | 662 | * avoid the recursive send_sigtrap() in SIGTRAP handler. |
661 | * The tracer may want to single-step inside the | ||
662 | * handler too. | ||
663 | */ | 663 | */ |
664 | regs->flags &= ~(X86_EFLAGS_DF|X86_EFLAGS_RF|X86_EFLAGS_TF); | 664 | regs->flags &= ~(X86_EFLAGS_DF|X86_EFLAGS_RF|X86_EFLAGS_TF); |
665 | /* | 665 | /* |
@@ -668,7 +668,7 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs) | |||
668 | if (used_math()) | 668 | if (used_math()) |
669 | fpu_reset_state(current); | 669 | fpu_reset_state(current); |
670 | } | 670 | } |
671 | signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP)); | 671 | signal_setup_done(failed, ksig, stepping); |
672 | } | 672 | } |
673 | 673 | ||
674 | #ifdef CONFIG_X86_32 | 674 | #ifdef CONFIG_X86_32 |
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index f0a7918178dd..ddf63569df5a 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | .PHONY: all all_32 all_64 check_build32 clean run_tests | 1 | .PHONY: all all_32 all_64 check_build32 clean run_tests |
2 | 2 | ||
3 | TARGETS_C_BOTHBITS := sigreturn | 3 | TARGETS_C_BOTHBITS := sigreturn single_step_syscall |
4 | 4 | ||
5 | BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32) | 5 | BINARIES_32 := $(TARGETS_C_BOTHBITS:%=%_32) |
6 | BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64) | 6 | BINARIES_64 := $(TARGETS_C_BOTHBITS:%=%_64) |
diff --git a/tools/testing/selftests/x86/run_x86_tests.sh b/tools/testing/selftests/x86/run_x86_tests.sh index 3d3ec65f3e7c..3fc19b376812 100644 --- a/tools/testing/selftests/x86/run_x86_tests.sh +++ b/tools/testing/selftests/x86/run_x86_tests.sh | |||
@@ -3,9 +3,11 @@ | |||
3 | # This is deliberately minimal. IMO kselftests should provide a standard | 3 | # This is deliberately minimal. IMO kselftests should provide a standard |
4 | # script here. | 4 | # script here. |
5 | ./sigreturn_32 || exit 1 | 5 | ./sigreturn_32 || exit 1 |
6 | ./single_step_syscall_32 || exit 1 | ||
6 | 7 | ||
7 | if [[ "$uname -p" -eq "x86_64" ]]; then | 8 | if [[ "$uname -p" -eq "x86_64" ]]; then |
8 | ./sigreturn_64 || exit 1 | 9 | ./sigreturn_64 || exit 1 |
10 | ./single_step_syscall_64 || exit 1 | ||
9 | fi | 11 | fi |
10 | 12 | ||
11 | exit 0 | 13 | exit 0 |
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c new file mode 100644 index 000000000000..50c26358e8b7 --- /dev/null +++ b/tools/testing/selftests/x86/single_step_syscall.c | |||
@@ -0,0 +1,181 @@ | |||
1 | /* | ||
2 | * single_step_syscall.c - single-steps various x86 syscalls | ||
3 | * Copyright (c) 2014-2015 Andrew Lutomirski | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but | ||
10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
12 | * General Public License for more details. | ||
13 | * | ||
14 | * This is a very simple series of tests that makes system calls with | ||
15 | * the TF flag set. This exercises some nasty kernel code in the | ||
16 | * SYSENTER case: SYSENTER does not clear TF, so SYSENTER with TF set | ||
17 | * immediately issues #DB from CPL 0. This requires special handling in | ||
18 | * the kernel. | ||
19 | */ | ||
20 | |||
21 | #define _GNU_SOURCE | ||
22 | |||
23 | #include <sys/time.h> | ||
24 | #include <time.h> | ||
25 | #include <stdlib.h> | ||
26 | #include <sys/syscall.h> | ||
27 | #include <unistd.h> | ||
28 | #include <stdio.h> | ||
29 | #include <string.h> | ||
30 | #include <inttypes.h> | ||
31 | #include <sys/mman.h> | ||
32 | #include <sys/signal.h> | ||
33 | #include <sys/ucontext.h> | ||
34 | #include <asm/ldt.h> | ||
35 | #include <err.h> | ||
36 | #include <setjmp.h> | ||
37 | #include <stddef.h> | ||
38 | #include <stdbool.h> | ||
39 | #include <sys/ptrace.h> | ||
40 | #include <sys/user.h> | ||
41 | |||
42 | static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), | ||
43 | int flags) | ||
44 | { | ||
45 | struct sigaction sa; | ||
46 | memset(&sa, 0, sizeof(sa)); | ||
47 | sa.sa_sigaction = handler; | ||
48 | sa.sa_flags = SA_SIGINFO | flags; | ||
49 | sigemptyset(&sa.sa_mask); | ||
50 | if (sigaction(sig, &sa, 0)) | ||
51 | err(1, "sigaction"); | ||
52 | } | ||
53 | |||
54 | static volatile sig_atomic_t sig_traps; | ||
55 | |||
56 | #ifdef __x86_64__ | ||
57 | # define REG_IP REG_RIP | ||
58 | # define WIDTH "q" | ||
59 | #else | ||
60 | # define REG_IP REG_EIP | ||
61 | # define WIDTH "l" | ||
62 | #endif | ||
63 | |||
64 | static unsigned long get_eflags(void) | ||
65 | { | ||
66 | unsigned long eflags; | ||
67 | asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags)); | ||
68 | return eflags; | ||
69 | } | ||
70 | |||
71 | static void set_eflags(unsigned long eflags) | ||
72 | { | ||
73 | asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH | ||
74 | : : "rm" (eflags) : "flags"); | ||
75 | } | ||
76 | |||
77 | #define X86_EFLAGS_TF (1UL << 8) | ||
78 | |||
79 | static void sigtrap(int sig, siginfo_t *info, void *ctx_void) | ||
80 | { | ||
81 | ucontext_t *ctx = (ucontext_t*)ctx_void; | ||
82 | |||
83 | if (get_eflags() & X86_EFLAGS_TF) { | ||
84 | set_eflags(get_eflags() & ~X86_EFLAGS_TF); | ||
85 | printf("[WARN]\tSIGTRAP handler had TF set\n"); | ||
86 | _exit(1); | ||
87 | } | ||
88 | |||
89 | sig_traps++; | ||
90 | |||
91 | if (sig_traps == 10000 || sig_traps == 10001) { | ||
92 | printf("[WARN]\tHit %d SIGTRAPs with si_addr 0x%lx, ip 0x%lx\n", | ||
93 | (int)sig_traps, | ||
94 | (unsigned long)info->si_addr, | ||
95 | (unsigned long)ctx->uc_mcontext.gregs[REG_IP]); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | static void check_result(void) | ||
100 | { | ||
101 | unsigned long new_eflags = get_eflags(); | ||
102 | set_eflags(new_eflags & ~X86_EFLAGS_TF); | ||
103 | |||
104 | if (!sig_traps) { | ||
105 | printf("[FAIL]\tNo SIGTRAP\n"); | ||
106 | exit(1); | ||
107 | } | ||
108 | |||
109 | if (!(new_eflags & X86_EFLAGS_TF)) { | ||
110 | printf("[FAIL]\tTF was cleared\n"); | ||
111 | exit(1); | ||
112 | } | ||
113 | |||
114 | printf("[OK]\tSurvived with TF set and %d traps\n", (int)sig_traps); | ||
115 | sig_traps = 0; | ||
116 | } | ||
117 | |||
118 | int main() | ||
119 | { | ||
120 | int tmp; | ||
121 | |||
122 | sethandler(SIGTRAP, sigtrap, 0); | ||
123 | |||
124 | printf("[RUN]\tSet TF and check nop\n"); | ||
125 | set_eflags(get_eflags() | X86_EFLAGS_TF); | ||
126 | asm volatile ("nop"); | ||
127 | check_result(); | ||
128 | |||
129 | #ifdef __x86_64__ | ||
130 | printf("[RUN]\tSet TF and check syscall-less opportunistic sysret\n"); | ||
131 | set_eflags(get_eflags() | X86_EFLAGS_TF); | ||
132 | extern unsigned char post_nop[]; | ||
133 | asm volatile ("pushf" WIDTH "\n\t" | ||
134 | "pop" WIDTH " %%r11\n\t" | ||
135 | "nop\n\t" | ||
136 | "post_nop:" | ||
137 | : : "c" (post_nop) : "r11"); | ||
138 | check_result(); | ||
139 | #endif | ||
140 | |||
141 | printf("[RUN]\tSet TF and check int80\n"); | ||
142 | set_eflags(get_eflags() | X86_EFLAGS_TF); | ||
143 | asm volatile ("int $0x80" : "=a" (tmp) : "a" (SYS_getpid)); | ||
144 | check_result(); | ||
145 | |||
146 | /* | ||
147 | * This test is particularly interesting if fast syscalls use | ||
148 | * SYSENTER: it triggers a nasty design flaw in SYSENTER. | ||
149 | * Specifically, SYSENTER does not clear TF, so either SYSENTER | ||
150 | * or the next instruction traps at CPL0. (Of course, Intel | ||
151 | * mostly forgot to document exactly what happens here.) So we | ||
152 | * get a CPL0 fault with usergs (on 64-bit kernels) and possibly | ||
153 | * no stack. The only sane way the kernel can possibly handle | ||
154 | * it is to clear TF on return from the #DB handler, but this | ||
155 | * happens way too early to set TF in the saved pt_regs, so the | ||
156 | * kernel has to do something clever to avoid losing track of | ||
157 | * the TF bit. | ||
158 | * | ||
159 | * Needless to say, we've had bugs in this area. | ||
160 | */ | ||
161 | syscall(SYS_getpid); /* Force symbol binding without TF set. */ | ||
162 | printf("[RUN]\tSet TF and check a fast syscall\n"); | ||
163 | set_eflags(get_eflags() | X86_EFLAGS_TF); | ||
164 | syscall(SYS_getpid); | ||
165 | check_result(); | ||
166 | |||
167 | /* Now make sure that another fast syscall doesn't set TF again. */ | ||
168 | printf("[RUN]\tFast syscall with TF cleared\n"); | ||
169 | fflush(stdout); /* Force a syscall */ | ||
170 | if (get_eflags() & X86_EFLAGS_TF) { | ||
171 | printf("[FAIL]\tTF is now set\n"); | ||
172 | exit(1); | ||
173 | } | ||
174 | if (sig_traps) { | ||
175 | printf("[FAIL]\tGot SIGTRAP\n"); | ||
176 | exit(1); | ||
177 | } | ||
178 | printf("[OK]\tNothing unexpected happened\n"); | ||
179 | |||
180 | return 0; | ||
181 | } | ||