diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 21:50:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-23 21:50:11 -0500 |
commit | 9e2d59ad580d590134285f361a0e80f0e98c0207 (patch) | |
tree | f3232be75781484193413f32ec82c21f6d8eb76e /arch/arm | |
parent | 5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff) | |
parent | 235b80226b986dabcbba844968f7807866bd0bfe (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/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/include/asm/signal.h | 18 | ||||
-rw-r--r-- | arch/arm/include/asm/unistd.h | 2 | ||||
-rw-r--r-- | arch/arm/kernel/calls.S | 2 | ||||
-rw-r--r-- | arch/arm/kernel/entry-common.S | 5 | ||||
-rw-r--r-- | arch/arm/kernel/signal.c | 160 |
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 | ||
19 | struct 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 | |||
26 | struct 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 | |||
33 | struct 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 |
515 | ENDPROC(sys_rt_sigreturn_wrapper) | 515 | ENDPROC(sys_rt_sigreturn_wrapper) |
516 | 516 | ||
517 | sys_sigaltstack_wrapper: | ||
518 | ldr r2, [sp, #S_OFF + S_SP] | ||
519 | b do_sigaltstack | ||
520 | ENDPROC(sys_sigaltstack_wrapper) | ||
521 | |||
522 | sys_statfs64_wrapper: | 517 | sys_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 | */ | ||
51 | asmlinkage 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 | |||
58 | asmlinkage int | ||
59 | sys_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 |
91 | static int preserve_crunch_context(struct crunch_sigframe __user *frame) | 49 | static 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 | ||
362 | static inline void __user * | 320 | static inline void __user * |
363 | get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize) | 321 | get_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 | */ | ||
343 | static 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 | |||
388 | static int | 351 | static int |
389 | setup_return(struct pt_regs *regs, struct k_sigaction *ka, | 352 | setup_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 | ||
463 | static int | 426 | static int |
464 | setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct pt_regs *regs) | 427 | setup_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 | ||
484 | static int | 447 | static int |
485 | setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info, | 448 | setup_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 | */ |
526 | static void | 482 | static void handle_signal(struct ksignal *ksig, struct pt_regs *regs) |
527 | handle_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, | |||
571 | static int do_signal(struct pt_regs *regs, int syscall) | 512 | static 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 | ||
637 | asmlinkage int | 575 | asmlinkage int |