return 0;
}
-static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize)
+static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize)
{
unsigned long sp;
return (void __user *) -1L;
/* This is the X/Open sanctioned signal stack switching. */
- if (sa->sa_flags & SA_ONSTACK) {
- if (sas_ss_flags(sp) == 0)
- sp = current->sas_ss_sp + current->sas_ss_size;
- }
-
- sp -= framesize;
+ sp = sigsp(sp, ksig) - framesize;
/* Always align the stack frame. This handles two cases. First,
* sigaltstack need not be mindful of platform specific stack
}
-static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
- int signo, sigset_t *oldset)
+static int setup_frame32(struct ksignal *ksig, struct pt_regs *regs,
+ sigset_t *oldset)
{
struct signal_frame32 __user *sf;
int i, err, wsaved;
sigframe_size += sizeof(__siginfo_rwin_t);
sf = (struct signal_frame32 __user *)
- get_sigframe(&ka->sa, regs, sigframe_size);
+ get_sigframe(ksig, regs, sigframe_size);
- if (invalid_frame_pointer(sf, sigframe_size))
- goto sigill;
+ if (invalid_frame_pointer(sf, sigframe_size)) {
+ do_exit(SIGILL);
+ return -EINVAL;
+ }
tail = (sf + 1);
err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
}
if (err)
- goto sigsegv;
+ return err;
/* 3. signal handler back-trampoline and parameters */
regs->u_regs[UREG_FP] = (unsigned long) sf;
- regs->u_regs[UREG_I0] = signo;
+ regs->u_regs[UREG_I0] = ksig->sig;
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
regs->u_regs[UREG_I2] = (unsigned long) &sf->info;
/* 4. signal handler */
- regs->tpc = (unsigned long) ka->sa.sa_handler;
+ regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
regs->tnpc = (regs->tpc + 4);
if (test_thread_flag(TIF_32BIT)) {
regs->tpc &= 0xffffffff;
}
/* 5. return to kernel instructions */
- if (ka->ka_restorer) {
- regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
+ if (ksig->ka.ka_restorer) {
+ regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
} else {
unsigned long address = ((unsigned long)&(sf->insns[0]));
err = __put_user(0x821020d8, &sf->insns[0]); /*mov __NR_sigreturn, %g1*/
err |= __put_user(0x91d02010, &sf->insns[1]); /*t 0x10*/
if (err)
- goto sigsegv;
+ return err;
flush_signal_insns(address);
}
return 0;
-
-sigill:
- do_exit(SIGILL);
- return -EINVAL;
-
-sigsegv:
- force_sigsegv(signo, current);
- return -EFAULT;
}
-static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
- unsigned long signr, sigset_t *oldset,
- siginfo_t *info)
+static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs,
+ sigset_t *oldset)
{
struct rt_signal_frame32 __user *sf;
int i, err, wsaved;
sigframe_size += sizeof(__siginfo_rwin_t);
sf = (struct rt_signal_frame32 __user *)
- get_sigframe(&ka->sa, regs, sigframe_size);
+ get_sigframe(ksig, regs, sigframe_size);
- if (invalid_frame_pointer(sf, sigframe_size))
- goto sigill;
+ if (invalid_frame_pointer(sf, sigframe_size)) {
+ do_exit(SIGILL);
+ return -EINVAL;
+ }
tail = (sf + 1);
}
/* Update the siginfo structure. */
- err |= copy_siginfo_to_user32(&sf->info, info);
+ err |= copy_siginfo_to_user32(&sf->info, &ksig->info);
/* Setup sigaltstack */
err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]);
err |= __put_user(rp->ins[7], &sf->ss.callers_pc);
}
if (err)
- goto sigsegv;
+ return err;
/* 3. signal handler back-trampoline and parameters */
regs->u_regs[UREG_FP] = (unsigned long) sf;
- regs->u_regs[UREG_I0] = signr;
+ regs->u_regs[UREG_I0] = ksig->sig;
regs->u_regs[UREG_I1] = (unsigned long) &sf->info;
regs->u_regs[UREG_I2] = (unsigned long) &sf->regs;
/* 4. signal handler */
- regs->tpc = (unsigned long) ka->sa.sa_handler;
+ regs->tpc = (unsigned long) ksig->ka.sa.sa_handler;
regs->tnpc = (regs->tpc + 4);
if (test_thread_flag(TIF_32BIT)) {
regs->tpc &= 0xffffffff;
}
/* 5. return to kernel instructions */
- if (ka->ka_restorer)
- regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer;
+ if (ksig->ka.ka_restorer)
+ regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer;
else {
unsigned long address = ((unsigned long)&(sf->insns[0]));
/* t 0x10 */
err |= __put_user(0x91d02010, &sf->insns[1]);
if (err)
- goto sigsegv;
+ return err;
flush_signal_insns(address);
}
return 0;
-
-sigill:
- do_exit(SIGILL);
- return -EINVAL;
-
-sigsegv:
- force_sigsegv(signr, current);
- return -EFAULT;
}
-static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
- siginfo_t *info,
- sigset_t *oldset, struct pt_regs *regs)
+static inline void handle_signal32(struct ksignal *ksig,
+ struct pt_regs *regs)
{
+ sigset_t *oldset = sigmask_to_save();
int err;
- if (ka->sa.sa_flags & SA_SIGINFO)
- err = setup_rt_frame32(ka, regs, signr, oldset, info);
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ err = setup_rt_frame32(ksig, regs, oldset);
else
- err = setup_frame32(ka, regs, signr, oldset);
+ err = setup_frame32(ksig, regs, oldset);
- if (err)
- return;
-
- signal_delivered(signr, info, ka, regs, 0);
+ signal_setup_done(err, ksig, 0);
}
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
* want to handle. Thus you cannot kill init even with a SIGKILL even by
* mistake.
*/
-void do_signal32(sigset_t *oldset, struct pt_regs * regs)
+void do_signal32(struct pt_regs * regs)
{
- struct k_sigaction ka;
- unsigned long orig_i0;
- int restart_syscall;
- siginfo_t info;
- int signr;
-
- signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+ struct ksignal ksig;
+ unsigned long orig_i0 = 0;
+ int restart_syscall = 0;
+ bool has_handler = get_signal(&ksig);
- restart_syscall = 0;
- orig_i0 = 0;
if (pt_regs_is_syscall(regs) &&
(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
restart_syscall = 1;
orig_i0 = regs->u_regs[UREG_G6];
}
- if (signr > 0) {
+ if (has_handler) {
if (restart_syscall)
- syscall_restart32(orig_i0, regs, &ka.sa);
- handle_signal32(signr, &ka, &info, oldset, regs);
- return;
- }
- if (restart_syscall &&
- (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
- regs->u_regs[UREG_I0] == ERESTARTSYS ||
- regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
- /* replay the system call when we are done */
- regs->u_regs[UREG_I0] = orig_i0;
- regs->tpc -= 4;
- regs->tnpc -= 4;
- pt_regs_clear_syscall(regs);
- }
- if (restart_syscall &&
- regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
- regs->u_regs[UREG_G1] = __NR_restart_syscall;
- regs->tpc -= 4;
- regs->tnpc -= 4;
- pt_regs_clear_syscall(regs);
+ syscall_restart32(orig_i0, regs, &ksig.ka.sa);
+ handle_signal32(&ksig, regs);
+ } else {
+ if (restart_syscall) {
+ switch (regs->u_regs[UREG_I0]) {
+ case ERESTARTNOHAND:
+ case ERESTARTSYS:
+ case ERESTARTNOINTR:
+ /* replay the system call when we are done */
+ regs->u_regs[UREG_I0] = orig_i0;
+ regs->tpc -= 4;
+ regs->tnpc -= 4;
+ pt_regs_clear_syscall(regs);
+ case ERESTART_RESTARTBLOCK:
+ regs->u_regs[UREG_G1] = __NR_restart_syscall;
+ regs->tpc -= 4;
+ regs->tnpc -= 4;
+ pt_regs_clear_syscall(regs);
+ }
+ }
+ restore_saved_sigmask();
}
-
- /* If there's no signal to deliver, we just put the saved sigmask
- * back
- */
- restore_saved_sigmask();
}
struct sigstack32 {