aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 21:50:11 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-23 21:50:11 -0500
commit9e2d59ad580d590134285f361a0e80f0e98c0207 (patch)
treef3232be75781484193413f32ec82c21f6d8eb76e /arch/arm
parent5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff)
parent235b80226b986dabcbba844968f7807866bd0bfe (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro: "This is the first pile; another one will come a bit later and will contain SYSCALL_DEFINE-related patches. - a bunch of signal-related syscalls (both native and compat) unified. - a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE (fixing several potential problems with missing argument validation, while we are at it) - a lot of now-pointless wrappers killed - a couple of architectures (cris and hexagon) forgot to save altstack settings into sigframe, even though they used the (uninitialized) values in sigreturn; fixed. - microblaze fixes for delivery of multiple signals arriving at once - saner set of helpers for signal delivery introduced, several architectures switched to using those." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits) x86: convert to ksignal sparc: convert to ksignal arm: switch to struct ksignal * passing alpha: pass k_sigaction and siginfo_t using ksignal pointer burying unused conditionals make do_sigaltstack() static arm64: switch to generic old sigaction() (compat-only) arm64: switch to generic compat rt_sigaction() arm64: switch compat to generic old sigsuspend arm64: switch to generic compat rt_sigqueueinfo() arm64: switch to generic compat rt_sigpending() arm64: switch to generic compat rt_sigprocmask() arm64: switch to generic sigaltstack sparc: switch to generic old sigsuspend sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE sparc: kill sign-extending wrappers for native syscalls kill sparc32_open() sparc: switch to use of generic old sigaction sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE mips: switch to generic sys_fork() and sys_clone() ...
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/include/asm/signal.h18
-rw-r--r--arch/arm/include/asm/unistd.h2
-rw-r--r--arch/arm/kernel/calls.S2
-rw-r--r--arch/arm/kernel/entry-common.S5
-rw-r--r--arch/arm/kernel/signal.c160
6 files changed, 53 insertions, 136 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 38ec1f8df5a8..a955d89ed836 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -56,6 +56,8 @@ config ARM
56 select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND 56 select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
57 select MODULES_USE_ELF_REL 57 select MODULES_USE_ELF_REL
58 select CLONE_BACKWARDS 58 select CLONE_BACKWARDS
59 select OLD_SIGSUSPEND3
60 select OLD_SIGACTION
59 help 61 help
60 The ARM series is a line of low-power-consumption RISC chip designs 62 The ARM series is a line of low-power-consumption RISC chip designs
61 licensed by ARM Ltd and targeted at embedded applications and 63 licensed by ARM Ltd and targeted at embedded applications and
diff --git a/arch/arm/include/asm/signal.h b/arch/arm/include/asm/signal.h
index 9a0ea6ab988f..c0eb412aff04 100644
--- a/arch/arm/include/asm/signal.h
+++ b/arch/arm/include/asm/signal.h
@@ -16,23 +16,7 @@ typedef struct {
16 unsigned long sig[_NSIG_WORDS]; 16 unsigned long sig[_NSIG_WORDS];
17} sigset_t; 17} sigset_t;
18 18
19struct old_sigaction { 19#define __ARCH_HAS_SA_RESTORER
20 __sighandler_t sa_handler;
21 old_sigset_t sa_mask;
22 unsigned long sa_flags;
23 __sigrestore_t sa_restorer;
24};
25
26struct sigaction {
27 __sighandler_t sa_handler;
28 unsigned long sa_flags;
29 __sigrestore_t sa_restorer;
30 sigset_t sa_mask; /* mask last for extensibility */
31};
32
33struct k_sigaction {
34 struct sigaction sa;
35};
36 20
37#include <asm/sigcontext.h> 21#include <asm/sigcontext.h>
38#endif 22#endif
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h
index 21a2700d2957..e4ddfb39ca34 100644
--- a/arch/arm/include/asm/unistd.h
+++ b/arch/arm/include/asm/unistd.h
@@ -26,8 +26,6 @@
26#define __ARCH_WANT_SYS_NICE 26#define __ARCH_WANT_SYS_NICE
27#define __ARCH_WANT_SYS_SIGPENDING 27#define __ARCH_WANT_SYS_SIGPENDING
28#define __ARCH_WANT_SYS_SIGPROCMASK 28#define __ARCH_WANT_SYS_SIGPROCMASK
29#define __ARCH_WANT_SYS_RT_SIGACTION
30#define __ARCH_WANT_SYS_RT_SIGSUSPEND
31#define __ARCH_WANT_SYS_OLD_MMAP 29#define __ARCH_WANT_SYS_OLD_MMAP
32#define __ARCH_WANT_SYS_OLD_SELECT 30#define __ARCH_WANT_SYS_OLD_SELECT
33 31
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S
index a4fda4e7a372..0cc57611fc4f 100644
--- a/arch/arm/kernel/calls.S
+++ b/arch/arm/kernel/calls.S
@@ -195,7 +195,7 @@
195 CALL(sys_getcwd) 195 CALL(sys_getcwd)
196 CALL(sys_capget) 196 CALL(sys_capget)
197/* 185 */ CALL(sys_capset) 197/* 185 */ CALL(sys_capset)
198 CALL(sys_sigaltstack_wrapper) 198 CALL(sys_sigaltstack)
199 CALL(sys_sendfile) 199 CALL(sys_sendfile)
200 CALL(sys_ni_syscall) /* getpmsg */ 200 CALL(sys_ni_syscall) /* getpmsg */
201 CALL(sys_ni_syscall) /* putpmsg */ 201 CALL(sys_ni_syscall) /* putpmsg */
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index a6c301e90a3b..3248cde504ed 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -514,11 +514,6 @@ sys_rt_sigreturn_wrapper:
514 b sys_rt_sigreturn 514 b sys_rt_sigreturn
515ENDPROC(sys_rt_sigreturn_wrapper) 515ENDPROC(sys_rt_sigreturn_wrapper)
516 516
517sys_sigaltstack_wrapper:
518 ldr r2, [sp, #S_OFF + S_SP]
519 b do_sigaltstack
520ENDPROC(sys_sigaltstack_wrapper)
521
522sys_statfs64_wrapper: 517sys_statfs64_wrapper:
523 teq r1, #88 518 teq r1, #88
524 moveq r1, #84 519 moveq r1, #84
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 56f72d257ebd..296786bdbb73 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -45,48 +45,6 @@ const unsigned long sigreturn_codes[7] = {
45 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN, 45 MOV_R7_NR_RT_SIGRETURN, SWI_SYS_RT_SIGRETURN, SWI_THUMB_RT_SIGRETURN,
46}; 46};
47 47
48/*
49 * atomically swap in the new signal mask, and wait for a signal.
50 */
51asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
52{
53 sigset_t blocked;
54 siginitset(&blocked, mask);
55 return sigsuspend(&blocked);
56}
57
58asmlinkage int
59sys_sigaction(int sig, const struct old_sigaction __user *act,
60 struct old_sigaction __user *oact)
61{
62 struct k_sigaction new_ka, old_ka;
63 int ret;
64
65 if (act) {
66 old_sigset_t mask;
67 if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
68 __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
69 __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
70 __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
71 __get_user(mask, &act->sa_mask))
72 return -EFAULT;
73 siginitset(&new_ka.sa.sa_mask, mask);
74 }
75
76 ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
77
78 if (!ret && oact) {
79 if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
80 __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
81 __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
82 __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
83 __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
84 return -EFAULT;
85 }
86
87 return ret;
88}
89
90#ifdef CONFIG_CRUNCH 48#ifdef CONFIG_CRUNCH
91static int preserve_crunch_context(struct crunch_sigframe __user *frame) 49static int preserve_crunch_context(struct crunch_sigframe __user *frame)
92{ 50{
@@ -300,7 +258,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
300 if (restore_sigframe(regs, &frame->sig)) 258 if (restore_sigframe(regs, &frame->sig))
301 goto badframe; 259 goto badframe;
302 260
303 if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT) 261 if (restore_altstack(&frame->sig.uc.uc_stack))
304 goto badframe; 262 goto badframe;
305 263
306 return regs->ARM_r0; 264 return regs->ARM_r0;
@@ -360,18 +318,12 @@ setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs, sigset_t *set)
360} 318}
361 319
362static inline void __user * 320static inline void __user *
363get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) 321get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize)
364{ 322{
365 unsigned long sp = regs->ARM_sp; 323 unsigned long sp = sigsp(regs->ARM_sp, ksig);
366 void __user *frame; 324 void __user *frame;
367 325
368 /* 326 /*
369 * This is the X/Open sanctioned signal stack switching.
370 */
371 if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
372 sp = current->sas_ss_sp + current->sas_ss_size;
373
374 /*
375 * ATPCS B01 mandates 8-byte alignment 327 * ATPCS B01 mandates 8-byte alignment
376 */ 328 */
377 frame = (void __user *)((sp - framesize) & ~7); 329 frame = (void __user *)((sp - framesize) & ~7);
@@ -385,11 +337,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
385 return frame; 337 return frame;
386} 338}
387 339
340/*
341 * translate the signal
342 */
343static inline int map_sig(int sig)
344{
345 struct thread_info *thread = current_thread_info();
346 if (sig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
347 sig = thread->exec_domain->signal_invmap[sig];
348 return sig;
349}
350
388static int 351static int
389setup_return(struct pt_regs *regs, struct k_sigaction *ka, 352setup_return(struct pt_regs *regs, struct ksignal *ksig,
390 unsigned long __user *rc, void __user *frame, int usig) 353 unsigned long __user *rc, void __user *frame)
391{ 354{
392 unsigned long handler = (unsigned long)ka->sa.sa_handler; 355 unsigned long handler = (unsigned long)ksig->ka.sa.sa_handler;
393 unsigned long retcode; 356 unsigned long retcode;
394 int thumb = 0; 357 int thumb = 0;
395 unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT); 358 unsigned long cpsr = regs->ARM_cpsr & ~(PSR_f | PSR_E_BIT);
@@ -399,7 +362,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
399 /* 362 /*
400 * Maybe we need to deliver a 32-bit signal to a 26-bit task. 363 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
401 */ 364 */
402 if (ka->sa.sa_flags & SA_THIRTYTWO) 365 if (ksig->ka.sa.sa_flags & SA_THIRTYTWO)
403 cpsr = (cpsr & ~MODE_MASK) | USR_MODE; 366 cpsr = (cpsr & ~MODE_MASK) | USR_MODE;
404 367
405#ifdef CONFIG_ARM_THUMB 368#ifdef CONFIG_ARM_THUMB
@@ -421,12 +384,12 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
421 } 384 }
422#endif 385#endif
423 386
424 if (ka->sa.sa_flags & SA_RESTORER) { 387 if (ksig->ka.sa.sa_flags & SA_RESTORER) {
425 retcode = (unsigned long)ka->sa.sa_restorer; 388 retcode = (unsigned long)ksig->ka.sa.sa_restorer;
426 } else { 389 } else {
427 unsigned int idx = thumb << 1; 390 unsigned int idx = thumb << 1;
428 391
429 if (ka->sa.sa_flags & SA_SIGINFO) 392 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
430 idx += 3; 393 idx += 3;
431 394
432 if (__put_user(sigreturn_codes[idx], rc) || 395 if (__put_user(sigreturn_codes[idx], rc) ||
@@ -451,7 +414,7 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
451 } 414 }
452 } 415 }
453 416
454 regs->ARM_r0 = usig; 417 regs->ARM_r0 = map_sig(ksig->sig);
455 regs->ARM_sp = (unsigned long)frame; 418 regs->ARM_sp = (unsigned long)frame;
456 regs->ARM_lr = retcode; 419 regs->ARM_lr = retcode;
457 regs->ARM_pc = handler; 420 regs->ARM_pc = handler;
@@ -461,9 +424,9 @@ setup_return(struct pt_regs *regs, struct k_sigaction *ka,
461} 424}
462 425
463static int 426static int
464setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) 427setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
465{ 428{
466 struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); 429 struct sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame));
467 int err = 0; 430 int err = 0;
468 431
469 if (!frame) 432 if (!frame)
@@ -476,36 +439,29 @@ setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *reg
476 439
477 err |= setup_sigframe(frame, regs, set); 440 err |= setup_sigframe(frame, regs, set);
478 if (err == 0) 441 if (err == 0)
479 err = setup_return(regs, ka, frame->retcode, frame, usig); 442 err = setup_return(regs, ksig, frame->retcode, frame);
480 443
481 return err; 444 return err;
482} 445}
483 446
484static int 447static int
485setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, 448setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
486 sigset_t *set, struct pt_regs *regs)
487{ 449{
488 struct rt_sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame)); 450 struct rt_sigframe __user *frame = get_sigframe(ksig, regs, sizeof(*frame));
489 stack_t stack;
490 int err = 0; 451 int err = 0;
491 452
492 if (!frame) 453 if (!frame)
493 return 1; 454 return 1;
494 455
495 err |= copy_siginfo_to_user(&frame->info, info); 456 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
496 457
497 __put_user_error(0, &frame->sig.uc.uc_flags, err); 458 __put_user_error(0, &frame->sig.uc.uc_flags, err);
498 __put_user_error(NULL, &frame->sig.uc.uc_link, err); 459 __put_user_error(NULL, &frame->sig.uc.uc_link, err);
499 460
500 memset(&stack, 0, sizeof(stack)); 461 err |= __save_altstack(&frame->sig.uc.uc_stack, regs->ARM_sp);
501 stack.ss_sp = (void __user *)current->sas_ss_sp;
502 stack.ss_flags = sas_ss_flags(regs->ARM_sp);
503 stack.ss_size = current->sas_ss_size;
504 err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
505
506 err |= setup_sigframe(&frame->sig, regs, set); 462 err |= setup_sigframe(&frame->sig, regs, set);
507 if (err == 0) 463 if (err == 0)
508 err = setup_return(regs, ka, frame->sig.retcode, frame, usig); 464 err = setup_return(regs, ksig, frame->sig.retcode, frame);
509 465
510 if (err == 0) { 466 if (err == 0) {
511 /* 467 /*
@@ -523,40 +479,25 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
523/* 479/*
524 * OK, we're invoking a handler 480 * OK, we're invoking a handler
525 */ 481 */
526static void 482static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
527handle_signal(unsigned long sig, struct k_sigaction *ka,
528 siginfo_t *info, struct pt_regs *regs)
529{ 483{
530 struct thread_info *thread = current_thread_info();
531 struct task_struct *tsk = current;
532 sigset_t *oldset = sigmask_to_save(); 484 sigset_t *oldset = sigmask_to_save();
533 int usig = sig;
534 int ret; 485 int ret;
535 486
536 /* 487 /*
537 * translate the signal
538 */
539 if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
540 usig = thread->exec_domain->signal_invmap[usig];
541
542 /*
543 * Set up the stack frame 488 * Set up the stack frame
544 */ 489 */
545 if (ka->sa.sa_flags & SA_SIGINFO) 490 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
546 ret = setup_rt_frame(usig, ka, info, oldset, regs); 491 ret = setup_rt_frame(ksig, oldset, regs);
547 else 492 else
548 ret = setup_frame(usig, ka, oldset, regs); 493 ret = setup_frame(ksig, oldset, regs);
549 494
550 /* 495 /*
551 * Check that the resulting registers are actually sane. 496 * Check that the resulting registers are actually sane.
552 */ 497 */
553 ret |= !valid_user_regs(regs); 498 ret |= !valid_user_regs(regs);
554 499
555 if (ret != 0) { 500 signal_setup_done(ret, ksig, 0);
556 force_sigsegv(sig, tsk);
557 return;
558 }
559 signal_delivered(sig, info, ka, regs, 0);
560} 501}
561 502
562/* 503/*
@@ -571,9 +512,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
571static int do_signal(struct pt_regs *regs, int syscall) 512static int do_signal(struct pt_regs *regs, int syscall)
572{ 513{
573 unsigned int retval = 0, continue_addr = 0, restart_addr = 0; 514 unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
574 struct k_sigaction ka; 515 struct ksignal ksig;
575 siginfo_t info;
576 int signr;
577 int restart = 0; 516 int restart = 0;
578 517
579 /* 518 /*
@@ -605,33 +544,32 @@ static int do_signal(struct pt_regs *regs, int syscall)
605 * Get the signal to deliver. When running under ptrace, at this 544 * Get the signal to deliver. When running under ptrace, at this
606 * point the debugger may change all our registers ... 545 * point the debugger may change all our registers ...
607 */ 546 */
608 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
609 /* 547 /*
610 * Depending on the signal settings we may need to revert the 548 * Depending on the signal settings we may need to revert the
611 * decision to restart the system call. But skip this if a 549 * decision to restart the system call. But skip this if a
612 * debugger has chosen to restart at a different PC. 550 * debugger has chosen to restart at a different PC.
613 */ 551 */
614 if (regs->ARM_pc != restart_addr) 552 if (get_signal(&ksig)) {
615 restart = 0; 553 /* handler */
616 if (signr > 0) { 554 if (unlikely(restart) && regs->ARM_pc == restart_addr) {
617 if (unlikely(restart)) {
618 if (retval == -ERESTARTNOHAND || 555 if (retval == -ERESTARTNOHAND ||
619 retval == -ERESTART_RESTARTBLOCK 556 retval == -ERESTART_RESTARTBLOCK
620 || (retval == -ERESTARTSYS 557 || (retval == -ERESTARTSYS
621 && !(ka.sa.sa_flags & SA_RESTART))) { 558 && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
622 regs->ARM_r0 = -EINTR; 559 regs->ARM_r0 = -EINTR;
623 regs->ARM_pc = continue_addr; 560 regs->ARM_pc = continue_addr;
624 } 561 }
625 } 562 }
626 563 handle_signal(&ksig, regs);
627 handle_signal(signr, &ka, &info, regs); 564 } else {
628 return 0; 565 /* no handler */
566 restore_saved_sigmask();
567 if (unlikely(restart) && regs->ARM_pc == restart_addr) {
568 regs->ARM_pc = continue_addr;
569 return restart;
570 }
629 } 571 }
630 572 return 0;
631 restore_saved_sigmask();
632 if (unlikely(restart))
633 regs->ARM_pc = continue_addr;
634 return restart;
635} 573}
636 574
637asmlinkage int 575asmlinkage int