From 99b06feb0f7c99f171cb962d0e6a17f81625abd3 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 23 Dec 2012 03:41:17 -0500 Subject: sparc: switch to generic sigaltstack Signed-off-by: Al Viro --- arch/sparc/kernel/signal_32.c | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) (limited to 'arch/sparc/kernel/signal_32.c') diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 68f9c8650af4..7391fa89651f 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -141,9 +141,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) unsigned int psr, pc, npc; __siginfo_fpu_t __user *fpu_save; __siginfo_rwin_t __user *rwin_save; - mm_segment_t old_fs; sigset_t set; - stack_t st; int err; synchronize_user_stack(); @@ -171,8 +169,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) if (!err && fpu_save) err |= restore_fpu_state(regs, fpu_save); err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t)); - - err |= __copy_from_user(&st, &sf->stack, sizeof(stack_t)); + err |= restore_altstack(&sf->stack); if (err) goto segv; @@ -180,14 +177,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) regs->pc = pc; regs->npc = npc; - /* It is more difficult to avoid calling this function than to - * call it and ignore errors. - */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((const stack_t __user *) &st, NULL, (unsigned long)sf); - set_fs(old_fs); - err |= __get_user(rwin_save, &sf->rwin_save); if (!err && rwin_save) { if (restore_rwin_state(rwin_save)) @@ -391,9 +380,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __copy_to_user(&sf->mask, &oldset->sig[0], sizeof(sigset_t)); /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &sf->stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &sf->stack.ss_flags); - err |= __put_user(current->sas_ss_size, &sf->stack.ss_size); + err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]); if (!wsaved) { err |= __copy_to_user(sf, (char *) regs->u_regs[UREG_FP], -- cgit v1.2.3 From c9716252befda972c94d2bbfa88abddf3377f8c5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sun, 25 Nov 2012 01:53:12 -0500 Subject: sparc: bury the sys_sigpause() remains Signed-off-by: Al Viro --- arch/sparc/kernel/signal_32.c | 7 +------ arch/sparc/kernel/signal_64.c | 12 +----------- arch/sparc/kernel/systbls.h | 1 - 3 files changed, 2 insertions(+), 18 deletions(-) (limited to 'arch/sparc/kernel/signal_32.c') diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 7391fa89651f..6541604329c4 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -59,18 +59,13 @@ struct rt_signal_frame { #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) -static int _sigpause_common(old_sigset_t set) +asmlinkage int sys_sigsuspend(old_sigset_t set) { sigset_t blocked; siginitset(&blocked, set); return sigsuspend(&blocked); } -asmlinkage int sys_sigsuspend(old_sigset_t set) -{ - return _sigpause_common(set); -} - asmlinkage void do_sigreturn(struct pt_regs *regs) { struct signal_frame __user *sf; diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 176e0e7b8f60..ea9d14ad1ea2 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -236,23 +236,13 @@ struct rt_signal_frame { __siginfo_rwin_t *rwin_save; }; -static long _sigpause_common(old_sigset_t set) +asmlinkage long sys_sigsuspend(old_sigset_t set) { sigset_t blocked; siginitset(&blocked, set); return sigsuspend(&blocked); } -asmlinkage long sys_sigpause(unsigned int set) -{ - return _sigpause_common(set); -} - -asmlinkage long sys_sigsuspend(old_sigset_t set) -{ - return _sigpause_common(set); -} - void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h index 1dd89dbac8d8..5f8090951bd5 100644 --- a/arch/sparc/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h @@ -36,7 +36,6 @@ extern asmlinkage long sys_rt_sigaction(int sig, extern asmlinkage void sparc64_set_context(struct pt_regs *regs); extern asmlinkage void sparc64_get_context(struct pt_regs *regs); -extern asmlinkage long sys_sigpause(unsigned int set); extern asmlinkage long sys_sigsuspend(old_sigset_t set); extern void do_rt_sigreturn(struct pt_regs *regs); -- cgit v1.2.3 From 52ad6b3f90c63653ba24c4f63f218a925b8e14d7 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 25 Dec 2012 16:18:10 -0500 Subject: sparc: switch to generic old sigsuspend Signed-off-by: Al Viro --- arch/sparc/Kconfig | 1 + arch/sparc/kernel/signal_32.c | 7 ------- arch/sparc/kernel/signal_64.c | 7 ------- arch/sparc/kernel/systbls.h | 1 - 4 files changed, 1 insertion(+), 15 deletions(-) (limited to 'arch/sparc/kernel/signal_32.c') diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 1a8ef82b3475..e557b0821540 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -47,6 +47,7 @@ config SPARC select GENERIC_COMPAT_RT_SIGPROCMASK select GENERIC_COMPAT_RT_SIGPENDING select GENERIC_COMPAT_RT_SIGACTION + select OLD_SIGSUSPEND config SPARC32 def_bool !64BIT diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 6541604329c4..cd1823487759 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -59,13 +59,6 @@ struct rt_signal_frame { #define SF_ALIGNEDSZ (((sizeof(struct signal_frame) + 7) & (~7))) #define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame) + 7) & (~7))) -asmlinkage int sys_sigsuspend(old_sigset_t set) -{ - sigset_t blocked; - siginitset(&blocked, set); - return sigsuspend(&blocked); -} - asmlinkage void do_sigreturn(struct pt_regs *regs) { struct signal_frame __user *sf; diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index ea9d14ad1ea2..165a897a4133 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -236,13 +236,6 @@ struct rt_signal_frame { __siginfo_rwin_t *rwin_save; }; -asmlinkage long sys_sigsuspend(old_sigset_t set) -{ - sigset_t blocked; - siginitset(&blocked, set); - return sigsuspend(&blocked); -} - void do_rt_sigreturn(struct pt_regs *regs) { struct rt_signal_frame __user *sf; diff --git a/arch/sparc/kernel/systbls.h b/arch/sparc/kernel/systbls.h index 5f8090951bd5..26e6dd72e92a 100644 --- a/arch/sparc/kernel/systbls.h +++ b/arch/sparc/kernel/systbls.h @@ -36,7 +36,6 @@ extern asmlinkage long sys_rt_sigaction(int sig, extern asmlinkage void sparc64_set_context(struct pt_regs *regs); extern asmlinkage void sparc64_get_context(struct pt_regs *regs); -extern asmlinkage long sys_sigsuspend(old_sigset_t set); extern void do_rt_sigreturn(struct pt_regs *regs); #endif /* _SYSTBLS_H */ -- cgit v1.2.3 From 08f739570de697dc06b949ba3be33acdda21498c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 7 Nov 2012 23:48:13 -0500 Subject: sparc: convert to ksignal Signed-off-by: Al Viro --- arch/sparc/kernel/signal32.c | 154 +++++++++++++++++------------------------- arch/sparc/kernel/signal_32.c | 146 ++++++++++++++++----------------------- arch/sparc/kernel/signal_64.c | 118 ++++++++++++-------------------- 3 files changed, 164 insertions(+), 254 deletions(-) (limited to 'arch/sparc/kernel/signal_32.c') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 9d9eb91d0de1..cd5dc4d411d1 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -323,7 +323,7 @@ static int invalid_frame_pointer(void __user *fp, int fplen) 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; @@ -338,12 +338,7 @@ static void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns 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 @@ -414,8 +409,8 @@ out_irqs_on: } -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; @@ -437,10 +432,12 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, 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); @@ -514,16 +511,16 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, 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; @@ -531,8 +528,8 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, } /* 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])); @@ -541,23 +538,14 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, 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; @@ -579,10 +567,12 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, 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); @@ -627,7 +617,7 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, } /* 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]); @@ -660,16 +650,16 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, 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; @@ -677,8 +667,8 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, } /* 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])); @@ -690,36 +680,25 @@ static int setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, /* 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, @@ -749,50 +728,41 @@ static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs */ void do_signal32(sigset_t *oldset, 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 { diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index cd1823487759..7d5d8e1f8415 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -186,7 +186,7 @@ static inline int invalid_frame_pointer(void __user *fp, int fplen) return 0; } -static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned long framesize) +static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = regs->u_regs[UREG_FP]; @@ -198,12 +198,7 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re 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 @@ -216,8 +211,8 @@ static inline void __user *get_sigframe(struct sigaction *sa, struct pt_regs *re return (void __user *) sp; } -static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset) +static int setup_frame(struct ksignal *ksig, struct pt_regs *regs, + sigset_t *oldset) { struct signal_frame __user *sf; int sigframe_size, err, wsaved; @@ -235,10 +230,12 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct signal_frame __user *) - get_sigframe(&ka->sa, regs, sigframe_size); + get_sigframe(ksig, regs, sigframe_size); - if (invalid_frame_pointer(sf, sigframe_size)) - goto sigill_and_return; + if (invalid_frame_pointer(sf, sigframe_size)) { + do_exit(SIGILL); + return -EINVAL; + } tail = sf + 1; @@ -277,21 +274,21 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); } 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->pc = (unsigned long) ka->sa.sa_handler; + regs->pc = (unsigned long) ksig->ka.sa.sa_handler; regs->npc = (regs->pc + 4); /* 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 { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); @@ -301,24 +298,16 @@ static int setup_frame(struct k_sigaction *ka, struct pt_regs *regs, /* t 0x10 */ err |= __put_user(0x91d02010, &sf->insns[1]); if (err) - goto sigsegv; + return err; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } return 0; - -sigill_and_return: - do_exit(SIGILL); - return -EINVAL; - -sigsegv: - force_sigsegv(signo, current); - return -EFAULT; } -static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset, siginfo_t *info) +static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs, + sigset_t *oldset) { struct rt_signal_frame __user *sf; int sigframe_size, wsaved; @@ -334,9 +323,11 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, if (wsaved) sigframe_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) - get_sigframe(&ka->sa, regs, sigframe_size); - if (invalid_frame_pointer(sf, sigframe_size)) - goto sigill; + get_sigframe(ksig, regs, sigframe_size); + if (invalid_frame_pointer(sf, sigframe_size)) { + do_exit(SIGILL); + return -EINVAL; + } tail = sf + 1; err = __put_user(regs->pc, &sf->regs.pc); @@ -380,21 +371,21 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, err |= __copy_to_user(sf, rp, sizeof(struct reg_window32)); } - err |= copy_siginfo_to_user(&sf->info, info); + err |= copy_siginfo_to_user(&sf->info, &ksig->info); if (err) - goto sigsegv; + return err; 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->regs; - regs->pc = (unsigned long) ka->sa.sa_handler; + regs->pc = (unsigned long) ksig->ka.sa.sa_handler; regs->npc = (regs->pc + 4); - 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 { regs->u_regs[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); @@ -404,38 +395,25 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, /* t 0x10 */ err |= __put_user(0x91d02010, &sf->insns[1]); if (err) - goto sigsegv; + return err; /* Flush instruction space. */ flush_sig_insns(current->mm, (unsigned long) &(sf->insns[0])); } return 0; - -sigill: - do_exit(SIGILL); - return -EINVAL; - -sigsegv: - force_sigsegv(signo, current); - return -EFAULT; } static inline void -handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, struct pt_regs *regs) +handle_signal(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_frame(ka, regs, signr, oldset, info); + if (ksig->ka.sa.sa_flags & SA_SIGINFO) + err = setup_rt_frame(ksig, regs, oldset); else - err = setup_frame(ka, regs, signr, oldset); - - if (err) - return; - - signal_delivered(signr, info, ka, regs, 0); + err = setup_frame(ksig, regs, oldset); + signal_setup_done(err, ksig, 0); } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -465,10 +443,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, */ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { - struct k_sigaction ka; + struct ksignal ksig; int restart_syscall; - siginfo_t info; - int signr; + bool has_handler; /* It's a lot of work and synchronization to add a new ptrace * register for GDB to save and restore in order to get @@ -491,7 +468,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) regs->u_regs[UREG_G6] = orig_i0; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); + has_handler = get_signal(&ksig); /* If the debugger messes with the program counter, it clears * the software "in syscall" bit, directing us to not perform @@ -503,35 +480,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) orig_i0 = regs->u_regs[UREG_G6]; } - - if (signr > 0) { + if (has_handler) { if (restart_syscall) - syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, 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->pc -= 4; - regs->npc -= 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->pc -= 4; - regs->npc -= 4; - pt_regs_clear_syscall(regs); + syscall_restart(orig_i0, regs, &ksig.ka.sa); + handle_signal(&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->pc -= 4; + regs->npc -= 4; + pt_regs_clear_syscall(regs); + case ERESTART_RESTARTBLOCK: + regs->u_regs[UREG_G1] = __NR_restart_syscall; + regs->pc -= 4; + regs->npc -= 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(); } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 165a897a4133..35923e8abd82 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -308,7 +308,7 @@ static int invalid_frame_pointer(void __user *fp) return 0; } -static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, unsigned long framesize) +static inline void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs, unsigned long framesize) { unsigned long sp = regs->u_regs[UREG_FP] + STACK_BIAS; @@ -320,12 +320,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * return (void __user *) -1L; /* This is the X/Open sanctioned signal stack switching. */ - if (ka->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 @@ -339,8 +334,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs * } static inline int -setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, - int signo, sigset_t *oldset, siginfo_t *info) +setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs) { struct rt_signal_frame __user *sf; int wsaved, err, sf_size; @@ -358,10 +352,12 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, if (wsaved) sf_size += sizeof(__siginfo_rwin_t); sf = (struct rt_signal_frame __user *) - get_sigframe(ka, regs, sf_size); + get_sigframe(ksig, regs, sf_size); - if (invalid_frame_pointer (sf)) - goto sigill; + if (invalid_frame_pointer (sf)) { + do_exit(SIGILL); /* won't return, actually */ + return -EINVAL; + } tail = (sf + 1); @@ -389,7 +385,7 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, /* Setup sigaltstack */ err |= __save_altstack(&sf->stack, regs->u_regs[UREG_FP]); - err |= copy_to_user(&sf->mask, oldset, sizeof(sigset_t)); + err |= copy_to_user(&sf->mask, sigmask_to_save(), sizeof(sigset_t)); if (!wsaved) { err |= copy_in_user((u64 __user *)sf, @@ -402,18 +398,18 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, rp = ¤t_thread_info()->reg_window[wsaved - 1]; err |= copy_to_user(sf, rp, sizeof(struct reg_window)); } - if (info) - err |= copy_siginfo_to_user(&sf->info, info); + if (ksig->ka.sa.sa_flags & SA_SIGINFO) + err |= copy_siginfo_to_user(&sf->info, &ksig->info); else { - err |= __put_user(signo, &sf->info.si_signo); + err |= __put_user(ksig->sig, &sf->info.si_signo); err |= __put_user(SI_NOINFO, &sf->info.si_code); } if (err) - goto sigsegv; + return err; /* 3. signal handler back-trampoline and parameters */ regs->u_regs[UREG_FP] = ((unsigned long) sf) - STACK_BIAS; - regs->u_regs[UREG_I0] = signo; + regs->u_regs[UREG_I0] = ksig->sig; regs->u_regs[UREG_I1] = (unsigned long) &sf->info; /* The sigcontext is passed in this way because of how it @@ -423,37 +419,15 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs, regs->u_regs[UREG_I2] = (unsigned long) &sf->info; /* 5. 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; regs->tnpc &= 0xffffffff; } /* 4. return to kernel instructions */ - regs->u_regs[UREG_I7] = (unsigned long)ka->ka_restorer; + regs->u_regs[UREG_I7] = (unsigned long)ksig->ka.ka_restorer; return 0; - -sigill: - do_exit(SIGILL); - return -EINVAL; - -sigsegv: - force_sigsegv(signo, current); - return -EFAULT; -} - -static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs) -{ - int err; - - err = setup_rt_frame(ka, regs, signr, oldset, - (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); - if (err) - return; - - signal_delivered(signr, info, ka, regs, 0); } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -483,11 +457,9 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, */ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { - struct k_sigaction ka; + struct ksignal ksig; int restart_syscall; - sigset_t *oldset = sigmask_to_save(); - siginfo_t info; - int signr; + bool has_handler; /* It's a lot of work and synchronization to add a new ptrace * register for GDB to save and restore in order to get @@ -513,13 +485,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { - extern void do_signal32(sigset_t *, struct pt_regs *); - do_signal32(oldset, regs); + extern void do_signal32(struct pt_regs *); + do_signal32(regs); return; } #endif - signr = get_signal_to_deliver(&info, &ka, regs, NULL); + has_handler = get_signal(&ksig); restart_syscall = 0; if (pt_regs_is_syscall(regs) && @@ -528,34 +500,30 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) orig_i0 = regs->u_regs[UREG_G6]; } - if (signr > 0) { + if (has_handler) { if (restart_syscall) - syscall_restart(orig_i0, regs, &ka.sa); - handle_signal(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_restart(orig_i0, regs, &ksig.ka.sa); + signal_setup_done(setup_rt_frame(&ksig, regs), &ksig, 0); + } 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(); } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) -- cgit v1.2.3