diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-11-09 23:51:47 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-14 09:21:17 -0500 |
commit | 235b80226b986dabcbba844968f7807866bd0bfe (patch) | |
tree | 834a02573bcb1986c0b5e73af8fc8bd7d16dbffb /arch/x86/kernel | |
parent | 08f739570de697dc06b949ba3be33acdda21498c (diff) |
x86: convert to ksignal
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/signal.c | 117 |
1 files changed, 54 insertions, 63 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index d5b1f8a912ff..69562992e457 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
@@ -278,7 +278,7 @@ static const struct { | |||
278 | }; | 278 | }; |
279 | 279 | ||
280 | static int | 280 | static int |
281 | __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | 281 | __setup_frame(int sig, struct ksignal *ksig, sigset_t *set, |
282 | struct pt_regs *regs) | 282 | struct pt_regs *regs) |
283 | { | 283 | { |
284 | struct sigframe __user *frame; | 284 | struct sigframe __user *frame; |
@@ -286,7 +286,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
286 | int err = 0; | 286 | int err = 0; |
287 | void __user *fpstate = NULL; | 287 | void __user *fpstate = NULL; |
288 | 288 | ||
289 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 289 | frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); |
290 | 290 | ||
291 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 291 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
292 | return -EFAULT; | 292 | return -EFAULT; |
@@ -307,8 +307,8 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
307 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); | 307 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); |
308 | else | 308 | else |
309 | restorer = &frame->retcode; | 309 | restorer = &frame->retcode; |
310 | if (ka->sa.sa_flags & SA_RESTORER) | 310 | if (ksig->ka.sa.sa_flags & SA_RESTORER) |
311 | restorer = ka->sa.sa_restorer; | 311 | restorer = ksig->ka.sa.sa_restorer; |
312 | 312 | ||
313 | /* Set up to return from userspace. */ | 313 | /* Set up to return from userspace. */ |
314 | err |= __put_user(restorer, &frame->pretcode); | 314 | err |= __put_user(restorer, &frame->pretcode); |
@@ -327,7 +327,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
327 | 327 | ||
328 | /* Set up registers for signal handler */ | 328 | /* Set up registers for signal handler */ |
329 | regs->sp = (unsigned long)frame; | 329 | regs->sp = (unsigned long)frame; |
330 | regs->ip = (unsigned long)ka->sa.sa_handler; | 330 | regs->ip = (unsigned long)ksig->ka.sa.sa_handler; |
331 | regs->ax = (unsigned long)sig; | 331 | regs->ax = (unsigned long)sig; |
332 | regs->dx = 0; | 332 | regs->dx = 0; |
333 | regs->cx = 0; | 333 | regs->cx = 0; |
@@ -340,7 +340,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, | |||
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
343 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 343 | static int __setup_rt_frame(int sig, struct ksignal *ksig, |
344 | sigset_t *set, struct pt_regs *regs) | 344 | sigset_t *set, struct pt_regs *regs) |
345 | { | 345 | { |
346 | struct rt_sigframe __user *frame; | 346 | struct rt_sigframe __user *frame; |
@@ -348,7 +348,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
348 | int err = 0; | 348 | int err = 0; |
349 | void __user *fpstate = NULL; | 349 | void __user *fpstate = NULL; |
350 | 350 | ||
351 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 351 | frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); |
352 | 352 | ||
353 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 353 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
354 | return -EFAULT; | 354 | return -EFAULT; |
@@ -368,8 +368,8 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
368 | 368 | ||
369 | /* Set up to return from userspace. */ | 369 | /* Set up to return from userspace. */ |
370 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); | 370 | restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
371 | if (ka->sa.sa_flags & SA_RESTORER) | 371 | if (ksig->ka.sa.sa_flags & SA_RESTORER) |
372 | restorer = ka->sa.sa_restorer; | 372 | restorer = ksig->ka.sa.sa_restorer; |
373 | put_user_ex(restorer, &frame->pretcode); | 373 | put_user_ex(restorer, &frame->pretcode); |
374 | 374 | ||
375 | /* | 375 | /* |
@@ -382,7 +382,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
382 | put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); | 382 | put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode); |
383 | } put_user_catch(err); | 383 | } put_user_catch(err); |
384 | 384 | ||
385 | err |= copy_siginfo_to_user(&frame->info, info); | 385 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
386 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, | 386 | err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate, |
387 | regs, set->sig[0]); | 387 | regs, set->sig[0]); |
388 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 388 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
@@ -392,7 +392,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
392 | 392 | ||
393 | /* Set up registers for signal handler */ | 393 | /* Set up registers for signal handler */ |
394 | regs->sp = (unsigned long)frame; | 394 | regs->sp = (unsigned long)frame; |
395 | regs->ip = (unsigned long)ka->sa.sa_handler; | 395 | regs->ip = (unsigned long)ksig->ka.sa.sa_handler; |
396 | regs->ax = (unsigned long)sig; | 396 | regs->ax = (unsigned long)sig; |
397 | regs->dx = (unsigned long)&frame->info; | 397 | regs->dx = (unsigned long)&frame->info; |
398 | regs->cx = (unsigned long)&frame->uc; | 398 | regs->cx = (unsigned long)&frame->uc; |
@@ -405,20 +405,20 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
405 | return 0; | 405 | return 0; |
406 | } | 406 | } |
407 | #else /* !CONFIG_X86_32 */ | 407 | #else /* !CONFIG_X86_32 */ |
408 | static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 408 | static int __setup_rt_frame(int sig, struct ksignal *ksig, |
409 | sigset_t *set, struct pt_regs *regs) | 409 | sigset_t *set, struct pt_regs *regs) |
410 | { | 410 | { |
411 | struct rt_sigframe __user *frame; | 411 | struct rt_sigframe __user *frame; |
412 | void __user *fp = NULL; | 412 | void __user *fp = NULL; |
413 | int err = 0; | 413 | int err = 0; |
414 | 414 | ||
415 | frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe), &fp); | 415 | frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp); |
416 | 416 | ||
417 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 417 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
418 | return -EFAULT; | 418 | return -EFAULT; |
419 | 419 | ||
420 | if (ka->sa.sa_flags & SA_SIGINFO) { | 420 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
421 | if (copy_siginfo_to_user(&frame->info, info)) | 421 | if (copy_siginfo_to_user(&frame->info, &ksig->info)) |
422 | return -EFAULT; | 422 | return -EFAULT; |
423 | } | 423 | } |
424 | 424 | ||
@@ -434,8 +434,8 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
434 | /* Set up to return from userspace. If provided, use a stub | 434 | /* Set up to return from userspace. If provided, use a stub |
435 | already in userspace. */ | 435 | already in userspace. */ |
436 | /* x86-64 should always use SA_RESTORER. */ | 436 | /* x86-64 should always use SA_RESTORER. */ |
437 | if (ka->sa.sa_flags & SA_RESTORER) { | 437 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
438 | put_user_ex(ka->sa.sa_restorer, &frame->pretcode); | 438 | put_user_ex(ksig->ka.sa.sa_restorer, &frame->pretcode); |
439 | } else { | 439 | } else { |
440 | /* could use a vstub here */ | 440 | /* could use a vstub here */ |
441 | err |= -EFAULT; | 441 | err |= -EFAULT; |
@@ -457,7 +457,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
457 | next argument after the signal number on the stack. */ | 457 | next argument after the signal number on the stack. */ |
458 | regs->si = (unsigned long)&frame->info; | 458 | regs->si = (unsigned long)&frame->info; |
459 | regs->dx = (unsigned long)&frame->uc; | 459 | regs->dx = (unsigned long)&frame->uc; |
460 | regs->ip = (unsigned long) ka->sa.sa_handler; | 460 | regs->ip = (unsigned long) ksig->ka.sa.sa_handler; |
461 | 461 | ||
462 | regs->sp = (unsigned long)frame; | 462 | regs->sp = (unsigned long)frame; |
463 | 463 | ||
@@ -469,8 +469,8 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | |||
469 | } | 469 | } |
470 | #endif /* CONFIG_X86_32 */ | 470 | #endif /* CONFIG_X86_32 */ |
471 | 471 | ||
472 | static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | 472 | static int x32_setup_rt_frame(struct ksignal *ksig, |
473 | siginfo_t *info, compat_sigset_t *set, | 473 | compat_sigset_t *set, |
474 | struct pt_regs *regs) | 474 | struct pt_regs *regs) |
475 | { | 475 | { |
476 | #ifdef CONFIG_X86_X32_ABI | 476 | #ifdef CONFIG_X86_X32_ABI |
@@ -479,13 +479,13 @@ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
479 | int err = 0; | 479 | int err = 0; |
480 | void __user *fpstate = NULL; | 480 | void __user *fpstate = NULL; |
481 | 481 | ||
482 | frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); | 482 | frame = get_sigframe(&ksig->ka, regs, sizeof(*frame), &fpstate); |
483 | 483 | ||
484 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) | 484 | if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) |
485 | return -EFAULT; | 485 | return -EFAULT; |
486 | 486 | ||
487 | if (ka->sa.sa_flags & SA_SIGINFO) { | 487 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
488 | if (copy_siginfo_to_user32(&frame->info, info)) | 488 | if (copy_siginfo_to_user32(&frame->info, &ksig->info)) |
489 | return -EFAULT; | 489 | return -EFAULT; |
490 | } | 490 | } |
491 | 491 | ||
@@ -499,8 +499,8 @@ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
499 | err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp); | 499 | err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp); |
500 | put_user_ex(0, &frame->uc.uc__pad0); | 500 | put_user_ex(0, &frame->uc.uc__pad0); |
501 | 501 | ||
502 | if (ka->sa.sa_flags & SA_RESTORER) { | 502 | if (ksig->ka.sa.sa_flags & SA_RESTORER) { |
503 | restorer = ka->sa.sa_restorer; | 503 | restorer = ksig->ka.sa.sa_restorer; |
504 | } else { | 504 | } else { |
505 | /* could use a vstub here */ | 505 | /* could use a vstub here */ |
506 | restorer = NULL; | 506 | restorer = NULL; |
@@ -518,10 +518,10 @@ static int x32_setup_rt_frame(int sig, struct k_sigaction *ka, | |||
518 | 518 | ||
519 | /* Set up registers for signal handler */ | 519 | /* Set up registers for signal handler */ |
520 | regs->sp = (unsigned long) frame; | 520 | regs->sp = (unsigned long) frame; |
521 | regs->ip = (unsigned long) ka->sa.sa_handler; | 521 | regs->ip = (unsigned long) ksig->ka.sa.sa_handler; |
522 | 522 | ||
523 | /* We use the x32 calling convention here... */ | 523 | /* We use the x32 calling convention here... */ |
524 | regs->di = sig; | 524 | regs->di = ksig->sig; |
525 | regs->si = (unsigned long) &frame->info; | 525 | regs->si = (unsigned long) &frame->info; |
526 | regs->dx = (unsigned long) &frame->uc; | 526 | regs->dx = (unsigned long) &frame->uc; |
527 | 527 | ||
@@ -611,30 +611,29 @@ static int signr_convert(int sig) | |||
611 | } | 611 | } |
612 | 612 | ||
613 | static int | 613 | static int |
614 | setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, | 614 | setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) |
615 | struct pt_regs *regs) | ||
616 | { | 615 | { |
617 | int usig = signr_convert(sig); | 616 | int usig = signr_convert(ksig->sig); |
618 | sigset_t *set = sigmask_to_save(); | 617 | sigset_t *set = sigmask_to_save(); |
619 | compat_sigset_t *cset = (compat_sigset_t *) set; | 618 | compat_sigset_t *cset = (compat_sigset_t *) set; |
620 | 619 | ||
621 | /* Set up the stack frame */ | 620 | /* Set up the stack frame */ |
622 | if (is_ia32_frame()) { | 621 | if (is_ia32_frame()) { |
623 | if (ka->sa.sa_flags & SA_SIGINFO) | 622 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) |
624 | return ia32_setup_rt_frame(usig, ka, info, cset, regs); | 623 | return ia32_setup_rt_frame(usig, ksig, cset, regs); |
625 | else | 624 | else |
626 | return ia32_setup_frame(usig, ka, cset, regs); | 625 | return ia32_setup_frame(usig, ksig, cset, regs); |
627 | } else if (is_x32_frame()) { | 626 | } else if (is_x32_frame()) { |
628 | return x32_setup_rt_frame(usig, ka, info, cset, regs); | 627 | return x32_setup_rt_frame(ksig, cset, regs); |
629 | } else { | 628 | } else { |
630 | return __setup_rt_frame(sig, ka, info, set, regs); | 629 | return __setup_rt_frame(ksig->sig, ksig, set, regs); |
631 | } | 630 | } |
632 | } | 631 | } |
633 | 632 | ||
634 | static void | 633 | static void |
635 | handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | 634 | handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
636 | struct pt_regs *regs) | ||
637 | { | 635 | { |
636 | bool failed; | ||
638 | /* Are we from a system call? */ | 637 | /* Are we from a system call? */ |
639 | if (syscall_get_nr(current, regs) >= 0) { | 638 | if (syscall_get_nr(current, regs) >= 0) { |
640 | /* If so, check system call restarting.. */ | 639 | /* If so, check system call restarting.. */ |
@@ -645,7 +644,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
645 | break; | 644 | break; |
646 | 645 | ||
647 | case -ERESTARTSYS: | 646 | case -ERESTARTSYS: |
648 | if (!(ka->sa.sa_flags & SA_RESTART)) { | 647 | if (!(ksig->ka.sa.sa_flags & SA_RESTART)) { |
649 | regs->ax = -EINTR; | 648 | regs->ax = -EINTR; |
650 | break; | 649 | break; |
651 | } | 650 | } |
@@ -665,26 +664,21 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
665 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) | 664 | likely(test_and_clear_thread_flag(TIF_FORCED_TF))) |
666 | regs->flags &= ~X86_EFLAGS_TF; | 665 | regs->flags &= ~X86_EFLAGS_TF; |
667 | 666 | ||
668 | if (setup_rt_frame(sig, ka, info, regs) < 0) { | 667 | failed = (setup_rt_frame(ksig, regs) < 0); |
669 | force_sigsegv(sig, current); | 668 | if (!failed) { |
670 | return; | 669 | /* |
670 | * Clear the direction flag as per the ABI for function entry. | ||
671 | */ | ||
672 | regs->flags &= ~X86_EFLAGS_DF; | ||
673 | /* | ||
674 | * Clear TF when entering the signal handler, but | ||
675 | * notify any tracer that was single-stepping it. | ||
676 | * The tracer may want to single-step inside the | ||
677 | * handler too. | ||
678 | */ | ||
679 | regs->flags &= ~X86_EFLAGS_TF; | ||
671 | } | 680 | } |
672 | 681 | signal_setup_done(failed, ksig, test_thread_flag(TIF_SINGLESTEP)); | |
673 | /* | ||
674 | * Clear the direction flag as per the ABI for function entry. | ||
675 | */ | ||
676 | regs->flags &= ~X86_EFLAGS_DF; | ||
677 | |||
678 | /* | ||
679 | * Clear TF when entering the signal handler, but | ||
680 | * notify any tracer that was single-stepping it. | ||
681 | * The tracer may want to single-step inside the | ||
682 | * handler too. | ||
683 | */ | ||
684 | regs->flags &= ~X86_EFLAGS_TF; | ||
685 | |||
686 | signal_delivered(sig, info, ka, regs, | ||
687 | test_thread_flag(TIF_SINGLESTEP)); | ||
688 | } | 682 | } |
689 | 683 | ||
690 | #ifdef CONFIG_X86_32 | 684 | #ifdef CONFIG_X86_32 |
@@ -701,14 +695,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, | |||
701 | */ | 695 | */ |
702 | static void do_signal(struct pt_regs *regs) | 696 | static void do_signal(struct pt_regs *regs) |
703 | { | 697 | { |
704 | struct k_sigaction ka; | 698 | struct ksignal ksig; |
705 | siginfo_t info; | ||
706 | int signr; | ||
707 | 699 | ||
708 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 700 | if (get_signal(&ksig)) { |
709 | if (signr > 0) { | ||
710 | /* Whee! Actually deliver the signal. */ | 701 | /* Whee! Actually deliver the signal. */ |
711 | handle_signal(signr, &info, &ka, regs); | 702 | handle_signal(&ksig, regs); |
712 | return; | 703 | return; |
713 | } | 704 | } |
714 | 705 | ||