aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/signal_32.c
diff options
context:
space:
mode:
authorHiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>2008-11-24 21:23:12 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-25 23:11:53 -0500
commitbfeb91a9435889ef4fe7bfbb4b673f625e69e790 (patch)
tree904f16d0eba56b7812b1462de6bc28df6c70371f /arch/x86/kernel/signal_32.c
parent2601657d223d82053d4e1fe1063091401e6b860a (diff)
x86: signal: cosmetic unification of __setup_sigframe() and __setup_rt_sigframe()
Impact: cleanup Add #ifdef directive to unify __setup_sigframe() and __setup_rt_sigframe(). Move them after {setup|restore}_sigcontext() declaration. Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/signal_32.c')
-rw-r--r--arch/x86/kernel/signal_32.c469
1 files changed, 280 insertions, 189 deletions
diff --git a/arch/x86/kernel/signal_32.c b/arch/x86/kernel/signal_32.c
index b3f30d2a2178..e9f71298e746 100644
--- a/arch/x86/kernel/signal_32.c
+++ b/arch/x86/kernel/signal_32.c
@@ -48,28 +48,6 @@
48# define FIX_EFLAGS __FIX_EFLAGS 48# define FIX_EFLAGS __FIX_EFLAGS
49#endif 49#endif
50 50
51static const struct {
52 u16 poplmovl;
53 u32 val;
54 u16 int80;
55} __attribute__((packed)) retcode = {
56 0xb858, /* popl %eax; movl $..., %eax */
57 __NR_sigreturn,
58 0x80cd, /* int $0x80 */
59};
60
61static const struct {
62 u8 movl;
63 u32 val;
64 u16 int80;
65 u8 pad;
66} __attribute__((packed)) rt_retcode = {
67 0xb8, /* movl $..., %eax */
68 __NR_rt_sigreturn,
69 0x80cd, /* int $0x80 */
70 0
71};
72
73#define COPY(x) { \ 51#define COPY(x) { \
74 err |= __get_user(regs->x, &sc->x); \ 52 err |= __get_user(regs->x, &sc->x); \
75} 53}
@@ -207,176 +185,30 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
207} 185}
208 186
209/* 187/*
210 * Atomically swap in the new signal mask, and wait for a signal. 188 * Set up a signal frame.
211 */ 189 */
212asmlinkage int
213sys_sigsuspend(int history0, int history1, old_sigset_t mask)
214{
215 mask &= _BLOCKABLE;
216 spin_lock_irq(&current->sighand->siglock);
217 current->saved_sigmask = current->blocked;
218 siginitset(&current->blocked, mask);
219 recalc_sigpending();
220 spin_unlock_irq(&current->sighand->siglock);
221
222 current->state = TASK_INTERRUPTIBLE;
223 schedule();
224 set_restore_sigmask();
225
226 return -ERESTARTNOHAND;
227}
228
229asmlinkage int
230sys_sigaction(int sig, const struct old_sigaction __user *act,
231 struct old_sigaction __user *oact)
232{
233 struct k_sigaction new_ka, old_ka;
234 int ret;
235
236 if (act) {
237 old_sigset_t mask;
238
239 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
240 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
241 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
242 return -EFAULT;
243
244 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
245 __get_user(mask, &act->sa_mask);
246 siginitset(&new_ka.sa.sa_mask, mask);
247 }
248
249 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
250
251 if (!ret && oact) {
252 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
253 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
254 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
255 return -EFAULT;
256
257 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
258 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
259 }
260
261 return ret;
262}
263
264#ifdef CONFIG_X86_32 190#ifdef CONFIG_X86_32
265asmlinkage int sys_sigaltstack(unsigned long bx) 191static const struct {
266{ 192 u16 poplmovl;
267 /* 193 u32 val;
268 * This is needed to make gcc realize it doesn't own the 194 u16 int80;
269 * "struct pt_regs" 195} __attribute__((packed)) retcode = {
270 */ 196 0xb858, /* popl %eax; movl $..., %eax */
271 struct pt_regs *regs = (struct pt_regs *)&bx; 197 __NR_sigreturn,
272 const stack_t __user *uss = (const stack_t __user *)bx; 198 0x80cd, /* int $0x80 */
273 stack_t __user *uoss = (stack_t __user *)regs->cx; 199};
274
275 return do_sigaltstack(uss, uoss, regs->sp);
276}
277#else /* !CONFIG_X86_32 */
278asmlinkage long
279sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
280 struct pt_regs *regs)
281{
282 return do_sigaltstack(uss, uoss, regs->sp);
283}
284#endif /* CONFIG_X86_32 */
285
286/*
287 * Do a signal return; undo the signal stack.
288 */
289asmlinkage unsigned long sys_sigreturn(unsigned long __unused)
290{
291 struct sigframe __user *frame;
292 struct pt_regs *regs;
293 unsigned long ax;
294 sigset_t set;
295
296 regs = (struct pt_regs *) &__unused;
297 frame = (struct sigframe __user *)(regs->sp - 8);
298
299 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
300 goto badframe;
301 if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1
302 && __copy_from_user(&set.sig[1], &frame->extramask,
303 sizeof(frame->extramask))))
304 goto badframe;
305
306 sigdelsetmask(&set, ~_BLOCKABLE);
307 spin_lock_irq(&current->sighand->siglock);
308 current->blocked = set;
309 recalc_sigpending();
310 spin_unlock_irq(&current->sighand->siglock);
311
312 if (restore_sigcontext(regs, &frame->sc, &ax))
313 goto badframe;
314 return ax;
315
316badframe:
317 if (show_unhandled_signals && printk_ratelimit()) {
318 printk("%s%s[%d] bad frame in sigreturn frame:"
319 "%p ip:%lx sp:%lx oeax:%lx",
320 task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
321 current->comm, task_pid_nr(current), frame, regs->ip,
322 regs->sp, regs->orig_ax);
323 print_vma_addr(" in ", regs->ip);
324 printk(KERN_CONT "\n");
325 }
326
327 force_sig(SIGSEGV, current);
328
329 return 0;
330}
331
332static long do_rt_sigreturn(struct pt_regs *regs)
333{
334 struct rt_sigframe __user *frame;
335 unsigned long ax;
336 sigset_t set;
337
338 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
339 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
340 goto badframe;
341 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
342 goto badframe;
343
344 sigdelsetmask(&set, ~_BLOCKABLE);
345 spin_lock_irq(&current->sighand->siglock);
346 current->blocked = set;
347 recalc_sigpending();
348 spin_unlock_irq(&current->sighand->siglock);
349
350 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
351 goto badframe;
352
353 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
354 goto badframe;
355
356 return ax;
357
358badframe:
359 signal_fault(regs, frame, "rt_sigreturn");
360 return 0;
361}
362
363#ifdef CONFIG_X86_32
364asmlinkage int sys_rt_sigreturn(unsigned long __unused)
365{
366 struct pt_regs *regs = (struct pt_regs *)&__unused;
367
368 return do_rt_sigreturn(regs);
369}
370#else /* !CONFIG_X86_32 */
371asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
372{
373 return do_rt_sigreturn(regs);
374}
375#endif /* CONFIG_X86_32 */
376 200
377/* 201static const struct {
378 * Set up a signal frame. 202 u8 movl;
379 */ 203 u32 val;
204 u16 int80;
205 u8 pad;
206} __attribute__((packed)) rt_retcode = {
207 0xb8, /* movl $..., %eax */
208 __NR_rt_sigreturn,
209 0x80cd, /* int $0x80 */
210 0
211};
380 212
381/* 213/*
382 * Determine which stack to use.. 214 * Determine which stack to use..
@@ -557,6 +389,265 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
557 389
558 return 0; 390 return 0;
559} 391}
392#else /* !CONFIG_X86_32 */
393/*
394 * Determine which stack to use..
395 */
396static void __user *
397get_stack(struct k_sigaction *ka, unsigned long sp, unsigned long size)
398{
399 /* Default to using normal stack - redzone*/
400 sp -= 128;
401
402 /* This is the X/Open sanctioned signal stack switching. */
403 if (ka->sa.sa_flags & SA_ONSTACK) {
404 if (sas_ss_flags(sp) == 0)
405 sp = current->sas_ss_sp + current->sas_ss_size;
406 }
407
408 return (void __user *)round_down(sp - size, 64);
409}
410
411static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
412 sigset_t *set, struct pt_regs *regs)
413{
414 struct rt_sigframe __user *frame;
415 void __user *fp = NULL;
416 int err = 0;
417 struct task_struct *me = current;
418
419 if (used_math()) {
420 fp = get_stack(ka, regs->sp, sig_xstate_size);
421 frame = (void __user *)round_down(
422 (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;
423
424 if (save_i387_xstate(fp) < 0)
425 return -EFAULT;
426 } else
427 frame = get_stack(ka, regs->sp, sizeof(struct rt_sigframe)) - 8;
428
429 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
430 return -EFAULT;
431
432 if (ka->sa.sa_flags & SA_SIGINFO) {
433 if (copy_siginfo_to_user(&frame->info, info))
434 return -EFAULT;
435 }
436
437 /* Create the ucontext. */
438 if (cpu_has_xsave)
439 err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
440 else
441 err |= __put_user(0, &frame->uc.uc_flags);
442 err |= __put_user(0, &frame->uc.uc_link);
443 err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
444 err |= __put_user(sas_ss_flags(regs->sp),
445 &frame->uc.uc_stack.ss_flags);
446 err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
447 err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
448 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
449
450 /* Set up to return from userspace. If provided, use a stub
451 already in userspace. */
452 /* x86-64 should always use SA_RESTORER. */
453 if (ka->sa.sa_flags & SA_RESTORER) {
454 err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
455 } else {
456 /* could use a vstub here */
457 return -EFAULT;
458 }
459
460 if (err)
461 return -EFAULT;
462
463 /* Set up registers for signal handler */
464 regs->di = sig;
465 /* In case the signal handler was declared without prototypes */
466 regs->ax = 0;
467
468 /* This also works for non SA_SIGINFO handlers because they expect the
469 next argument after the signal number on the stack. */
470 regs->si = (unsigned long)&frame->info;
471 regs->dx = (unsigned long)&frame->uc;
472 regs->ip = (unsigned long) ka->sa.sa_handler;
473
474 regs->sp = (unsigned long)frame;
475
476 /* Set up the CS register to run signal handlers in 64-bit mode,
477 even if the handler happens to be interrupting 32-bit code. */
478 regs->cs = __USER_CS;
479
480 return 0;
481}
482#endif /* CONFIG_X86_32 */
483
484/*
485 * Atomically swap in the new signal mask, and wait for a signal.
486 */
487asmlinkage int
488sys_sigsuspend(int history0, int history1, old_sigset_t mask)
489{
490 mask &= _BLOCKABLE;
491 spin_lock_irq(&current->sighand->siglock);
492 current->saved_sigmask = current->blocked;
493 siginitset(&current->blocked, mask);
494 recalc_sigpending();
495 spin_unlock_irq(&current->sighand->siglock);
496
497 current->state = TASK_INTERRUPTIBLE;
498 schedule();
499 set_restore_sigmask();
500
501 return -ERESTARTNOHAND;
502}
503
504asmlinkage int
505sys_sigaction(int sig, const struct old_sigaction __user *act,
506 struct old_sigaction __user *oact)
507{
508 struct k_sigaction new_ka, old_ka;
509 int ret;
510
511 if (act) {
512 old_sigset_t mask;
513
514 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
515 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
516 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
517 return -EFAULT;
518
519 __get_user(new_ka.sa.sa_flags, &act->sa_flags);
520 __get_user(mask, &act->sa_mask);
521 siginitset(&new_ka.sa.sa_mask, mask);
522 }
523
524 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
525
526 if (!ret && oact) {
527 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
528 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
529 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
530 return -EFAULT;
531
532 __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
533 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
534 }
535
536 return ret;
537}
538
539#ifdef CONFIG_X86_32
540asmlinkage int sys_sigaltstack(unsigned long bx)
541{
542 /*
543 * This is needed to make gcc realize it doesn't own the
544 * "struct pt_regs"
545 */
546 struct pt_regs *regs = (struct pt_regs *)&bx;
547 const stack_t __user *uss = (const stack_t __user *)bx;
548 stack_t __user *uoss = (stack_t __user *)regs->cx;
549
550 return do_sigaltstack(uss, uoss, regs->sp);
551}
552#else /* !CONFIG_X86_32 */
553asmlinkage long
554sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
555 struct pt_regs *regs)
556{
557 return do_sigaltstack(uss, uoss, regs->sp);
558}
559#endif /* CONFIG_X86_32 */
560
561/*
562 * Do a signal return; undo the signal stack.
563 */
564asmlinkage unsigned long sys_sigreturn(unsigned long __unused)
565{
566 struct sigframe __user *frame;
567 struct pt_regs *regs;
568 unsigned long ax;
569 sigset_t set;
570
571 regs = (struct pt_regs *) &__unused;
572 frame = (struct sigframe __user *)(regs->sp - 8);
573
574 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
575 goto badframe;
576 if (__get_user(set.sig[0], &frame->sc.oldmask) || (_NSIG_WORDS > 1
577 && __copy_from_user(&set.sig[1], &frame->extramask,
578 sizeof(frame->extramask))))
579 goto badframe;
580
581 sigdelsetmask(&set, ~_BLOCKABLE);
582 spin_lock_irq(&current->sighand->siglock);
583 current->blocked = set;
584 recalc_sigpending();
585 spin_unlock_irq(&current->sighand->siglock);
586
587 if (restore_sigcontext(regs, &frame->sc, &ax))
588 goto badframe;
589 return ax;
590
591badframe:
592 if (show_unhandled_signals && printk_ratelimit()) {
593 printk("%s%s[%d] bad frame in sigreturn frame:"
594 "%p ip:%lx sp:%lx oeax:%lx",
595 task_pid_nr(current) > 1 ? KERN_INFO : KERN_EMERG,
596 current->comm, task_pid_nr(current), frame, regs->ip,
597 regs->sp, regs->orig_ax);
598 print_vma_addr(" in ", regs->ip);
599 printk(KERN_CONT "\n");
600 }
601
602 force_sig(SIGSEGV, current);
603
604 return 0;
605}
606
607static long do_rt_sigreturn(struct pt_regs *regs)
608{
609 struct rt_sigframe __user *frame;
610 unsigned long ax;
611 sigset_t set;
612
613 frame = (struct rt_sigframe __user *)(regs->sp - sizeof(long));
614 if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
615 goto badframe;
616 if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
617 goto badframe;
618
619 sigdelsetmask(&set, ~_BLOCKABLE);
620 spin_lock_irq(&current->sighand->siglock);
621 current->blocked = set;
622 recalc_sigpending();
623 spin_unlock_irq(&current->sighand->siglock);
624
625 if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
626 goto badframe;
627
628 if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->sp) == -EFAULT)
629 goto badframe;
630
631 return ax;
632
633badframe:
634 signal_fault(regs, frame, "rt_sigreturn");
635 return 0;
636}
637
638#ifdef CONFIG_X86_32
639asmlinkage int sys_rt_sigreturn(unsigned long __unused)
640{
641 struct pt_regs *regs = (struct pt_regs *)&__unused;
642
643 return do_rt_sigreturn(regs);
644}
645#else /* !CONFIG_X86_32 */
646asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
647{
648 return do_rt_sigreturn(regs);
649}
650#endif /* CONFIG_X86_32 */
560 651
561/* 652/*
562 * OK, we're invoking a handler: 653 * OK, we're invoking a handler: