aboutsummaryrefslogtreecommitdiffstats
path: root/arch/cris/arch-v10/kernel
diff options
context:
space:
mode:
authorJesper Nilsson <jesper.nilsson@axis.com>2008-01-14 03:55:22 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-01-14 11:52:23 -0500
commita4858d4dab4580ec8b1fb7576f91522b6962502c (patch)
treed3b356a3f021bdffbef5d3803264b0a25a8bb1ac /arch/cris/arch-v10/kernel
parent3ea0345be38555c6a1a04ed7e9c015a42e76bd0e (diff)
CRIS v10: correct do_signal to fix oops and clean up signal handling in general
This fixes a kernel panic on boot due to do_signal not being compatible with it's callers. - do_signal now returns void, and does not have the previous signal set as a parameter. - Remove sys_rt_sigsuspend, we can use the common one instead. - Change sys_sigsuspend to be more like x86, don't call do_signal here. - handle_signal, setup_frame and setup_rt_frame now return -EFAULT if we've delivered a segfault, which is used by callers to perform necessary cleanup. - Break long lines, correct whitespace and formatting errors. Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com> Cc: Mikael Starvik <mikael.starvik@axis.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/cris/arch-v10/kernel')
-rw-r--r--arch/cris/arch-v10/kernel/signal.c251
1 files changed, 112 insertions, 139 deletions
diff --git a/arch/cris/arch-v10/kernel/signal.c b/arch/cris/arch-v10/kernel/signal.c
index 41d4a5f93284..b6be705c2a3e 100644
--- a/arch/cris/arch-v10/kernel/signal.c
+++ b/arch/cris/arch-v10/kernel/signal.c
@@ -7,7 +7,7 @@
7 * 7 *
8 * Ideas also taken from arch/arm. 8 * Ideas also taken from arch/arm.
9 * 9 *
10 * Copyright (C) 2000, 2001 Axis Communications AB 10 * Copyright (C) 2000-2007 Axis Communications AB
11 * 11 *
12 * Authors: Bjorn Wesen (bjornw@axis.com) 12 * Authors: Bjorn Wesen (bjornw@axis.com)
13 * 13 *
@@ -40,84 +40,30 @@
40 */ 40 */
41#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2; 41#define RESTART_CRIS_SYS(regs) regs->r10 = regs->orig_r10; regs->irp -= 2;
42 42
43int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs); 43void do_signal(int canrestart, struct pt_regs *regs);
44 44
45/* 45/*
46 * Atomically swap in the new signal mask, and wait for a signal. Define 46 * Atomically swap in the new signal mask, and wait for a signal. Define
47 * dummy arguments to be able to reach the regs argument. (Note that this 47 * dummy arguments to be able to reach the regs argument. (Note that this
48 * arrangement relies on old_sigset_t occupying one register.) 48 * arrangement relies on old_sigset_t occupying one register.)
49 */ 49 */
50int 50int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
51sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof, 51 long srp, struct pt_regs *regs)
52 long srp, struct pt_regs *regs)
53{ 52{
54 sigset_t saveset;
55
56 mask &= _BLOCKABLE; 53 mask &= _BLOCKABLE;
57 spin_lock_irq(&current->sighand->siglock); 54 spin_lock_irq(&current->sighand->siglock);
58 saveset = current->blocked; 55 current->saved_sigmask = current->blocked;
59 siginitset(&current->blocked, mask); 56 siginitset(&current->blocked, mask);
60 recalc_sigpending(); 57 recalc_sigpending();
61 spin_unlock_irq(&current->sighand->siglock); 58 spin_unlock_irq(&current->sighand->siglock);
62 59 current->state = TASK_INTERRUPTIBLE;
63 regs->r10 = -EINTR; 60 schedule();
64 while (1) { 61 set_thread_flag(TIF_RESTORE_SIGMASK);
65 current->state = TASK_INTERRUPTIBLE; 62 return -ERESTARTNOHAND;
66 schedule();
67 if (do_signal(0, &saveset, regs))
68 /* We will get here twice: once to call the signal
69 handler, then again to return from the
70 sigsuspend system call. When calling the
71 signal handler, R10 holds the signal number as
72 set through do_signal. The sigsuspend call
73 will return with the restored value set above;
74 always -EINTR. */
75 return regs->r10;
76 }
77} 63}
78 64
79/* Define dummy arguments to be able to reach the regs argument. (Note that 65int sys_sigaction(int sig, const struct old_sigaction __user *act,
80 * this arrangement relies on size_t occupying one register.) 66 struct old_sigaction *oact)
81 */
82int
83sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, long r12, long r13,
84 long mof, long srp, struct pt_regs *regs)
85{
86 sigset_t saveset, newset;
87
88 /* XXX: Don't preclude handling different sized sigset_t's. */
89 if (sigsetsize != sizeof(sigset_t))
90 return -EINVAL;
91
92 if (copy_from_user(&newset, unewset, sizeof(newset)))
93 return -EFAULT;
94 sigdelsetmask(&newset, ~_BLOCKABLE);
95
96 spin_lock_irq(&current->sighand->siglock);
97 saveset = current->blocked;
98 current->blocked = newset;
99 recalc_sigpending();
100 spin_unlock_irq(&current->sighand->siglock);
101
102 regs->r10 = -EINTR;
103 while (1) {
104 current->state = TASK_INTERRUPTIBLE;
105 schedule();
106 if (do_signal(0, &saveset, regs))
107 /* We will get here twice: once to call the signal
108 handler, then again to return from the
109 sigsuspend system call. When calling the
110 signal handler, R10 holds the signal number as
111 set through do_signal. The sigsuspend call
112 will return with the restored value set above;
113 always -EINTR. */
114 return regs->r10;
115 }
116}
117
118int
119sys_sigaction(int sig, const struct old_sigaction __user *act,
120 struct old_sigaction *oact)
121{ 67{
122 struct k_sigaction new_ka, old_ka; 68 struct k_sigaction new_ka, old_ka;
123 int ret; 69 int ret;
@@ -147,8 +93,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
147 return ret; 93 return ret;
148} 94}
149 95
150int 96int sys_sigaltstack(const stack_t *uss, stack_t __user *uoss)
151sys_sigaltstack(const stack_t *uss, stack_t __user *uoss)
152{ 97{
153 return do_sigaltstack(uss, uoss, rdusp()); 98 return do_sigaltstack(uss, uoss, rdusp());
154} 99}
@@ -205,7 +150,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
205 150
206 /* TODO: the other ports use regs->orig_XX to disable syscall checks 151 /* TODO: the other ports use regs->orig_XX to disable syscall checks
207 * after this completes, but we don't use that mechanism. maybe we can 152 * after this completes, but we don't use that mechanism. maybe we can
208 * use it now ? 153 * use it now ?
209 */ 154 */
210 155
211 return err; 156 return err;
@@ -216,7 +161,7 @@ badframe:
216 161
217/* Define dummy arguments to be able to reach the regs argument. */ 162/* Define dummy arguments to be able to reach the regs argument. */
218 163
219asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof, 164asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
220 long srp, struct pt_regs *regs) 165 long srp, struct pt_regs *regs)
221{ 166{
222 struct sigframe __user *frame = (struct sigframe *)rdusp(); 167 struct sigframe __user *frame = (struct sigframe *)rdusp();
@@ -243,7 +188,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
243 current->blocked = set; 188 current->blocked = set;
244 recalc_sigpending(); 189 recalc_sigpending();
245 spin_unlock_irq(&current->sighand->siglock); 190 spin_unlock_irq(&current->sighand->siglock);
246 191
247 if (restore_sigcontext(regs, &frame->sc)) 192 if (restore_sigcontext(regs, &frame->sc))
248 goto badframe; 193 goto badframe;
249 194
@@ -254,11 +199,11 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
254badframe: 199badframe:
255 force_sig(SIGSEGV, current); 200 force_sig(SIGSEGV, current);
256 return 0; 201 return 0;
257} 202}
258 203
259/* Define dummy arguments to be able to reach the regs argument. */ 204/* Define dummy arguments to be able to reach the regs argument. */
260 205
261asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13, 206asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
262 long mof, long srp, struct pt_regs *regs) 207 long mof, long srp, struct pt_regs *regs)
263{ 208{
264 struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp(); 209 struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp();
@@ -282,7 +227,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
282 current->blocked = set; 227 current->blocked = set;
283 recalc_sigpending(); 228 recalc_sigpending();
284 spin_unlock_irq(&current->sighand->siglock); 229 spin_unlock_irq(&current->sighand->siglock);
285 230
286 if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) 231 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
287 goto badframe; 232 goto badframe;
288 233
@@ -294,14 +239,14 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
294badframe: 239badframe:
295 force_sig(SIGSEGV, current); 240 force_sig(SIGSEGV, current);
296 return 0; 241 return 0;
297} 242}
298 243
299/* 244/*
300 * Set up a signal frame. 245 * Set up a signal frame.
301 */ 246 */
302 247
303static int 248static int setup_sigcontext(struct sigcontext __user *sc,
304setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned long mask) 249 struct pt_regs *regs, unsigned long mask)
305{ 250{
306 int err = 0; 251 int err = 0;
307 unsigned long usp = rdusp(); 252 unsigned long usp = rdusp();
@@ -324,10 +269,11 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, unsigned lo
324 return err; 269 return err;
325} 270}
326 271
327/* figure out where we want to put the new signal frame - usually on the stack */ 272/* Figure out where we want to put the new signal frame
273 * - usually on the stack. */
328 274
329static inline void __user * 275static inline void __user *
330get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) 276get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
331{ 277{
332 unsigned long sp = rdusp(); 278 unsigned long sp = rdusp();
333 279
@@ -345,15 +291,15 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
345} 291}
346 292
347/* grab and setup a signal frame. 293/* grab and setup a signal frame.
348 * 294 *
349 * basically we stack a lot of state info, and arrange for the 295 * basically we stack a lot of state info, and arrange for the
350 * user-mode program to return to the kernel using either a 296 * user-mode program to return to the kernel using either a
351 * trampoline which performs the syscall sigreturn, or a provided 297 * trampoline which performs the syscall sigreturn, or a provided
352 * user-mode trampoline. 298 * user-mode trampoline.
353 */ 299 */
354 300
355static void setup_frame(int sig, struct k_sigaction *ka, 301static int setup_frame(int sig, struct k_sigaction *ka,
356 sigset_t *set, struct pt_regs * regs) 302 sigset_t *set, struct pt_regs *regs)
357{ 303{
358 struct sigframe __user *frame; 304 struct sigframe __user *frame;
359 unsigned long return_ip; 305 unsigned long return_ip;
@@ -401,14 +347,15 @@ static void setup_frame(int sig, struct k_sigaction *ka,
401 347
402 wrusp((unsigned long)frame); 348 wrusp((unsigned long)frame);
403 349
404 return; 350 return 0;
405 351
406give_sigsegv: 352give_sigsegv:
407 force_sigsegv(sig, current); 353 force_sigsegv(sig, current);
354 return -EFAULT;
408} 355}
409 356
410static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 357static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
411 sigset_t *set, struct pt_regs * regs) 358 sigset_t *set, struct pt_regs *regs)
412{ 359{
413 struct rt_sigframe __user *frame; 360 struct rt_sigframe __user *frame;
414 unsigned long return_ip; 361 unsigned long return_ip;
@@ -443,9 +390,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
443 /* trampoline - the desired return ip is the retcode itself */ 390 /* trampoline - the desired return ip is the retcode itself */
444 return_ip = (unsigned long)&frame->retcode; 391 return_ip = (unsigned long)&frame->retcode;
445 /* This is movu.w __NR_rt_sigreturn, r9; break 13; */ 392 /* This is movu.w __NR_rt_sigreturn, r9; break 13; */
446 err |= __put_user(0x9c5f, (short __user*)(frame->retcode+0)); 393 err |= __put_user(0x9c5f, (short __user *)(frame->retcode+0));
447 err |= __put_user(__NR_rt_sigreturn, (short __user*)(frame->retcode+2)); 394 err |= __put_user(__NR_rt_sigreturn,
448 err |= __put_user(0xe93d, (short __user*)(frame->retcode+4)); 395 (short __user *)(frame->retcode+2));
396 err |= __put_user(0xe93d, (short __user *)(frame->retcode+4));
449 } 397 }
450 398
451 if (err) 399 if (err)
@@ -455,73 +403,81 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
455 403
456 /* Set up registers for signal handler */ 404 /* Set up registers for signal handler */
457 405
458 regs->irp = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */ 406 /* What we enter NOW */
459 regs->srp = return_ip; /* what we enter LATER */ 407 regs->irp = (unsigned long) ka->sa.sa_handler;
460 regs->r10 = sig; /* first argument is signo */ 408 /* What we enter LATER */
461 regs->r11 = (unsigned long) &frame->info; /* second argument is (siginfo_t *) */ 409 regs->srp = return_ip;
462 regs->r12 = 0; /* third argument is unused */ 410 /* First argument is signo */
463 411 regs->r10 = sig;
464 /* actually move the usp to reflect the stacked frame */ 412 /* Second argument is (siginfo_t *) */
465 413 regs->r11 = (unsigned long)&frame->info;
414 /* Third argument is unused */
415 regs->r12 = 0;
416
417 /* Actually move the usp to reflect the stacked frame */
466 wrusp((unsigned long)frame); 418 wrusp((unsigned long)frame);
467 419
468 return; 420 return 0;
469 421
470give_sigsegv: 422give_sigsegv:
471 force_sigsegv(sig, current); 423 force_sigsegv(sig, current);
424 return -EFAULT;
472} 425}
473 426
474/* 427/*
475 * OK, we're invoking a handler 428 * OK, we're invoking a handler
476 */ 429 */
477 430
478static inline void 431static inline int handle_signal(int canrestart, unsigned long sig,
479handle_signal(int canrestart, unsigned long sig, 432 siginfo_t *info, struct k_sigaction *ka,
480 siginfo_t *info, struct k_sigaction *ka, 433 sigset_t *oldset, struct pt_regs *regs)
481 sigset_t *oldset, struct pt_regs * regs)
482{ 434{
435 int ret;
436
483 /* Are we from a system call? */ 437 /* Are we from a system call? */
484 if (canrestart) { 438 if (canrestart) {
485 /* If so, check system call restarting.. */ 439 /* If so, check system call restarting.. */
486 switch (regs->r10) { 440 switch (regs->r10) {
487 case -ERESTART_RESTARTBLOCK: 441 case -ERESTART_RESTARTBLOCK:
488 case -ERESTARTNOHAND: 442 case -ERESTARTNOHAND:
489 /* ERESTARTNOHAND means that the syscall should only be 443 /* ERESTARTNOHAND means that the syscall should
490 restarted if there was no handler for the signal, and since 444 * only be restarted if there was no handler for
491 we only get here if there is a handler, we don't restart */ 445 * the signal, and since we only get here if there
446 * is a handler, we don't restart */
447 regs->r10 = -EINTR;
448 break;
449 case -ERESTARTSYS:
450 /* ERESTARTSYS means to restart the syscall if
451 * there is no handler or the handler was
452 * registered with SA_RESTART */
453 if (!(ka->sa.sa_flags & SA_RESTART)) {
492 regs->r10 = -EINTR; 454 regs->r10 = -EINTR;
493 break; 455 break;
494 456 }
495 case -ERESTARTSYS: 457 /* fallthrough */
496 /* ERESTARTSYS means to restart the syscall if there is no 458 case -ERESTARTNOINTR:
497 handler or the handler was registered with SA_RESTART */ 459 /* ERESTARTNOINTR means that the syscall should
498 if (!(ka->sa.sa_flags & SA_RESTART)) { 460 * be called again after the signal handler returns. */
499 regs->r10 = -EINTR; 461 RESTART_CRIS_SYS(regs);
500 break;
501 }
502 /* fallthrough */
503 case -ERESTARTNOINTR:
504 /* ERESTARTNOINTR means that the syscall should be called again
505 after the signal handler returns. */
506 RESTART_CRIS_SYS(regs);
507 } 462 }
508 } 463 }
509 464
510 /* Set up the stack frame */ 465 /* Set up the stack frame */
511 if (ka->sa.sa_flags & SA_SIGINFO) 466 if (ka->sa.sa_flags & SA_SIGINFO)
512 setup_rt_frame(sig, ka, info, oldset, regs); 467 ret = setup_rt_frame(sig, ka, info, oldset, regs);
513 else 468 else
514 setup_frame(sig, ka, oldset, regs); 469 ret = setup_frame(sig, ka, oldset, regs);
515 470
516 if (ka->sa.sa_flags & SA_ONESHOT) 471 if (ret == 0) {
517 ka->sa.sa_handler = SIG_DFL; 472 spin_lock_irq(&current->sighand->siglock);
518 473 sigorsets(&current->blocked, &current->blocked,
519 spin_lock_irq(&current->sighand->siglock); 474 &ka->sa.sa_mask);
520 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 475 if (!(ka->sa.sa_flags & SA_NODEFER))
521 if (!(ka->sa.sa_flags & SA_NODEFER)) 476 sigaddset(&current->blocked, sig);
522 sigaddset(&current->blocked,sig); 477 recalc_sigpending();
523 recalc_sigpending(); 478 spin_unlock_irq(&current->sighand->siglock);
524 spin_unlock_irq(&current->sighand->siglock); 479 }
480 return ret;
525} 481}
526 482
527/* 483/*
@@ -536,11 +492,12 @@ handle_signal(int canrestart, unsigned long sig,
536 * mode below. 492 * mode below.
537 */ 493 */
538 494
539int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs) 495void do_signal(int canrestart, struct pt_regs *regs)
540{ 496{
541 siginfo_t info; 497 siginfo_t info;
542 int signr; 498 int signr;
543 struct k_sigaction ka; 499 struct k_sigaction ka;
500 sigset_t *oldset;
544 501
545 /* 502 /*
546 * We want the common case to go fast, which 503 * We want the common case to go fast, which
@@ -549,16 +506,26 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
549 * if so. 506 * if so.
550 */ 507 */
551 if (!user_mode(regs)) 508 if (!user_mode(regs))
552 return 1; 509 return;
553 510
554 if (!oldset) 511 if (test_thread_flag(TIF_RESTORE_SIGMASK))
512 oldset = &current->saved_sigmask;
513 else
555 oldset = &current->blocked; 514 oldset = &current->blocked;
556 515
557 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 516 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
558 if (signr > 0) { 517 if (signr > 0) {
559 /* Whee! Actually deliver the signal. */ 518 /* Whee! Actually deliver the signal. */
560 handle_signal(canrestart, signr, &info, &ka, oldset, regs); 519 if (handle_signal(canrestart, signr, &info, &ka,
561 return 1; 520 oldset, regs)) {
521 /* a signal was successfully delivered; the saved
522 * sigmask will have been stored in the signal frame,
523 * and will be restored by sigreturn, so we can simply
524 * clear the TIF_RESTORE_SIGMASK flag */
525 if (test_thread_flag(TIF_RESTORE_SIGMASK))
526 clear_thread_flag(TIF_RESTORE_SIGMASK);
527 }
528 return;
562 } 529 }
563 530
564 /* Did we come from a system call? */ 531 /* Did we come from a system call? */
@@ -569,10 +536,16 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
569 regs->r10 == -ERESTARTNOINTR) { 536 regs->r10 == -ERESTARTNOINTR) {
570 RESTART_CRIS_SYS(regs); 537 RESTART_CRIS_SYS(regs);
571 } 538 }
572 if (regs->r10 == -ERESTART_RESTARTBLOCK){ 539 if (regs->r10 == -ERESTART_RESTARTBLOCK) {
573 regs->r10 = __NR_restart_syscall; 540 regs->r10 = __NR_restart_syscall;
574 regs->irp -= 2; 541 regs->irp -= 2;
575 } 542 }
576 } 543 }
577 return 0; 544
545 /* if there's no signal to deliver, we just put the saved sigmask
546 * back */
547 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
548 clear_thread_flag(TIF_RESTORE_SIGMASK);
549 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
550 }
578} 551}