diff options
Diffstat (limited to 'arch/x86/ia32')
-rw-r--r-- | arch/x86/ia32/ia32_signal.c | 70 |
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 | ||
212 | static int ia32_restore_sigcontext(struct pt_regs *regs, | 221 | static 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 | } |