2 * linux/arch/x86_64/ia32/ia32_signal.c
4 * Copyright (C) 1991, 1992 Linus Torvalds
6 * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
7 * 2000-06-20 Pentium III FXSR, SSE support by Gareth Hughes
8 * 2000-12-* x86-64 compatibility mode signal handling by Andi Kleen
11 #include <linux/sched.h>
13 #include <linux/smp.h>
14 #include <linux/kernel.h>
15 #include <linux/errno.h>
16 #include <linux/wait.h>
17 #include <linux/unistd.h>
18 #include <linux/stddef.h>
19 #include <linux/personality.h>
20 #include <linux/compat.h>
21 #include <linux/binfmts.h>
22 #include <asm/ucontext.h>
23 #include <asm/uaccess.h>
25 #include <asm/ptrace.h>
26 #include <asm/ia32_unistd.h>
27 #include <asm/user32.h>
28 #include <asm/sigcontext32.h>
29 #include <asm/proto.h>
31 #include <asm/sigframe.h>
32 #include <asm/sighandling.h>
33 #include <asm/sys_ia32.h>
35 #define FIX_EFLAGS __FIX_EFLAGS
37 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
41 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
45 /* If you change siginfo_t structure, please make sure that
46 this code is fixed accordingly.
47 It should never copy any pad contained in the structure
48 to avoid security leaks, but must copy the generic
49 3 ints plus the relevant union member. */
50 put_user_ex(from->si_signo, &to->si_signo);
51 put_user_ex(from->si_errno, &to->si_errno);
52 put_user_ex((short)from->si_code, &to->si_code);
54 if (from->si_code < 0) {
55 put_user_ex(from->si_pid, &to->si_pid);
56 put_user_ex(from->si_uid, &to->si_uid);
57 put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
60 * First 32bits of unions are always present:
61 * si_pid === si_band === si_tid === si_addr(LS half)
63 put_user_ex(from->_sifields._pad[0],
64 &to->_sifields._pad[0]);
65 switch (from->si_code >> 16) {
66 case __SI_FAULT >> 16:
69 put_user_ex(from->si_utime, &to->si_utime);
70 put_user_ex(from->si_stime, &to->si_stime);
71 put_user_ex(from->si_status, &to->si_status);
75 put_user_ex(from->si_uid, &to->si_uid);
78 put_user_ex(from->si_fd, &to->si_fd);
80 case __SI_TIMER >> 16:
81 put_user_ex(from->si_overrun, &to->si_overrun);
82 put_user_ex(ptr_to_compat(from->si_ptr),
85 /* This is not generated by the kernel as of now. */
87 case __SI_MESGQ >> 16:
88 put_user_ex(from->si_uid, &to->si_uid);
89 put_user_ex(from->si_int, &to->si_int);
93 } put_user_catch(err);
98 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
103 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
107 get_user_ex(to->si_signo, &from->si_signo);
108 get_user_ex(to->si_errno, &from->si_errno);
109 get_user_ex(to->si_code, &from->si_code);
111 get_user_ex(to->si_pid, &from->si_pid);
112 get_user_ex(to->si_uid, &from->si_uid);
113 get_user_ex(ptr32, &from->si_ptr);
114 to->si_ptr = compat_ptr(ptr32);
115 } get_user_catch(err);
120 asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
124 current->saved_sigmask = current->blocked;
127 siginitset(&blocked, mask);
128 set_current_blocked(&blocked);
130 current->state = TASK_INTERRUPTIBLE;
133 set_restore_sigmask();
134 return -ERESTARTNOHAND;
137 asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
138 stack_ia32_t __user *uoss_ptr,
139 struct pt_regs *regs)
148 memset(&uss, 0, sizeof(stack_t));
149 if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
153 get_user_ex(ptr, &uss_ptr->ss_sp);
154 get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
155 get_user_ex(uss.ss_size, &uss_ptr->ss_size);
156 } get_user_catch(err);
160 uss.ss_sp = compat_ptr(ptr);
164 ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
166 if (ret >= 0 && uoss_ptr) {
167 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
171 put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
172 put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
173 put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
174 } put_user_catch(err);
183 * Do a signal return; undo the signal stack.
185 #define loadsegment_gs(v) load_gs_index(v)
186 #define loadsegment_fs(v) loadsegment(fs, v)
187 #define loadsegment_ds(v) loadsegment(ds, v)
188 #define loadsegment_es(v) loadsegment(es, v)
190 #define get_user_seg(seg) ({ unsigned int v; savesegment(seg, v); v; })
191 #define set_user_seg(seg, v) loadsegment_##seg(v)
194 get_user_ex(regs->x, &sc->x); \
197 #define GET_SEG(seg) ({ \
198 unsigned short tmp; \
199 get_user_ex(tmp, &sc->seg); \
203 #define COPY_SEG_CPL3(seg) do { \
204 regs->seg = GET_SEG(seg) | 3; \
207 #define RELOAD_SEG(seg) { \
208 unsigned int pre = GET_SEG(seg); \
209 unsigned int cur = get_user_seg(seg); \
212 set_user_seg(seg, pre); \
215 static int ia32_restore_sigcontext(struct pt_regs *regs,
216 struct sigcontext_ia32 __user *sc,
219 unsigned int tmpflags, err = 0;
223 /* Always make any pending restarted system calls return -EINTR */
224 current_thread_info()->restart_block.fn = do_no_restart_syscall;
228 * Reload fs and gs if they have changed in the signal
229 * handler. This does not handle long fs/gs base changes in
230 * the handler, but does not clobber them at least in the
238 COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
239 COPY(dx); COPY(cx); COPY(ip);
240 /* Don't touch extended registers */
245 get_user_ex(tmpflags, &sc->flags);
246 regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
247 /* disable syscall checks */
250 get_user_ex(tmp, &sc->fpstate);
251 buf = compat_ptr(tmp);
252 err |= restore_i387_xstate_ia32(buf);
254 get_user_ex(*pax, &sc->ax);
255 } get_user_catch(err);
260 asmlinkage long sys32_sigreturn(struct pt_regs *regs)
262 struct sigframe_ia32 __user *frame = (struct sigframe_ia32 __user *)(regs->sp-8);
266 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
268 if (__get_user(set.sig[0], &frame->sc.oldmask)
269 || (_COMPAT_NSIG_WORDS > 1
270 && __copy_from_user((((char *) &set.sig) + 4),
272 sizeof(frame->extramask))))
275 sigdelsetmask(&set, ~_BLOCKABLE);
276 set_current_blocked(&set);
278 if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
283 signal_fault(regs, frame, "32bit sigreturn");
287 asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
289 struct rt_sigframe_ia32 __user *frame;
292 struct pt_regs tregs;
294 frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
296 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
298 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
301 sigdelsetmask(&set, ~_BLOCKABLE);
302 set_current_blocked(&set);
304 if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
308 if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
314 signal_fault(regs, frame, "32bit rt sigreturn");
319 * Set up a signal frame.
322 static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
323 void __user *fpstate,
324 struct pt_regs *regs, unsigned int mask)
329 put_user_ex(get_user_seg(gs), (unsigned int __user *)&sc->gs);
330 put_user_ex(get_user_seg(fs), (unsigned int __user *)&sc->fs);
331 put_user_ex(get_user_seg(ds), (unsigned int __user *)&sc->ds);
332 put_user_ex(get_user_seg(es), (unsigned int __user *)&sc->es);
334 put_user_ex(regs->di, &sc->di);
335 put_user_ex(regs->si, &sc->si);
336 put_user_ex(regs->bp, &sc->bp);
337 put_user_ex(regs->sp, &sc->sp);
338 put_user_ex(regs->bx, &sc->bx);
339 put_user_ex(regs->dx, &sc->dx);
340 put_user_ex(regs->cx, &sc->cx);
341 put_user_ex(regs->ax, &sc->ax);
342 put_user_ex(current->thread.trap_no, &sc->trapno);
343 put_user_ex(current->thread.error_code, &sc->err);
344 put_user_ex(regs->ip, &sc->ip);
345 put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
346 put_user_ex(regs->flags, &sc->flags);
347 put_user_ex(regs->sp, &sc->sp_at_signal);
348 put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
350 put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
352 /* non-iBCS2 extensions.. */
353 put_user_ex(mask, &sc->oldmask);
354 put_user_ex(current->thread.cr2, &sc->cr2);
355 } put_user_catch(err);
361 * Determine which stack to use..
363 static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
369 /* Default to using normal stack */
372 /* This is the X/Open sanctioned signal stack switching. */
373 if (ka->sa.sa_flags & SA_ONSTACK) {
374 if (sas_ss_flags(sp) == 0)
375 sp = current->sas_ss_sp + current->sas_ss_size;
378 /* This is the legacy signal stack switching. */
379 else if ((regs->ss & 0xffff) != __USER32_DS &&
380 !(ka->sa.sa_flags & SA_RESTORER) &&
382 sp = (unsigned long) ka->sa.sa_restorer;
385 sp = sp - sig_xstate_ia32_size;
386 *fpstate = (struct _fpstate_ia32 *) sp;
387 if (save_i387_xstate_ia32(*fpstate) < 0)
388 return (void __user *) -1L;
392 /* Align the stack pointer according to the i386 ABI,
393 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
394 sp = ((sp + 4) & -16ul) - 4;
395 return (void __user *) sp;
398 int ia32_setup_frame(int sig, struct k_sigaction *ka,
399 compat_sigset_t *set, struct pt_regs *regs)
401 struct sigframe_ia32 __user *frame;
402 void __user *restorer;
404 void __user *fpstate = NULL;
406 /* copy_to_user optimizes that into a single 8 byte store */
407 static const struct {
411 } __attribute__((packed)) code = {
412 0xb858, /* popl %eax ; movl $...,%eax */
414 0x80cd, /* int $0x80 */
417 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
419 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
422 if (__put_user(sig, &frame->sig))
425 if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
428 if (_COMPAT_NSIG_WORDS > 1) {
429 if (__copy_to_user(frame->extramask, &set->sig[1],
430 sizeof(frame->extramask)))
434 if (ka->sa.sa_flags & SA_RESTORER) {
435 restorer = ka->sa.sa_restorer;
437 /* Return stub is in 32bit vsyscall page */
438 if (current->mm->context.vdso)
439 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
442 restorer = &frame->retcode;
446 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
449 * These are actually not used anymore, but left because some
450 * gdb versions depend on them as a marker.
452 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
453 } put_user_catch(err);
458 /* Set up registers for signal handler */
459 regs->sp = (unsigned long) frame;
460 regs->ip = (unsigned long) ka->sa.sa_handler;
462 /* Make -mregparm=3 work */
467 loadsegment(ds, __USER32_DS);
468 loadsegment(es, __USER32_DS);
470 regs->cs = __USER32_CS;
471 regs->ss = __USER32_DS;
476 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
477 compat_sigset_t *set, struct pt_regs *regs)
479 struct rt_sigframe_ia32 __user *frame;
480 void __user *restorer;
482 void __user *fpstate = NULL;
484 /* __copy_to_user optimizes that into a single 8 byte store */
485 static const struct {
490 } __attribute__((packed)) code = {
492 __NR_ia32_rt_sigreturn,
497 frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
499 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
503 put_user_ex(sig, &frame->sig);
504 put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
505 put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
506 err |= copy_siginfo_to_user32(&frame->info, info);
508 /* Create the ucontext. */
510 put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
512 put_user_ex(0, &frame->uc.uc_flags);
513 put_user_ex(0, &frame->uc.uc_link);
514 put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
515 put_user_ex(sas_ss_flags(regs->sp),
516 &frame->uc.uc_stack.ss_flags);
517 put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
518 err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
520 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
522 if (ka->sa.sa_flags & SA_RESTORER)
523 restorer = ka->sa.sa_restorer;
525 restorer = VDSO32_SYMBOL(current->mm->context.vdso,
527 put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
530 * Not actually used anymore, but left because some gdb
533 put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
534 } put_user_catch(err);
539 /* Set up registers for signal handler */
540 regs->sp = (unsigned long) frame;
541 regs->ip = (unsigned long) ka->sa.sa_handler;
543 /* Make -mregparm=3 work */
545 regs->dx = (unsigned long) &frame->info;
546 regs->cx = (unsigned long) &frame->uc;
548 loadsegment(ds, __USER32_DS);
549 loadsegment(es, __USER32_DS);
551 regs->cs = __USER32_CS;
552 regs->ss = __USER32_DS;