aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha
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/alpha
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/alpha')
-rw-r--r--arch/alpha/Kconfig3
-rw-r--r--arch/alpha/include/asm/signal.h11
-rw-r--r--arch/alpha/include/asm/unistd.h1
-rw-r--r--arch/alpha/kernel/process.c1
-rw-r--r--arch/alpha/kernel/signal.c121
5 files changed, 48 insertions, 89 deletions
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig
index dabc93649495..1ecbf7a1b677 100644
--- a/arch/alpha/Kconfig
+++ b/arch/alpha/Kconfig
@@ -21,7 +21,8 @@ config ALPHA
21 select GENERIC_STRNLEN_USER 21 select GENERIC_STRNLEN_USER
22 select HAVE_MOD_ARCH_SPECIFIC 22 select HAVE_MOD_ARCH_SPECIFIC
23 select MODULES_USE_ELF_RELA 23 select MODULES_USE_ELF_RELA
24 select GENERIC_SIGALTSTACK 24 select ODD_RT_SIGACTION
25 select OLD_SIGSUSPEND
25 help 26 help
26 The Alpha is a 64-bit general-purpose processor designed and 27 The Alpha is a 64-bit general-purpose processor designed and
27 marketed by the Digital Equipment Corporation of blessed memory, 28 marketed by the Digital Equipment Corporation of blessed memory,
diff --git a/arch/alpha/include/asm/signal.h b/arch/alpha/include/asm/signal.h
index 8a1ac28cd562..963f0494dca7 100644
--- a/arch/alpha/include/asm/signal.h
+++ b/arch/alpha/include/asm/signal.h
@@ -22,15 +22,6 @@ struct osf_sigaction {
22 int sa_flags; 22 int sa_flags;
23}; 23};
24 24
25struct sigaction { 25#define __ARCH_HAS_KA_RESTORER
26 __sighandler_t sa_handler;
27 unsigned long sa_flags;
28 sigset_t sa_mask; /* mask last for extensibility */
29};
30
31struct k_sigaction {
32 struct sigaction sa;
33 __sigrestore_t ka_restorer;
34};
35#include <asm/sigcontext.h> 26#include <asm/sigcontext.h>
36#endif 27#endif
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h
index b3396ee039b7..6d6fe7ab5473 100644
--- a/arch/alpha/include/asm/unistd.h
+++ b/arch/alpha/include/asm/unistd.h
@@ -14,7 +14,6 @@
14#define __ARCH_WANT_SYS_OLD_GETRLIMIT 14#define __ARCH_WANT_SYS_OLD_GETRLIMIT
15#define __ARCH_WANT_SYS_OLDUMOUNT 15#define __ARCH_WANT_SYS_OLDUMOUNT
16#define __ARCH_WANT_SYS_SIGPENDING 16#define __ARCH_WANT_SYS_SIGPENDING
17#define __ARCH_WANT_SYS_RT_SIGSUSPEND
18#define __ARCH_WANT_SYS_FORK 17#define __ARCH_WANT_SYS_FORK
19#define __ARCH_WANT_SYS_VFORK 18#define __ARCH_WANT_SYS_VFORK
20#define __ARCH_WANT_SYS_CLONE 19#define __ARCH_WANT_SYS_CLONE
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index b5d0d0923699..63d27fb9b023 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -250,7 +250,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
250 struct pt_regs *childregs = task_pt_regs(p); 250 struct pt_regs *childregs = task_pt_regs(p);
251 struct pt_regs *regs = current_pt_regs(); 251 struct pt_regs *regs = current_pt_regs();
252 struct switch_stack *childstack, *stack; 252 struct switch_stack *childstack, *stack;
253 unsigned long settls;
254 253
255 childstack = ((struct switch_stack *) childregs) - 1; 254 childstack = ((struct switch_stack *) childregs) - 1;
256 childti->pcb.ksp = (unsigned long) childstack; 255 childti->pcb.ksp = (unsigned long) childstack;
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 02d02c047f17..6cec2881acbf 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -113,16 +113,6 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
113} 113}
114 114
115/* 115/*
116 * Atomically swap in the new signal mask, and wait for a signal.
117 */
118SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
119{
120 sigset_t blocked;
121 siginitset(&blocked, mask);
122 return sigsuspend(&blocked);
123}
124
125/*
126 * Do a signal return; undo the signal stack. 116 * Do a signal return; undo the signal stack.
127 */ 117 */
128 118
@@ -282,12 +272,9 @@ give_sigsegv:
282 */ 272 */
283 273
284static inline void __user * 274static inline void __user *
285get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) 275get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
286{ 276{
287 if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) 277 return (void __user *)((sigsp(sp, ksig) - frame_size) & -32ul);
288 sp = current->sas_ss_sp + current->sas_ss_size;
289
290 return (void __user *)((sp - frame_size) & -32ul);
291} 278}
292 279
293static long 280static long
@@ -348,14 +335,13 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
348} 335}
349 336
350static int 337static int
351setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 338setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
352 struct pt_regs *regs)
353{ 339{
354 unsigned long oldsp, r26, err = 0; 340 unsigned long oldsp, r26, err = 0;
355 struct sigframe __user *frame; 341 struct sigframe __user *frame;
356 342
357 oldsp = rdusp(); 343 oldsp = rdusp();
358 frame = get_sigframe(ka, oldsp, sizeof(*frame)); 344 frame = get_sigframe(ksig, oldsp, sizeof(*frame));
359 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 345 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
360 return -EFAULT; 346 return -EFAULT;
361 347
@@ -365,9 +351,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
365 351
366 /* Set up to return from userspace. If provided, use a stub 352 /* Set up to return from userspace. If provided, use a stub
367 already in userspace. */ 353 already in userspace. */
368 if (ka->ka_restorer) { 354 r26 = (unsigned long) ksig->ka.ka_restorer;
369 r26 = (unsigned long) ka->ka_restorer; 355 if (!r26) {
370 } else {
371 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 356 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
372 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1); 357 err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
373 err |= __put_user(INSN_CALLSYS, frame->retcode+2); 358 err |= __put_user(INSN_CALLSYS, frame->retcode+2);
@@ -381,8 +366,8 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
381 366
382 /* "Return" to the handler */ 367 /* "Return" to the handler */
383 regs->r26 = r26; 368 regs->r26 = r26;
384 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; 369 regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
385 regs->r16 = sig; /* a0: signal number */ 370 regs->r16 = ksig->sig; /* a0: signal number */
386 regs->r17 = 0; /* a1: exception code */ 371 regs->r17 = 0; /* a1: exception code */
387 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */ 372 regs->r18 = (unsigned long) &frame->sc; /* a2: sigcontext pointer */
388 wrusp((unsigned long) frame); 373 wrusp((unsigned long) frame);
@@ -395,18 +380,17 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
395} 380}
396 381
397static int 382static int
398setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 383setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
399 sigset_t *set, struct pt_regs *regs)
400{ 384{
401 unsigned long oldsp, r26, err = 0; 385 unsigned long oldsp, r26, err = 0;
402 struct rt_sigframe __user *frame; 386 struct rt_sigframe __user *frame;
403 387
404 oldsp = rdusp(); 388 oldsp = rdusp();
405 frame = get_sigframe(ka, oldsp, sizeof(*frame)); 389 frame = get_sigframe(ksig, oldsp, sizeof(*frame));
406 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 390 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
407 return -EFAULT; 391 return -EFAULT;
408 392
409 err |= copy_siginfo_to_user(&frame->info, info); 393 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
410 394
411 /* Create the ucontext. */ 395 /* Create the ucontext. */
412 err |= __put_user(0, &frame->uc.uc_flags); 396 err |= __put_user(0, &frame->uc.uc_flags);
@@ -421,9 +405,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
421 405
422 /* Set up to return from userspace. If provided, use a stub 406 /* Set up to return from userspace. If provided, use a stub
423 already in userspace. */ 407 already in userspace. */
424 if (ka->ka_restorer) { 408 r26 = (unsigned long) ksig->ka.ka_restorer;
425 r26 = (unsigned long) ka->ka_restorer; 409 if (!r26) {
426 } else {
427 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0); 410 err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
428 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn, 411 err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
429 frame->retcode+1); 412 frame->retcode+1);
@@ -437,8 +420,8 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
437 420
438 /* "Return" to the handler */ 421 /* "Return" to the handler */
439 regs->r26 = r26; 422 regs->r26 = r26;
440 regs->r27 = regs->pc = (unsigned long) ka->sa.sa_handler; 423 regs->r27 = regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
441 regs->r16 = sig; /* a0: signal number */ 424 regs->r16 = ksig->sig; /* a0: signal number */
442 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */ 425 regs->r17 = (unsigned long) &frame->info; /* a1: siginfo pointer */
443 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */ 426 regs->r18 = (unsigned long) &frame->uc; /* a2: ucontext pointer */
444 wrusp((unsigned long) frame); 427 wrusp((unsigned long) frame);
@@ -456,22 +439,17 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
456 * OK, we're invoking a handler. 439 * OK, we're invoking a handler.
457 */ 440 */
458static inline void 441static inline void
459handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 442handle_signal(struct ksignal *ksig, struct pt_regs *regs)
460 struct pt_regs * regs)
461{ 443{
462 sigset_t *oldset = sigmask_to_save(); 444 sigset_t *oldset = sigmask_to_save();
463 int ret; 445 int ret;
464 446
465 if (ka->sa.sa_flags & SA_SIGINFO) 447 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
466 ret = setup_rt_frame(sig, ka, info, oldset, regs); 448 ret = setup_rt_frame(ksig, oldset, regs);
467 else 449 else
468 ret = setup_frame(sig, ka, oldset, regs); 450 ret = setup_frame(ksig, oldset, regs);
469 451
470 if (ret) { 452 signal_setup_done(ret, ksig, 0);
471 force_sigsegv(sig, current);
472 return;
473 }
474 signal_delivered(sig, info, ka, regs, 0);
475} 453}
476 454
477static inline void 455static inline void
@@ -514,47 +492,38 @@ syscall_restart(unsigned long r0, unsigned long r19,
514static void 492static void
515do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19) 493do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
516{ 494{
517 siginfo_t info;
518 int signr;
519 unsigned long single_stepping = ptrace_cancel_bpt(current); 495 unsigned long single_stepping = ptrace_cancel_bpt(current);
520 struct k_sigaction ka; 496 struct ksignal ksig;
521 497
522 /* This lets the debugger run, ... */ 498 /* This lets the debugger run, ... */
523 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 499 if (get_signal(&ksig)) {
524 500 /* ... so re-check the single stepping. */
525 /* ... so re-check the single stepping. */ 501 single_stepping |= ptrace_cancel_bpt(current);
526 single_stepping |= ptrace_cancel_bpt(current);
527
528 if (signr > 0) {
529 /* Whee! Actually deliver the signal. */ 502 /* Whee! Actually deliver the signal. */
530 if (r0) 503 if (r0)
531 syscall_restart(r0, r19, regs, &ka); 504 syscall_restart(r0, r19, regs, &ksig.ka);
532 handle_signal(signr, &ka, &info, regs); 505 handle_signal(&ksig, regs);
533 if (single_stepping) 506 } else {
534 ptrace_set_bpt(current); /* re-set bpt */ 507 single_stepping |= ptrace_cancel_bpt(current);
535 return; 508 if (r0) {
536 } 509 switch (regs->r0) {
537 510 case ERESTARTNOHAND:
538 if (r0) { 511 case ERESTARTSYS:
539 switch (regs->r0) { 512 case ERESTARTNOINTR:
540 case ERESTARTNOHAND: 513 /* Reset v0 and a3 and replay syscall. */
541 case ERESTARTSYS: 514 regs->r0 = r0;
542 case ERESTARTNOINTR: 515 regs->r19 = r19;
543 /* Reset v0 and a3 and replay syscall. */ 516 regs->pc -= 4;
544 regs->r0 = r0; 517 break;
545 regs->r19 = r19; 518 case ERESTART_RESTARTBLOCK:
546 regs->pc -= 4; 519 /* Set v0 to the restart_syscall and replay */
547 break; 520 regs->r0 = __NR_restart_syscall;
548 case ERESTART_RESTARTBLOCK: 521 regs->pc -= 4;
549 /* Force v0 to the restart syscall and reply. */ 522 break;
550 regs->r0 = __NR_restart_syscall; 523 }
551 regs->pc -= 4;
552 break;
553 } 524 }
525 restore_saved_sigmask();
554 } 526 }
555
556 /* If there's no signal to deliver, we just restore the saved mask. */
557 restore_saved_sigmask();
558 if (single_stepping) 527 if (single_stepping)
559 ptrace_set_bpt(current); /* re-set breakpoint */ 528 ptrace_set_bpt(current); /* re-set breakpoint */
560} 529}