aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/ia32/ia32_signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/ia32/ia32_signal.c')
-rw-r--r--arch/x86/ia32/ia32_signal.c70
1 files changed, 27 insertions, 43 deletions
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index dd77ac0cac46..588a7aa937e1 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -33,8 +33,6 @@
33#include <asm/sigframe.h> 33#include <asm/sigframe.h>
34#include <asm/sys_ia32.h> 34#include <asm/sys_ia32.h>
35 35
36#define DEBUG_SIG 0
37
38#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 36#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
39 37
40#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \ 38#define FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
@@ -190,42 +188,47 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
190/* 188/*
191 * Do a signal return; undo the signal stack. 189 * Do a signal return; undo the signal stack.
192 */ 190 */
191#define loadsegment_gs(v) load_gs_index(v)
192#define loadsegment_fs(v) loadsegment(fs, v)
193#define loadsegment_ds(v) loadsegment(ds, v)
194#define loadsegment_es(v) loadsegment(es, v)
195
196#define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
197#define set_user_seg(seg, v) loadsegment_##seg(v)
198
193#define COPY(x) { \ 199#define COPY(x) { \
194 get_user_ex(regs->x, &sc->x); \ 200 get_user_ex(regs->x, &sc->x); \
195} 201}
196 202
197#define COPY_SEG_CPL3(seg) { \ 203#define GET_SEG(seg) ({ \
198 unsigned short tmp; \ 204 unsigned short tmp; \
199 get_user_ex(tmp, &sc->seg); \ 205 get_user_ex(tmp, &sc->seg); \
200 regs->seg = tmp | 3; \ 206 tmp; \
201} 207})
208
209#define COPY_SEG_CPL3(seg) do { \
210 regs->seg = GET_SEG(seg) | 3; \
211} while (0)
202 212
203#define RELOAD_SEG(seg) { \ 213#define RELOAD_SEG(seg) { \
204 unsigned int cur, pre; \ 214 unsigned int pre = GET_SEG(seg); \
205 get_user_ex(pre, &sc->seg); \ 215 unsigned int cur = get_user_seg(seg); \
206 savesegment(seg, cur); \
207 pre |= 3; \ 216 pre |= 3; \
208 if (pre != cur) \ 217 if (pre != cur) \
209 loadsegment(seg, pre); \ 218 set_user_seg(seg, pre); \
210} 219}
211 220
212static int ia32_restore_sigcontext(struct pt_regs *regs, 221static int ia32_restore_sigcontext(struct pt_regs *regs,
213 struct sigcontext_ia32 __user *sc, 222 struct sigcontext_ia32 __user *sc,
214 unsigned int *pax) 223 unsigned int *pax)
215{ 224{
216 unsigned int tmpflags, gs, oldgs, err = 0; 225 unsigned int tmpflags, err = 0;
217 void __user *buf; 226 void __user *buf;
218 u32 tmp; 227 u32 tmp;
219 228
220 /* Always make any pending restarted system calls return -EINTR */ 229 /* Always make any pending restarted system calls return -EINTR */
221 current_thread_info()->restart_block.fn = do_no_restart_syscall; 230 current_thread_info()->restart_block.fn = do_no_restart_syscall;
222 231
223#if DEBUG_SIG
224 printk(KERN_DEBUG "SIG restore_sigcontext: "
225 "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
226 sc, sc->err, sc->ip, sc->cs, sc->flags);
227#endif
228
229 get_user_try { 232 get_user_try {
230 /* 233 /*
231 * Reload fs and gs if they have changed in the signal 234 * Reload fs and gs if they have changed in the signal
@@ -233,12 +236,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
233 * the handler, but does not clobber them at least in the 236 * the handler, but does not clobber them at least in the
234 * normal case. 237 * normal case.
235 */ 238 */
236 get_user_ex(gs, &sc->gs); 239 RELOAD_SEG(gs);
237 gs |= 3;
238 savesegment(gs, oldgs);
239 if (gs != oldgs)
240 load_gs_index(gs);
241
242 RELOAD_SEG(fs); 240 RELOAD_SEG(fs);
243 RELOAD_SEG(ds); 241 RELOAD_SEG(ds);
244 RELOAD_SEG(es); 242 RELOAD_SEG(es);
@@ -337,17 +335,13 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
337 void __user *fpstate, 335 void __user *fpstate,
338 struct pt_regs *regs, unsigned int mask) 336 struct pt_regs *regs, unsigned int mask)
339{ 337{
340 int tmp, err = 0; 338 int err = 0;
341 339
342 put_user_try { 340 put_user_try {
343 savesegment(gs, tmp); 341 put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
344 put_user_ex(tmp, (unsigned int __user *)&sc->gs); 342 put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
345 savesegment(fs, tmp); 343 put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
346 put_user_ex(tmp, (unsigned int __user *)&sc->fs); 344 put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
347 savesegment(ds, tmp);
348 put_user_ex(tmp, (unsigned int __user *)&sc->ds);
349 savesegment(es, tmp);
350 put_user_ex(tmp, (unsigned int __user *)&sc->es);
351 345
352 put_user_ex(regs->di, &sc->di); 346 put_user_ex(regs->di, &sc->di);
353 put_user_ex(regs->si, &sc->si); 347 put_user_ex(regs->si, &sc->si);
@@ -488,11 +482,6 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
488 regs->cs = __USER32_CS; 482 regs->cs = __USER32_CS;
489 regs->ss = __USER32_DS; 483 regs->ss = __USER32_DS;
490 484
491#if DEBUG_SIG
492 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
493 current->comm, current->pid, frame, regs->ip, frame->pretcode);
494#endif
495
496 return 0; 485 return 0;
497} 486}
498 487
@@ -574,10 +563,5 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
574 regs->cs = __USER32_CS; 563 regs->cs = __USER32_CS;
575 regs->ss = __USER32_DS; 564 regs->ss = __USER32_DS;
576 565
577#if DEBUG_SIG
578 printk(KERN_DEBUG "SIG deliver (%s:%d): sp=%p pc=%lx ra=%u\n",
579 current->comm, current->pid, frame, regs->ip, frame->pretcode);
580#endif
581
582 return 0; 566 return 0;
583} 567}