]>
Commit | Line | Data |
---|---|---|
ea04701c GKH |
1 | From ed596cde9425509ec6ce88e19f03e9b13b6f518b Mon Sep 17 00:00:00 2001 |
2 | From: Linus Torvalds <torvalds@linux-foundation.org> | |
3 | Date: Thu, 13 Aug 2015 08:25:20 -0700 | |
4 | Subject: Revert x86 sigcontext cleanups | |
5 | ||
6 | From: Linus Torvalds <torvalds@linux-foundation.org> | |
7 | ||
8 | commit ed596cde9425509ec6ce88e19f03e9b13b6f518b upstream. | |
9 | ||
10 | This reverts commits 9a036b93a344 ("x86/signal/64: Remove 'fs' and 'gs' | |
11 | from sigcontext") and c6f2062935c8 ("x86/signal/64: Fix SS handling for | |
12 | signals delivered to 64-bit programs"). | |
13 | ||
14 | They were cleanups, but they break dosemu by changing the signal return | |
15 | behavior (and removing 'fs' and 'gs' from the sigcontext struct - while | |
16 | not actually changing any behavior - causes build problems). | |
17 | ||
18 | Reported-and-tested-by: Stas Sergeev <stsp@list.ru> | |
19 | Acked-by: Andy Lutomirski <luto@amacapital.net> | |
20 | Cc: Ingo Molnar <mingo@kernel.org> | |
21 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
22 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
23 | ||
24 | --- | |
25 | arch/x86/include/asm/sigcontext.h | 6 +++--- | |
26 | arch/x86/include/uapi/asm/sigcontext.h | 21 +++------------------ | |
27 | arch/x86/kernel/signal.c | 26 +++++++++++--------------- | |
28 | 3 files changed, 17 insertions(+), 36 deletions(-) | |
29 | ||
30 | --- a/arch/x86/include/asm/sigcontext.h | |
31 | +++ b/arch/x86/include/asm/sigcontext.h | |
32 | @@ -57,9 +57,9 @@ struct sigcontext { | |
33 | unsigned long ip; | |
34 | unsigned long flags; | |
35 | unsigned short cs; | |
36 | - unsigned short __pad2; /* Was called gs, but was always zero. */ | |
37 | - unsigned short __pad1; /* Was called fs, but was always zero. */ | |
38 | - unsigned short ss; | |
39 | + unsigned short gs; | |
40 | + unsigned short fs; | |
41 | + unsigned short __pad0; | |
42 | unsigned long err; | |
43 | unsigned long trapno; | |
44 | unsigned long oldmask; | |
45 | --- a/arch/x86/include/uapi/asm/sigcontext.h | |
46 | +++ b/arch/x86/include/uapi/asm/sigcontext.h | |
47 | @@ -177,24 +177,9 @@ struct sigcontext { | |
48 | __u64 rip; | |
49 | __u64 eflags; /* RFLAGS */ | |
50 | __u16 cs; | |
51 | - | |
52 | - /* | |
53 | - * Prior to 2.5.64 ("[PATCH] x86-64 updates for 2.5.64-bk3"), | |
54 | - * Linux saved and restored fs and gs in these slots. This | |
55 | - * was counterproductive, as fsbase and gsbase were never | |
56 | - * saved, so arch_prctl was presumably unreliable. | |
57 | - * | |
58 | - * If these slots are ever needed for any other purpose, there | |
59 | - * is some risk that very old 64-bit binaries could get | |
60 | - * confused. I doubt that many such binaries still work, | |
61 | - * though, since the same patch in 2.5.64 also removed the | |
62 | - * 64-bit set_thread_area syscall, so it appears that there is | |
63 | - * no TLS API that works in both pre- and post-2.5.64 kernels. | |
64 | - */ | |
65 | - __u16 __pad2; /* Was gs. */ | |
66 | - __u16 __pad1; /* Was fs. */ | |
67 | - | |
68 | - __u16 ss; | |
69 | + __u16 gs; | |
70 | + __u16 fs; | |
71 | + __u16 __pad0; | |
72 | __u64 err; | |
73 | __u64 trapno; | |
74 | __u64 oldmask; | |
75 | --- a/arch/x86/kernel/signal.c | |
76 | +++ b/arch/x86/kernel/signal.c | |
77 | @@ -93,8 +93,15 @@ int restore_sigcontext(struct pt_regs *r | |
78 | COPY(r15); | |
79 | #endif /* CONFIG_X86_64 */ | |
80 | ||
81 | +#ifdef CONFIG_X86_32 | |
82 | COPY_SEG_CPL3(cs); | |
83 | COPY_SEG_CPL3(ss); | |
84 | +#else /* !CONFIG_X86_32 */ | |
85 | + /* Kernel saves and restores only the CS segment register on signals, | |
86 | + * which is the bare minimum needed to allow mixed 32/64-bit code. | |
87 | + * App's signal handler can save/restore other segments if needed. */ | |
88 | + COPY_SEG_CPL3(cs); | |
89 | +#endif /* CONFIG_X86_32 */ | |
90 | ||
91 | get_user_ex(tmpflags, &sc->flags); | |
92 | regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); | |
93 | @@ -154,9 +161,8 @@ int setup_sigcontext(struct sigcontext _ | |
94 | #else /* !CONFIG_X86_32 */ | |
95 | put_user_ex(regs->flags, &sc->flags); | |
96 | put_user_ex(regs->cs, &sc->cs); | |
97 | - put_user_ex(0, &sc->__pad2); | |
98 | - put_user_ex(0, &sc->__pad1); | |
99 | - put_user_ex(regs->ss, &sc->ss); | |
100 | + put_user_ex(0, &sc->gs); | |
101 | + put_user_ex(0, &sc->fs); | |
102 | #endif /* CONFIG_X86_32 */ | |
103 | ||
104 | put_user_ex(fpstate, &sc->fpstate); | |
105 | @@ -450,19 +456,9 @@ static int __setup_rt_frame(int sig, str | |
106 | ||
107 | regs->sp = (unsigned long)frame; | |
108 | ||
109 | - /* | |
110 | - * Set up the CS and SS registers to run signal handlers in | |
111 | - * 64-bit mode, even if the handler happens to be interrupting | |
112 | - * 32-bit or 16-bit code. | |
113 | - * | |
114 | - * SS is subtle. In 64-bit mode, we don't need any particular | |
115 | - * SS descriptor, but we do need SS to be valid. It's possible | |
116 | - * that the old SS is entirely bogus -- this can happen if the | |
117 | - * signal we're trying to deliver is #GP or #SS caused by a bad | |
118 | - * SS value. | |
119 | - */ | |
120 | + /* Set up the CS register to run signal handlers in 64-bit mode, | |
121 | + even if the handler happens to be interrupting 32-bit code. */ | |
122 | regs->cs = __USER_CS; | |
123 | - regs->ss = __USER_DS; | |
124 | ||
125 | return 0; | |
126 | } |