diff options
Diffstat (limited to 'arch/mips/kernel/signal.c')
| -rw-r--r-- | arch/mips/kernel/signal.c | 45 |
1 files changed, 22 insertions, 23 deletions
diff --git a/arch/mips/kernel/signal.c b/arch/mips/kernel/signal.c index 2099d5a4c4b7..5922342bca39 100644 --- a/arch/mips/kernel/signal.c +++ b/arch/mips/kernel/signal.c | |||
| @@ -390,7 +390,6 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 390 | { | 390 | { |
| 391 | struct rt_sigframe __user *frame; | 391 | struct rt_sigframe __user *frame; |
| 392 | sigset_t set; | 392 | sigset_t set; |
| 393 | stack_t st; | ||
| 394 | int sig; | 393 | int sig; |
| 395 | 394 | ||
| 396 | frame = (struct rt_sigframe __user *) regs.regs[29]; | 395 | frame = (struct rt_sigframe __user *) regs.regs[29]; |
| @@ -411,11 +410,9 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs) | |||
| 411 | else if (sig) | 410 | else if (sig) |
| 412 | force_sig(sig, current); | 411 | force_sig(sig, current); |
| 413 | 412 | ||
| 414 | if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st))) | ||
| 415 | goto badframe; | ||
| 416 | /* It is more difficult to avoid calling this function than to | 413 | /* It is more difficult to avoid calling this function than to |
| 417 | call it and ignore errors. */ | 414 | call it and ignore errors. */ |
| 418 | do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]); | 415 | do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]); |
| 419 | 416 | ||
| 420 | /* | 417 | /* |
| 421 | * Don't let your children do this ... | 418 | * Don't let your children do this ... |
| @@ -550,23 +547,26 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 550 | struct mips_abi *abi = current->thread.abi; | 547 | struct mips_abi *abi = current->thread.abi; |
| 551 | void *vdso = current->mm->context.vdso; | 548 | void *vdso = current->mm->context.vdso; |
| 552 | 549 | ||
| 553 | switch(regs->regs[0]) { | 550 | if (regs->regs[0]) { |
| 554 | case ERESTART_RESTARTBLOCK: | 551 | switch(regs->regs[2]) { |
| 555 | case ERESTARTNOHAND: | 552 | case ERESTART_RESTARTBLOCK: |
| 556 | regs->regs[2] = EINTR; | 553 | case ERESTARTNOHAND: |
| 557 | break; | ||
| 558 | case ERESTARTSYS: | ||
| 559 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
| 560 | regs->regs[2] = EINTR; | 554 | regs->regs[2] = EINTR; |
| 561 | break; | 555 | break; |
| 556 | case ERESTARTSYS: | ||
| 557 | if (!(ka->sa.sa_flags & SA_RESTART)) { | ||
| 558 | regs->regs[2] = EINTR; | ||
| 559 | break; | ||
| 560 | } | ||
| 561 | /* fallthrough */ | ||
| 562 | case ERESTARTNOINTR: | ||
| 563 | regs->regs[7] = regs->regs[26]; | ||
| 564 | regs->regs[2] = regs->regs[0]; | ||
| 565 | regs->cp0_epc -= 4; | ||
| 562 | } | 566 | } |
| 563 | /* fallthrough */ | ||
| 564 | case ERESTARTNOINTR: /* Userland will reload $v0. */ | ||
| 565 | regs->regs[7] = regs->regs[26]; | ||
| 566 | regs->cp0_epc -= 8; | ||
| 567 | } | ||
| 568 | 567 | ||
| 569 | regs->regs[0] = 0; /* Don't deal with this again. */ | 568 | regs->regs[0] = 0; /* Don't deal with this again. */ |
| 569 | } | ||
| 570 | 570 | ||
| 571 | if (sig_uses_siginfo(ka)) | 571 | if (sig_uses_siginfo(ka)) |
| 572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, | 572 | ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset, |
| @@ -575,6 +575,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info, | |||
| 575 | ret = abi->setup_frame(vdso + abi->signal_return_offset, | 575 | ret = abi->setup_frame(vdso + abi->signal_return_offset, |
| 576 | ka, regs, sig, oldset); | 576 | ka, regs, sig, oldset); |
| 577 | 577 | ||
| 578 | if (ret) | ||
| 579 | return ret; | ||
| 580 | |||
| 578 | spin_lock_irq(¤t->sighand->siglock); | 581 | spin_lock_irq(¤t->sighand->siglock); |
| 579 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); | 582 | sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); |
| 580 | if (!(ka->sa.sa_flags & SA_NODEFER)) | 583 | if (!(ka->sa.sa_flags & SA_NODEFER)) |
| @@ -622,17 +625,13 @@ static void do_signal(struct pt_regs *regs) | |||
| 622 | return; | 625 | return; |
| 623 | } | 626 | } |
| 624 | 627 | ||
| 625 | /* | ||
| 626 | * Who's code doesn't conform to the restartable syscall convention | ||
| 627 | * dies here!!! The li instruction, a single machine instruction, | ||
| 628 | * must directly be followed by the syscall instruction. | ||
| 629 | */ | ||
| 630 | if (regs->regs[0]) { | 628 | if (regs->regs[0]) { |
| 631 | if (regs->regs[2] == ERESTARTNOHAND || | 629 | if (regs->regs[2] == ERESTARTNOHAND || |
| 632 | regs->regs[2] == ERESTARTSYS || | 630 | regs->regs[2] == ERESTARTSYS || |
| 633 | regs->regs[2] == ERESTARTNOINTR) { | 631 | regs->regs[2] == ERESTARTNOINTR) { |
| 632 | regs->regs[2] = regs->regs[0]; | ||
| 634 | regs->regs[7] = regs->regs[26]; | 633 | regs->regs[7] = regs->regs[26]; |
| 635 | regs->cp0_epc -= 8; | 634 | regs->cp0_epc -= 4; |
| 636 | } | 635 | } |
| 637 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { | 636 | if (regs->regs[2] == ERESTART_RESTARTBLOCK) { |
| 638 | regs->regs[2] = current->thread.abi->restart; | 637 | regs->regs[2] = current->thread.abi->restart; |
