mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-07 13:53:24 +00:00
Merge branch 'signal-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc
Pull arch signal handling cleanup from Richard Weinberger: "This patch series moves all remaining archs to the get_signal(), signal_setup_done() and sigsp() functions. Currently these archs use open coded variants of the said functions. Further, unused parameters get removed from get_signal_to_deliver(), tracehook_signal_handler() and signal_delivered(). At the end of the day we save around 500 lines of code." * 'signal-cleanup' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/misc: (43 commits) powerpc: Use sigsp() openrisc: Use sigsp() mn10300: Use sigsp() mips: Use sigsp() microblaze: Use sigsp() metag: Use sigsp() m68k: Use sigsp() m32r: Use sigsp() hexagon: Use sigsp() frv: Use sigsp() cris: Use sigsp() c6x: Use sigsp() blackfin: Use sigsp() avr32: Use sigsp() arm64: Use sigsp() arc: Use sigsp() sas_ss_flags: Remove nested ternary if Rip out get_signal_to_deliver() Clean up signal_delivered() tracehook_signal_handler: Remove sig, info, ka and regs ...
This commit is contained in:
commit
63b12bdb0d
@ -141,17 +141,13 @@ SYSCALL_DEFINE0(rt_sigreturn)
|
||||
/*
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs,
|
||||
unsigned long framesize)
|
||||
{
|
||||
unsigned long sp = regs->sp;
|
||||
unsigned long sp = sigsp(regs->sp, ksig);
|
||||
void __user *frame;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching */
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
|
||||
/* No matter what happens, 'sp' must be word
|
||||
* aligned otherwise nasty things could happen
|
||||
*/
|
||||
@ -179,14 +175,13 @@ static inline int map_sig(int sig)
|
||||
}
|
||||
|
||||
static int
|
||||
setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *sf;
|
||||
unsigned int magic = 0;
|
||||
int err = 0;
|
||||
|
||||
sf = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
|
||||
sf = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
|
||||
if (!sf)
|
||||
return 1;
|
||||
|
||||
@ -205,8 +200,8 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
|
||||
* #2: struct siginfo
|
||||
* #3: struct ucontext (completely populated)
|
||||
*/
|
||||
if (unlikely(ka->sa.sa_flags & SA_SIGINFO)) {
|
||||
err |= copy_siginfo_to_user(&sf->info, info);
|
||||
if (unlikely(ksig->ka.sa.sa_flags & SA_SIGINFO)) {
|
||||
err |= copy_siginfo_to_user(&sf->info, &ksig->info);
|
||||
err |= __put_user(0, &sf->uc.uc_flags);
|
||||
err |= __put_user(NULL, &sf->uc.uc_link);
|
||||
err |= __save_altstack(&sf->uc.uc_stack, regs->sp);
|
||||
@ -227,16 +222,16 @@ setup_rt_frame(int signo, struct k_sigaction *ka, siginfo_t *info,
|
||||
return err;
|
||||
|
||||
/* #1 arg to the user Signal handler */
|
||||
regs->r0 = map_sig(signo);
|
||||
regs->r0 = map_sig(ksig->sig);
|
||||
|
||||
/* setup PC of user space signal handler */
|
||||
regs->ret = (unsigned long)ka->sa.sa_handler;
|
||||
regs->ret = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
|
||||
/*
|
||||
* handler returns using sigreturn stub provided already by userpsace
|
||||
*/
|
||||
BUG_ON(!(ka->sa.sa_flags & SA_RESTORER));
|
||||
regs->blink = (unsigned long)ka->sa.sa_restorer;
|
||||
BUG_ON(!(ksig->ka.sa.sa_flags & SA_RESTORER));
|
||||
regs->blink = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
|
||||
/* User Stack for signal handler will be above the frame just carved */
|
||||
regs->sp = (unsigned long)sf;
|
||||
@ -298,38 +293,30 @@ static void arc_restart_syscall(struct k_sigaction *ka, struct pt_regs *regs)
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void
|
||||
handle_signal(unsigned long sig, 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 ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret)
|
||||
force_sigsegv(sig, current);
|
||||
else
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
int restart_scall;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
restart_scall = in_syscall(regs) && syscall_restartable(regs);
|
||||
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
if (restart_scall) {
|
||||
arc_restart_syscall(&ka, regs);
|
||||
arc_restart_syscall(&ksig.ka, regs);
|
||||
syscall_wont_restart(regs); /* No more restarts */
|
||||
}
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -24,22 +24,21 @@
|
||||
|
||||
extern const compat_ulong_t aarch32_sigret_code[6];
|
||||
|
||||
int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
|
||||
int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs);
|
||||
int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs);
|
||||
int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs);
|
||||
|
||||
void compat_setup_restart_syscall(struct pt_regs *regs);
|
||||
#else
|
||||
|
||||
static inline int compat_setup_frame(int usid, struct k_sigaction *ka,
|
||||
static inline int compat_setup_frame(int usid, struct ksignal *ksig,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
static inline int compat_setup_rt_frame(int usig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *set,
|
||||
static inline int compat_setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return -ENOSYS;
|
||||
|
@ -209,19 +209,13 @@ static int setup_sigframe(struct rt_sigframe __user *sf,
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct rt_sigframe __user *get_sigframe(struct k_sigaction *ka,
|
||||
static struct rt_sigframe __user *get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long sp, sp_top;
|
||||
struct rt_sigframe __user *frame;
|
||||
|
||||
sp = sp_top = regs->sp;
|
||||
|
||||
/*
|
||||
* This is the X/Open sanctioned signal stack switching.
|
||||
*/
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
|
||||
sp = sp_top = current->sas_ss_sp + current->sas_ss_size;
|
||||
sp = sp_top = sigsp(regs->sp, ksig);
|
||||
|
||||
sp = (sp - sizeof(struct rt_sigframe)) & ~15;
|
||||
frame = (struct rt_sigframe __user *)sp;
|
||||
@ -253,13 +247,13 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
||||
regs->regs[30] = (unsigned long)sigtramp;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs);
|
||||
frame = get_sigframe(ksig, regs);
|
||||
if (!frame)
|
||||
return 1;
|
||||
|
||||
@ -269,9 +263,9 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
|
||||
err |= setup_sigframe(frame, regs, set);
|
||||
if (err == 0) {
|
||||
setup_return(regs, ka, frame, usig);
|
||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
setup_return(regs, &ksig->ka, frame, usig);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
regs->regs[1] = (unsigned long)&frame->info;
|
||||
regs->regs[2] = (unsigned long)&frame->uc;
|
||||
}
|
||||
@ -291,13 +285,12 @@ static void setup_restart_syscall(struct pt_regs *regs)
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, struct pt_regs *regs)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
struct task_struct *tsk = current;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int usig = sig;
|
||||
int usig = ksig->sig;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -310,13 +303,12 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
* Set up the stack frame
|
||||
*/
|
||||
if (is_compat_task()) {
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = compat_setup_rt_frame(usig, ka, info, oldset,
|
||||
regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = compat_setup_rt_frame(usig, ksig, oldset, regs);
|
||||
else
|
||||
ret = compat_setup_frame(usig, ka, oldset, regs);
|
||||
ret = compat_setup_frame(usig, ksig, oldset, regs);
|
||||
} else {
|
||||
ret = setup_rt_frame(usig, ka, info, oldset, regs);
|
||||
ret = setup_rt_frame(usig, ksig, oldset, regs);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -324,18 +316,14 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
*/
|
||||
ret |= !valid_user_regs(®s->user_regs);
|
||||
|
||||
if (ret != 0) {
|
||||
force_sigsegv(sig, tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fast forward the stepping logic so we step into the signal
|
||||
* handler.
|
||||
*/
|
||||
user_fastforward_single_step(tsk);
|
||||
if (!ret)
|
||||
user_fastforward_single_step(tsk);
|
||||
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -350,10 +338,9 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
unsigned long continue_addr = 0, restart_addr = 0;
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr, retval = 0;
|
||||
int retval = 0;
|
||||
int syscall = (int)regs->syscallno;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* If we were from a system call, check for system call restarting...
|
||||
@ -387,8 +374,7 @@ static void do_signal(struct pt_regs *regs)
|
||||
* Get the signal to deliver. When running under ptrace, at this point
|
||||
* the debugger may change all of our registers.
|
||||
*/
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/*
|
||||
* Depending on the signal settings, we may need to revert the
|
||||
* decision to restart the system call, but skip this if a
|
||||
@ -398,12 +384,12 @@ static void do_signal(struct pt_regs *regs)
|
||||
(retval == -ERESTARTNOHAND ||
|
||||
retval == -ERESTART_RESTARTBLOCK ||
|
||||
(retval == -ERESTARTSYS &&
|
||||
!(ka.sa.sa_flags & SA_RESTART)))) {
|
||||
!(ksig.ka.sa.sa_flags & SA_RESTART)))) {
|
||||
regs->regs[0] = -EINTR;
|
||||
regs->pc = continue_addr;
|
||||
}
|
||||
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -407,19 +407,13 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __user *compat_get_sigframe(struct k_sigaction *ka,
|
||||
static void __user *compat_get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs,
|
||||
int framesize)
|
||||
{
|
||||
compat_ulong_t sp = regs->compat_sp;
|
||||
compat_ulong_t sp = sigsp(regs->compat_sp, ksig);
|
||||
void __user *frame;
|
||||
|
||||
/*
|
||||
* This is the X/Open sanctioned signal stack switching.
|
||||
*/
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
|
||||
/*
|
||||
* ATPCS B01 mandates 8-byte alignment
|
||||
*/
|
||||
@ -520,18 +514,18 @@ static int compat_setup_sigframe(struct compat_sigframe __user *sf,
|
||||
/*
|
||||
* 32-bit signal handling routines called from signal.c
|
||||
*/
|
||||
int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
int compat_setup_rt_frame(int usig, struct ksignal *ksig,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct compat_rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = compat_get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!frame)
|
||||
return 1;
|
||||
|
||||
err |= copy_siginfo_to_user32(&frame->info, info);
|
||||
err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
|
||||
|
||||
__put_user_error(0, &frame->sig.uc.uc_flags, err);
|
||||
__put_user_error(0, &frame->sig.uc.uc_link, err);
|
||||
@ -541,7 +535,7 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= compat_setup_sigframe(&frame->sig, regs, set);
|
||||
|
||||
if (err == 0) {
|
||||
compat_setup_return(regs, ka, frame->sig.retcode, frame, usig);
|
||||
compat_setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
|
||||
regs->regs[1] = (compat_ulong_t)(unsigned long)&frame->info;
|
||||
regs->regs[2] = (compat_ulong_t)(unsigned long)&frame->sig.uc;
|
||||
}
|
||||
@ -549,13 +543,13 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
return err;
|
||||
}
|
||||
|
||||
int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
|
||||
int compat_setup_frame(int usig, struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct compat_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = compat_get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = compat_get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!frame)
|
||||
return 1;
|
||||
@ -564,7 +558,7 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
|
||||
|
||||
err |= compat_setup_sigframe(frame, regs, set);
|
||||
if (err == 0)
|
||||
compat_setup_return(regs, ka, frame->retcode, frame, usig);
|
||||
compat_setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -127,24 +127,20 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, int framesize)
|
||||
get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize)
|
||||
{
|
||||
unsigned long sp = regs->sp;
|
||||
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
unsigned long sp = sigsp(regs->sp, ksig);
|
||||
|
||||
return (void __user *)((sp - framesize) & ~3);
|
||||
}
|
||||
|
||||
static int
|
||||
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
err = -EFAULT;
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
goto out;
|
||||
@ -164,7 +160,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20),
|
||||
&frame->retcode);
|
||||
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Set up the ucontext */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -176,12 +172,12 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
regs->r12 = sig;
|
||||
regs->r12 = ksig->sig;
|
||||
regs->r11 = (unsigned long) &frame->info;
|
||||
regs->r10 = (unsigned long) &frame->uc;
|
||||
regs->sp = (unsigned long) frame;
|
||||
if (ka->sa.sa_flags & SA_RESTORER)
|
||||
regs->lr = (unsigned long)ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
else {
|
||||
printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n",
|
||||
current->comm, current->pid);
|
||||
@ -189,10 +185,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n",
|
||||
current->comm, current->pid, sig, regs->sp,
|
||||
regs->pc, ka->sa.sa_handler, regs->lr);
|
||||
current->comm, current->pid, ksig->sig, regs->sp,
|
||||
regs->pc, ksig->ka.sa.sa_handler, regs->lr);
|
||||
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
|
||||
out:
|
||||
return err;
|
||||
@ -208,15 +204,14 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
|
||||
}
|
||||
|
||||
static inline void
|
||||
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
struct pt_regs *regs, int syscall)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Set up the stack frame
|
||||
*/
|
||||
ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
|
||||
ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
|
||||
|
||||
/*
|
||||
* Check that the resulting registers are sane
|
||||
@ -226,10 +221,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
/*
|
||||
* Block the signal if we were successful.
|
||||
*/
|
||||
if (ret != 0)
|
||||
force_sigsegv(sig, current);
|
||||
else
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -239,9 +231,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, int syscall)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which is why we may in
|
||||
@ -251,18 +241,18 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
get_signal(&ksig);
|
||||
if (syscall) {
|
||||
switch (regs->r12) {
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
case -ERESTARTNOHAND:
|
||||
if (signr > 0) {
|
||||
if (ksig.sig > 0) {
|
||||
regs->r12 = -EINTR;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case -ERESTARTSYS:
|
||||
if (signr > 0 && !(ka.sa.sa_flags & SA_RESTART)) {
|
||||
if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->r12 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -272,13 +262,13 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
}
|
||||
}
|
||||
|
||||
if (signr == 0) {
|
||||
if (!ksig.sig) {
|
||||
/* No signal to deliver -- put the saved sigmask back */
|
||||
restore_saved_sigmask();
|
||||
return;
|
||||
}
|
||||
|
||||
handle_signal(signr, &ka, &info, regs, syscall);
|
||||
handle_signal(&ksig, regs, syscall);
|
||||
}
|
||||
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
|
||||
|
@ -135,40 +135,31 @@ static inline int rt_setup_sigcontext(struct sigcontext *sc, struct pt_regs *reg
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
static inline void *get_sigframe(struct ksignal *ksig,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long usp;
|
||||
unsigned long usp = sigsp(rdusp(), ksig);
|
||||
|
||||
/* Default to using normal stack. */
|
||||
usp = rdusp();
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (!on_sig_stack(usp))
|
||||
usp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
return (void *)((usp - frame_size) & -8UL);
|
||||
}
|
||||
|
||||
static int
|
||||
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
|
||||
sigset_t * set, struct pt_regs *regs)
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
err |= __put_user((current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
&& sig < 32
|
||||
&& ksig->sig < 32
|
||||
? current_thread_info()->exec_domain->
|
||||
signal_invmap[sig] : sig), &frame->sig);
|
||||
signal_invmap[ksig->sig] : ksig->sig), &frame->sig);
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -183,7 +174,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
|
||||
/* Set up registers for signal handler */
|
||||
if (current->personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor *) ka->sa.sa_handler;
|
||||
(struct fdpic_func_descriptor *) ksig->ka.sa.sa_handler;
|
||||
u32 pc, p3;
|
||||
err |= __get_user(pc, &funcptr->text);
|
||||
err |= __get_user(p3, &funcptr->GOT);
|
||||
@ -192,7 +183,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
|
||||
regs->pc = pc;
|
||||
regs->p3 = p3;
|
||||
} else
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
wrusp((unsigned long)frame);
|
||||
regs->rets = SIGRETURN_STUB;
|
||||
|
||||
@ -237,20 +228,19 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void
|
||||
handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* are we from a system call? to see pt_regs->orig_p0 */
|
||||
if (regs->orig_p0 >= 0)
|
||||
/* If so, check system call restarting.. */
|
||||
handle_restart(regs, ka, 1);
|
||||
handle_restart(regs, &ksig->ka, 1);
|
||||
|
||||
/* set up the stack frame */
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
|
||||
force_sigsegv(sig, current);
|
||||
else
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
|
||||
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -264,16 +254,13 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
*/
|
||||
asmlinkage void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
current->thread.esp0 = (unsigned long)regs;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -127,17 +127,11 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs,
|
||||
unsigned long framesize)
|
||||
{
|
||||
unsigned long sp = regs->sp;
|
||||
|
||||
/*
|
||||
* This is the X/Open sanctioned signal stack switching.
|
||||
*/
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(sp) == 0)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
unsigned long sp = sigsp(regs->sp, ksig);
|
||||
|
||||
/*
|
||||
* No matter what happens, 'sp' must be dword
|
||||
@ -146,21 +140,21 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
return (void __user *)((sp - framesize) & ~7);
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
unsigned long __user *retcode;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto segv_and_exit;
|
||||
return -EFAULT;
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Clear all the bits of the ucontext we don't use. */
|
||||
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
|
||||
@ -188,7 +182,7 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
#undef COPY
|
||||
|
||||
if (err)
|
||||
goto segv_and_exit;
|
||||
return -EFAULT;
|
||||
|
||||
flush_icache_range((unsigned long) &frame->retcode,
|
||||
(unsigned long) &frame->retcode + RETCODE_SIZE);
|
||||
@ -198,10 +192,10 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
/* Change user context to branch to signal handler */
|
||||
regs->sp = (unsigned long) frame - 8;
|
||||
regs->b3 = (unsigned long) retcode;
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
/* Give the signal number to the handler */
|
||||
regs->a4 = signr;
|
||||
regs->a4 = ksig->sig;
|
||||
|
||||
/*
|
||||
* For realtime signals we must also set the second and third
|
||||
@ -212,10 +206,6 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->a6 = (unsigned long)&frame->uc;
|
||||
|
||||
return 0;
|
||||
|
||||
segv_and_exit:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -245,10 +235,11 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
|
||||
/*
|
||||
* handle the actual delivery of a signal to userspace
|
||||
*/
|
||||
static void handle_signal(int sig,
|
||||
siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int syscall)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
|
||||
int syscall)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
if (syscall) {
|
||||
/* If so, check system call restarting.. */
|
||||
@ -259,7 +250,7 @@ static void handle_signal(int sig,
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->a4 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -272,9 +263,8 @@ static void handle_signal(int sig,
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -282,18 +272,15 @@ static void handle_signal(int sig,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, int syscall)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
/* we want the common case to go fast, which is why we may in certain
|
||||
* cases get here from kernel mode */
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
handle_signal(signr, &info, &ka, regs, syscall);
|
||||
if (get_signal(&ksig)) {
|
||||
handle_signal(&ksig, regs, syscall);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -203,15 +203,9 @@ static int setup_sigcontext(struct sigcontext __user *sc,
|
||||
* - usually on the stack. */
|
||||
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
||||
get_sigframe(struct ksignal *ksig, size_t frame_size)
|
||||
{
|
||||
unsigned long sp = rdusp();
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (! on_sig_stack(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
unsigned long sp = sigsp(rdusp(), ksig);
|
||||
|
||||
/* make sure the frame is dword-aligned */
|
||||
|
||||
@ -228,33 +222,33 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
||||
* user-mode trampoline.
|
||||
*/
|
||||
|
||||
static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
unsigned long return_ip;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (_NSIG_WORDS > 1) {
|
||||
err |= __copy_to_user(frame->extramask, &set->sig[1],
|
||||
sizeof(frame->extramask));
|
||||
}
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long)ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
} else {
|
||||
/* trampoline - the desired return ip is the retcode itself */
|
||||
return_ip = (unsigned long)&frame->retcode;
|
||||
@ -265,42 +259,38 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
|
||||
regs->irp = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */
|
||||
regs->irp = (unsigned long) ksig->ka.sa.sa_handler; /* what we enter NOW */
|
||||
regs->srp = return_ip; /* what we enter LATER */
|
||||
regs->r10 = sig; /* first argument is signo */
|
||||
regs->r10 = ksig->sig; /* first argument is signo */
|
||||
|
||||
/* actually move the usp to reflect the stacked frame */
|
||||
|
||||
wrusp((unsigned long)frame);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
unsigned long return_ip;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Clear all the bits of the ucontext we don't use. */
|
||||
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
|
||||
@ -312,12 +302,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= __save_altstack(&frame->uc.uc_stack, rdusp());
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long)ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
} else {
|
||||
/* trampoline - the desired return ip is the retcode itself */
|
||||
return_ip = (unsigned long)&frame->retcode;
|
||||
@ -329,18 +319,18 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* TODO what is the current->exec_domain stuff and invmap ? */
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
|
||||
/* What we enter NOW */
|
||||
regs->irp = (unsigned long) ka->sa.sa_handler;
|
||||
regs->irp = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
/* What we enter LATER */
|
||||
regs->srp = return_ip;
|
||||
/* First argument is signo */
|
||||
regs->r10 = sig;
|
||||
regs->r10 = ksig->sig;
|
||||
/* Second argument is (siginfo_t *) */
|
||||
regs->r11 = (unsigned long)&frame->info;
|
||||
/* Third argument is unused */
|
||||
@ -350,19 +340,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
wrusp((unsigned long)frame);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
|
||||
static inline void handle_signal(int canrestart, unsigned long sig,
|
||||
siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
static inline void handle_signal(int canrestart, struct ksignal *ksig,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
@ -383,7 +368,7 @@ static inline void handle_signal(int canrestart, unsigned long sig,
|
||||
/* ERESTARTSYS means to restart the syscall if
|
||||
* there is no handler or the handler was
|
||||
* registered with SA_RESTART */
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->r10 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -396,13 +381,12 @@ static inline void handle_signal(int canrestart, unsigned long sig,
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret == 0)
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -419,9 +403,7 @@ static inline void handle_signal(int canrestart, unsigned long sig,
|
||||
|
||||
void do_signal(int canrestart, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -432,10 +414,9 @@ void do_signal(int canrestart, struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(canrestart, signr, &info, &ka, regs);
|
||||
handle_signal(canrestart, &ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -189,17 +189,9 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
|
||||
/* Figure out where to put the new signal frame - usually on the stack. */
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
|
||||
get_sigframe(struct ksignal *ksig, size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
||||
sp = rdusp();
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (!on_sig_stack(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
unsigned long sp = sigsp(rdusp(), ksig);
|
||||
|
||||
/* Make sure the frame is dword-aligned. */
|
||||
sp &= ~3;
|
||||
@ -215,23 +207,22 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
|
||||
* trampoline.
|
||||
*/
|
||||
static int
|
||||
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
struct pt_regs * regs)
|
||||
setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
unsigned long return_ip;
|
||||
struct signal_frame __user *frame;
|
||||
|
||||
err = 0;
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
err |= setup_sigcontext(&frame->sc, regs, set->sig[0]);
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (_NSIG_WORDS > 1) {
|
||||
err |= __copy_to_user(frame->extramask, &set->sig[1],
|
||||
@ -239,14 +230,14 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Set up to return from user-space. If provided, use a stub
|
||||
* already located in user-space.
|
||||
*/
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long)ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
} else {
|
||||
/* Trampoline - the desired return ip is in the signal return page. */
|
||||
return_ip = cris_signal_return_page;
|
||||
@ -264,7 +255,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Set up registers for signal handler.
|
||||
@ -273,42 +264,37 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
* Where the code enter later.
|
||||
* First argument, signo.
|
||||
*/
|
||||
regs->erp = (unsigned long) ka->sa.sa_handler;
|
||||
regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->srp = return_ip;
|
||||
regs->r10 = sig;
|
||||
regs->r10 = ksig->sig;
|
||||
|
||||
/* Actually move the USP to reflect the stacked frame. */
|
||||
wrusp((unsigned long)frame);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs * regs)
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
int err;
|
||||
unsigned long return_ip;
|
||||
struct rt_signal_frame __user *frame;
|
||||
|
||||
err = 0;
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* TODO: what is the current->exec_domain stuff and invmap ? */
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Clear all the bits of the ucontext we don't use. */
|
||||
err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
|
||||
@ -317,14 +303,14 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= __save_altstack(&frame->uc.uc_stack, rdusp());
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Set up to return from user-space. If provided, use a stub
|
||||
* already located in user-space.
|
||||
*/
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long) ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
return_ip = (unsigned long) ksig->ka.sa.sa_restorer;
|
||||
} else {
|
||||
/* Trampoline - the desired return ip is in the signal return page. */
|
||||
return_ip = cris_signal_return_page + 6;
|
||||
@ -345,7 +331,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Set up registers for signal handler.
|
||||
@ -356,9 +342,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
* Second argument is (siginfo_t *).
|
||||
* Third argument is unused.
|
||||
*/
|
||||
regs->erp = (unsigned long) ka->sa.sa_handler;
|
||||
regs->erp = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->srp = return_ip;
|
||||
regs->r10 = sig;
|
||||
regs->r10 = ksig->sig;
|
||||
regs->r11 = (unsigned long) &frame->info;
|
||||
regs->r12 = 0;
|
||||
|
||||
@ -366,17 +352,11 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
wrusp((unsigned long)frame);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Invoke a signal handler to, well, handle the signal. */
|
||||
static inline void
|
||||
handle_signal(int canrestart, unsigned long sig,
|
||||
siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs * regs)
|
||||
handle_signal(int canrestart, struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
@ -404,7 +384,7 @@ handle_signal(int canrestart, unsigned long sig,
|
||||
* there is no handler, or the handler
|
||||
* was registered with SA_RESTART.
|
||||
*/
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->r10 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -423,13 +403,12 @@ handle_signal(int canrestart, unsigned long sig,
|
||||
}
|
||||
|
||||
/* Set up the stack frame. */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret == 0)
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -446,9 +425,7 @@ handle_signal(int canrestart, unsigned long sig,
|
||||
void
|
||||
do_signal(int canrestart, struct pt_regs *regs)
|
||||
{
|
||||
int signr;
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* The common case should go fast, which is why this point is
|
||||
@ -458,11 +435,9 @@ do_signal(int canrestart, struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(canrestart, signr, &info, &ka, regs);
|
||||
handle_signal(canrestart, &ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -158,19 +158,10 @@ static int setup_sigcontext(struct sigcontext __user *sc, unsigned long mask)
|
||||
/*
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
||||
/* Default to using normal stack */
|
||||
sp = __frame->sp;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (! sas_ss_flags(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
unsigned long sp = sigsp(__frame->sp, ksig);
|
||||
|
||||
return (void __user *) ((sp - frame_size) & ~7UL);
|
||||
|
||||
@ -180,17 +171,17 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int rsig;
|
||||
int rsig, sig = ksig->sig;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
frame = get_sigframe(ka, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
rsig = sig;
|
||||
if (sig < 32 &&
|
||||
@ -199,22 +190,22 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
rsig = __current_thread_info->exec_domain->signal_invmap[sig];
|
||||
|
||||
if (__put_user(rsig, &frame->sig) < 0)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (setup_sigcontext(&frame->sc, set->sig[0]))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (_NSIG_WORDS > 1) {
|
||||
if (__copy_to_user(frame->extramask, &set->sig[1],
|
||||
sizeof(frame->extramask)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
* already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ka->sa.sa_restorer, &frame->pretcode) < 0)
|
||||
goto give_sigsegv;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode) < 0)
|
||||
return -EFAULT;
|
||||
}
|
||||
else {
|
||||
/* Set up the following code on the stack:
|
||||
@ -224,7 +215,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
|
||||
__put_user(0x8efc0000|__NR_sigreturn, &frame->retcode[0]) ||
|
||||
__put_user(0xc0700000, &frame->retcode[1]))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
flush_icache_range((unsigned long) frame->retcode,
|
||||
(unsigned long) (frame->retcode + 2));
|
||||
@ -233,14 +224,14 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
/* Set up registers for the signal handler */
|
||||
if (current->personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
|
||||
(struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
|
||||
struct fdpic_func_descriptor desc;
|
||||
if (copy_from_user(&desc, funcptr, sizeof(desc)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
__frame->pc = desc.text;
|
||||
__frame->gr15 = desc.GOT;
|
||||
} else {
|
||||
__frame->pc = (unsigned long) ka->sa.sa_handler;
|
||||
__frame->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
__frame->gr15 = 0;
|
||||
}
|
||||
|
||||
@ -255,29 +246,23 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set)
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
|
||||
} /* end setup_frame() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int rsig;
|
||||
int rsig, sig = ksig->sig;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
frame = get_sigframe(ka, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
rsig = sig;
|
||||
if (sig < 32 &&
|
||||
@ -288,28 +273,28 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (__put_user(rsig, &frame->sig) ||
|
||||
__put_user(&frame->info, &frame->pinfo) ||
|
||||
__put_user(&frame->uc, &frame->puc))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_siginfo_to_user(&frame->info, info))
|
||||
goto give_sigsegv;
|
||||
if (copy_siginfo_to_user(&frame->info, &ksig->info))
|
||||
return -EFAULT;
|
||||
|
||||
/* Create the ucontext. */
|
||||
if (__put_user(0, &frame->uc.uc_flags) ||
|
||||
__put_user(NULL, &frame->uc.uc_link) ||
|
||||
__save_altstack(&frame->uc.uc_stack, __frame->sp))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (setup_sigcontext(&frame->uc.uc_mcontext, set->sig[0]))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
* already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
|
||||
goto give_sigsegv;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
|
||||
return -EFAULT;
|
||||
}
|
||||
else {
|
||||
/* Set up the following code on the stack:
|
||||
@ -319,7 +304,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (__put_user((__sigrestore_t)frame->retcode, &frame->pretcode) ||
|
||||
__put_user(0x8efc0000|__NR_rt_sigreturn, &frame->retcode[0]) ||
|
||||
__put_user(0xc0700000, &frame->retcode[1]))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
flush_icache_range((unsigned long) frame->retcode,
|
||||
(unsigned long) (frame->retcode + 2));
|
||||
@ -328,14 +313,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
/* Set up registers for signal handler */
|
||||
if (current->personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor __user *) ka->sa.sa_handler;
|
||||
(struct fdpic_func_descriptor __user *) ksig->ka.sa.sa_handler;
|
||||
struct fdpic_func_descriptor desc;
|
||||
if (copy_from_user(&desc, funcptr, sizeof(desc)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
__frame->pc = desc.text;
|
||||
__frame->gr15 = desc.GOT;
|
||||
} else {
|
||||
__frame->pc = (unsigned long) ka->sa.sa_handler;
|
||||
__frame->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
__frame->gr15 = 0;
|
||||
}
|
||||
|
||||
@ -349,21 +334,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sig, current->comm, current->pid, frame, __frame->pc,
|
||||
frame->pretcode);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
|
||||
} /* end setup_rt_frame() */
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka)
|
||||
static void handle_signal(struct ksignal *ksig)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
@ -378,7 +357,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
__frame->gr8 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -392,16 +371,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset);
|
||||
ret = setup_frame(ksig, oldset);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, __frame,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
} /* end handle_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -412,13 +387,10 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
*/
|
||||
static void do_signal(void)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
|
||||
if (signr > 0) {
|
||||
handle_signal(signr, &info, &ka);
|
||||
if (get_signal(&ksig)) {
|
||||
handle_signal(&ksig);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -36,18 +36,10 @@ struct rt_sigframe {
|
||||
struct ucontext uc;
|
||||
};
|
||||
|
||||
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp = regs->r29;
|
||||
|
||||
/* check if we would overflow the alt stack */
|
||||
if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
|
||||
return (void __user __force *)-1UL;
|
||||
|
||||
/* Switch to signal stack if appropriate */
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
unsigned long sp = sigsp(regs->r29, ksig);
|
||||
|
||||
return (void __user *)((sp - frame_size) & ~(sizeof(long long) - 1));
|
||||
}
|
||||
@ -112,20 +104,20 @@ static int restore_sigcontext(struct pt_regs *regs,
|
||||
/*
|
||||
* Setup signal stack frame with siginfo structure
|
||||
*/
|
||||
static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
struct rt_sigframe __user *frame;
|
||||
struct hexagon_vdso *vdso = current->mm->context.vdso;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(struct rt_sigframe));
|
||||
frame = get_sigframe(ksig, regs, sizeof(struct rt_sigframe));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(struct rt_sigframe)))
|
||||
goto sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_siginfo_to_user(&frame->info, info))
|
||||
goto sigsegv;
|
||||
if (copy_siginfo_to_user(&frame->info, &ksig->info))
|
||||
return -EFAULT;
|
||||
|
||||
/* The on-stack signal trampoline is no longer executed;
|
||||
* however, the libgcc signal frame unwinding code checks for
|
||||
@ -137,29 +129,26 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
err |= __save_altstack(&frame->uc.uc_stack, user_stack_pointer(regs));
|
||||
if (err)
|
||||
goto sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Load r0/r1 pair with signumber/siginfo pointer... */
|
||||
regs->r0100 = ((unsigned long long)((unsigned long)&frame->info) << 32)
|
||||
| (unsigned long long)signr;
|
||||
| (unsigned long long)ksig->sig;
|
||||
regs->r02 = (unsigned long) &frame->uc;
|
||||
regs->r31 = (unsigned long) vdso->rt_signal_trampoline;
|
||||
pt_psp(regs) = (unsigned long) frame;
|
||||
pt_set_elr(regs, (unsigned long)ka->sa.sa_handler);
|
||||
pt_set_elr(regs, (unsigned long)ksig->ka.sa.sa_handler);
|
||||
|
||||
return 0;
|
||||
|
||||
sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup invocation of signal handler
|
||||
*/
|
||||
static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* If we're handling a signal that aborted a system call,
|
||||
* set up the error return value before adding the signal
|
||||
@ -173,7 +162,7 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
regs->r00 = -EINTR;
|
||||
break;
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->r00 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -193,11 +182,9 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
* only set up the rt_frame flavor.
|
||||
*/
|
||||
/* If there was an error on setup, no signal was delivered. */
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
|
||||
return;
|
||||
ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
|
||||
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -205,17 +192,13 @@ static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
*/
|
||||
void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction sigact;
|
||||
siginfo_t info;
|
||||
int signo;
|
||||
struct ksignal ksig;
|
||||
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
|
||||
|
||||
if (signo > 0) {
|
||||
handle_signal(signo, &info, &sigact, regs);
|
||||
if (get_signal(&ksig)) {
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -309,12 +309,11 @@ force_sigsegv_info (int sig, void __user *addr)
|
||||
si.si_uid = from_kuid_munged(current_user_ns(), current_uid());
|
||||
si.si_addr = addr;
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static long
|
||||
setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
||||
struct sigscratch *scr)
|
||||
setup_frame(struct ksignal *ksig, sigset_t *set, struct sigscratch *scr)
|
||||
{
|
||||
extern char __kernel_sigtramp[];
|
||||
unsigned long tramp_addr, new_rbs = 0, new_sp;
|
||||
@ -323,7 +322,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
||||
|
||||
new_sp = scr->pt.r12;
|
||||
tramp_addr = (unsigned long) __kernel_sigtramp;
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (ksig->ka.sa.sa_flags & SA_ONSTACK) {
|
||||
int onstack = sas_ss_flags(new_sp);
|
||||
|
||||
if (onstack == 0) {
|
||||
@ -347,29 +346,29 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
||||
*/
|
||||
check_sp = (new_sp - sizeof(*frame)) & -STACK_ALIGN;
|
||||
if (!likely(on_sig_stack(check_sp)))
|
||||
return force_sigsegv_info(sig, (void __user *)
|
||||
return force_sigsegv_info(ksig->sig, (void __user *)
|
||||
check_sp);
|
||||
}
|
||||
}
|
||||
frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return force_sigsegv_info(sig, frame);
|
||||
return force_sigsegv_info(ksig->sig, frame);
|
||||
|
||||
err = __put_user(sig, &frame->arg0);
|
||||
err = __put_user(ksig->sig, &frame->arg0);
|
||||
err |= __put_user(&frame->info, &frame->arg1);
|
||||
err |= __put_user(&frame->sc, &frame->arg2);
|
||||
err |= __put_user(new_rbs, &frame->sc.sc_rbs_base);
|
||||
err |= __put_user(0, &frame->sc.sc_loadrs); /* initialize to zero */
|
||||
err |= __put_user(ka->sa.sa_handler, &frame->handler);
|
||||
err |= __put_user(ksig->ka.sa.sa_handler, &frame->handler);
|
||||
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
err |= __save_altstack(&frame->sc.sc_stack, scr->pt.r12);
|
||||
err |= setup_sigcontext(&frame->sc, set, scr);
|
||||
|
||||
if (unlikely(err))
|
||||
return force_sigsegv_info(sig, frame);
|
||||
return force_sigsegv_info(ksig->sig, frame);
|
||||
|
||||
scr->pt.r12 = (unsigned long) frame - 16; /* new stack pointer */
|
||||
scr->pt.ar_fpsr = FPSR_DEFAULT; /* reset fpsr for signal handler */
|
||||
@ -394,22 +393,20 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
|
||||
|
||||
#if DEBUG_SIG
|
||||
printk("SIG deliver (%s:%d): sig=%d sp=%lx ip=%lx handler=%p\n",
|
||||
current->comm, current->pid, sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
|
||||
current->comm, current->pid, ksig->sig, scr->pt.r12, frame->sc.sc_ip, frame->handler);
|
||||
#endif
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long
|
||||
handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
struct sigscratch *scr)
|
||||
handle_signal (struct ksignal *ksig, struct sigscratch *scr)
|
||||
{
|
||||
if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
|
||||
return 0;
|
||||
int ret = setup_frame(ksig, sigmask_to_save(), scr);
|
||||
|
||||
signal_delivered(sig, info, ka, &scr->pt,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
if (!ret)
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
|
||||
return 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -419,17 +416,16 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
void
|
||||
ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
long restart = in_syscall;
|
||||
long errno = scr->pt.r8;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* This only loops in the rare cases of handle_signal() failing, in which case we
|
||||
* need to push through a forced SIGSEGV.
|
||||
*/
|
||||
while (1) {
|
||||
int signr = get_signal_to_deliver(&info, &ka, &scr->pt, NULL);
|
||||
get_signal(&ksig);
|
||||
|
||||
/*
|
||||
* get_signal_to_deliver() may have run a debugger (via notify_parent())
|
||||
@ -446,7 +442,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
||||
*/
|
||||
restart = 0;
|
||||
|
||||
if (signr <= 0)
|
||||
if (ksig.sig <= 0)
|
||||
break;
|
||||
|
||||
if (unlikely(restart)) {
|
||||
@ -458,7 +454,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
||||
break;
|
||||
|
||||
case ERESTARTSYS:
|
||||
if ((ka.sa.sa_flags & SA_RESTART) == 0) {
|
||||
if ((ksig.ka.sa.sa_flags & SA_RESTART) == 0) {
|
||||
scr->pt.r8 = EINTR;
|
||||
/* note: scr->pt.r10 is already -1 */
|
||||
break;
|
||||
@ -473,7 +469,7 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
||||
* Whee! Actually deliver the signal. If the delivery failed, we need to
|
||||
* continue to iterate in this loop so we can deliver the SIGSEGV...
|
||||
*/
|
||||
if (handle_signal(signr, &ka, &info, scr))
|
||||
if (handle_signal(&ksig, scr))
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -162,28 +162,22 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
|
||||
get_sigframe(struct ksignal *ksig, unsigned long sp, size_t frame_size)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
|
||||
return (void __user *)((sp - frame_size) & -8ul);
|
||||
return (void __user *)((sigsp(sp, ksig) - frame_size) & -8ul);
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int signal;
|
||||
int signal, sig = ksig->sig;
|
||||
|
||||
frame = get_sigframe(ka, regs->spu, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs->spu, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -193,13 +187,13 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
err |= __put_user(signal, &frame->sig);
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -208,17 +202,17 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. */
|
||||
regs->lr = (unsigned long)ka->sa.sa_restorer;
|
||||
regs->lr = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->spu = (unsigned long)frame;
|
||||
regs->r0 = signal; /* Arg for signal handler */
|
||||
regs->r1 = (unsigned long)&frame->info;
|
||||
regs->r2 = (unsigned long)&frame->uc;
|
||||
regs->bpc = (unsigned long)ka->sa.sa_handler;
|
||||
regs->bpc = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
@ -228,10 +222,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int prev_insn(struct pt_regs *regs)
|
||||
@ -252,9 +242,10 @@ static int prev_insn(struct pt_regs *regs)
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
struct pt_regs *regs)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
if (regs->syscall_nr >= 0) {
|
||||
/* If so, check system call restarting.. */
|
||||
@ -265,7 +256,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->r0 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -278,10 +269,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
|
||||
return;
|
||||
ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
|
||||
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -291,9 +281,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -304,8 +292,7 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Re-enable any watchpoints before delivering the
|
||||
* signal to user space. The processor register will
|
||||
* have been cleared if the watchpoint triggered
|
||||
@ -313,7 +300,7 @@ static void do_signal(struct pt_regs *regs)
|
||||
*/
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -835,38 +835,30 @@ static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *
|
||||
}
|
||||
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
||||
get_sigframe(struct ksignal *ksig, size_t frame_size)
|
||||
{
|
||||
unsigned long usp;
|
||||
unsigned long usp = sigsp(rdusp(), ksig);
|
||||
|
||||
/* Default to using normal stack. */
|
||||
usp = rdusp();
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if (ka->sa.sa_flags & SA_ONSTACK) {
|
||||
if (!sas_ss_flags(usp))
|
||||
usp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
return (void __user *)((usp - frame_size) & -8UL);
|
||||
}
|
||||
|
||||
static int setup_frame (int sig, struct k_sigaction *ka,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int fsize = frame_extra_sizes(regs->format);
|
||||
struct sigcontext context;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
|
||||
if (fsize < 0) {
|
||||
#ifdef DEBUG
|
||||
printk ("setup_frame: Unknown frame format %#x\n",
|
||||
regs->format);
|
||||
#endif
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
|
||||
frame = get_sigframe(ksig, sizeof(*frame) + fsize);
|
||||
|
||||
if (fsize)
|
||||
err |= copy_to_user (frame + 1, regs + 1, fsize);
|
||||
@ -899,7 +891,7 @@ static int setup_frame (int sig, struct k_sigaction *ka,
|
||||
#endif
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
push_cache ((unsigned long) &frame->retcode);
|
||||
|
||||
@ -908,7 +900,7 @@ static int setup_frame (int sig, struct k_sigaction *ka,
|
||||
* to destroy is successfully copied to sigframe.
|
||||
*/
|
||||
wrusp ((unsigned long) frame);
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
adjustformat(regs);
|
||||
|
||||
/*
|
||||
@ -934,28 +926,24 @@ static int setup_frame (int sig, struct k_sigaction *ka,
|
||||
tregs->sr = regs->sr;
|
||||
}
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int fsize = frame_extra_sizes(regs->format);
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
|
||||
if (fsize < 0) {
|
||||
#ifdef DEBUG
|
||||
printk ("setup_frame: Unknown frame format %#x\n",
|
||||
regs->format);
|
||||
#endif
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, sizeof(*frame));
|
||||
|
||||
if (fsize)
|
||||
err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
|
||||
@ -968,7 +956,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
&frame->sig);
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -996,7 +984,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
#endif /* CONFIG_MMU */
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
push_cache ((unsigned long) &frame->retcode);
|
||||
|
||||
@ -1005,7 +993,7 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
* to destroy is successfully copied to sigframe.
|
||||
*/
|
||||
wrusp ((unsigned long) frame);
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
adjustformat(regs);
|
||||
|
||||
/*
|
||||
@ -1031,10 +1019,6 @@ static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
tregs->sr = regs->sr;
|
||||
}
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -1074,26 +1058,22 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void
|
||||
handle_signal(int sig, 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;
|
||||
/* are we from a system call? */
|
||||
if (regs->orig_d0 >= 0)
|
||||
/* If so, check system call restarting.. */
|
||||
handle_restart(regs, ka, 1);
|
||||
handle_restart(regs, &ksig->ka, 1);
|
||||
|
||||
/* set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
err = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
err = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
err = setup_frame(sig, ka, oldset, regs);
|
||||
err = setup_frame(ksig, oldset, regs);
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(err, ksig, 0);
|
||||
|
||||
if (test_thread_flag(TIF_DELAYED_TRACE)) {
|
||||
regs->sr &= ~0x8000;
|
||||
@ -1108,16 +1088,13 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
current->thread.esp0 = (unsigned long) regs;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -140,13 +140,9 @@ static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
/*
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static void __user *get_sigframe(struct k_sigaction *ka, unsigned long sp,
|
||||
size_t frame_size)
|
||||
static void __user *get_sigframe(struct ksignal *ksig, unsigned long sp)
|
||||
{
|
||||
/* Meta stacks grows upwards */
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
|
||||
sp = current->sas_ss_sp;
|
||||
|
||||
sp = sigsp(sp, ksig);
|
||||
sp = (sp + 7) & ~7; /* 8byte align stack */
|
||||
|
||||
return (void __user *)sp;
|
||||
@ -159,7 +155,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
int err;
|
||||
unsigned long code;
|
||||
|
||||
frame = get_sigframe(&ksig->ka, regs->REG_SP, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs->REG_SP);
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return -EFAULT;
|
||||
|
||||
|
@ -145,22 +145,19 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
static inline void __user *
|
||||
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
||||
get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size)
|
||||
{
|
||||
/* Default to using normal stack */
|
||||
unsigned long sp = regs->r1;
|
||||
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
unsigned long sp = sigsp(regs->r1, ksig);
|
||||
|
||||
return (void __user *)((sp - frame_size) & -8UL);
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int signal;
|
||||
unsigned long address = 0;
|
||||
#ifdef CONFIG_MMU
|
||||
@ -168,10 +165,10 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
pte_t *ptep;
|
||||
#endif
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -179,8 +176,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
? current_thread_info()->exec_domain->signal_invmap[sig]
|
||||
: sig;
|
||||
|
||||
if (info)
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -227,7 +224,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
flush_dcache_range(address, address + 8);
|
||||
#endif
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->r1 = (unsigned long) frame;
|
||||
@ -237,7 +234,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
|
||||
regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
|
||||
/* Offset to handle microblaze rtid r14, 0 */
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
@ -247,10 +244,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Handle restarting system calls */
|
||||
@ -283,23 +276,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_signal(unsigned long sig, 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 ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
else
|
||||
ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -313,21 +298,19 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, int in_syscall)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
#ifdef DEBUG_SIG
|
||||
pr_info("do signal: %p %d\n", regs, in_syscall);
|
||||
pr_info("do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
|
||||
regs->r12, current_thread_info()->flags);
|
||||
#endif
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (in_syscall)
|
||||
handle_restart(regs, &ka, 1);
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
handle_restart(regs, &ksig.ka, 1);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -13,13 +13,11 @@
|
||||
#include <asm/siginfo.h>
|
||||
|
||||
struct mips_abi {
|
||||
int (* const setup_frame)(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr,
|
||||
sigset_t *set);
|
||||
int (* const setup_frame)(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set);
|
||||
const unsigned long signal_return_offset;
|
||||
int (* const setup_rt_frame)(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr,
|
||||
sigset_t *set, siginfo_t *info);
|
||||
int (* const setup_rt_frame)(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set);
|
||||
const unsigned long rt_signal_return_offset;
|
||||
const unsigned long restart;
|
||||
};
|
||||
|
@ -22,7 +22,7 @@
|
||||
/*
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
extern void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
extern void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
|
||||
size_t frame_size);
|
||||
/* Check and clear pending FPU exceptions in saved CSR */
|
||||
extern int fpcsr_pending(unsigned int __user *fpcsr);
|
||||
|
@ -280,7 +280,7 @@ int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
|
||||
return err;
|
||||
}
|
||||
|
||||
void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
@ -295,9 +295,7 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
*/
|
||||
sp -= 32;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags (sp) == 0))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
sp = sigsp(sp, ksig);
|
||||
|
||||
return (void __user *)((sp - frame_size) & (ICACHE_REFILLS_WORKAROUND_WAR ? ~(cpu_icache_line_size()-1) : ALMASK));
|
||||
}
|
||||
@ -428,20 +426,20 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRAD_SIGNALS
|
||||
static int setup_frame(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr, sigset_t *set)
|
||||
static int setup_frame(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
err |= setup_sigcontext(regs, &frame->sf_sc);
|
||||
err |= __copy_to_user(&frame->sf_mask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Arguments to signal handler:
|
||||
@ -453,37 +451,32 @@ static int setup_frame(void *sig_return, struct k_sigaction *ka,
|
||||
* $25 and c0_epc point to the signal handler, $29 points to the
|
||||
* struct sigframe.
|
||||
*/
|
||||
regs->regs[ 4] = signr;
|
||||
regs->regs[ 4] = ksig->sig;
|
||||
regs->regs[ 5] = 0;
|
||||
regs->regs[ 6] = (unsigned long) &frame->sf_sc;
|
||||
regs->regs[29] = (unsigned long) frame;
|
||||
regs->regs[31] = (unsigned long) sig_return;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr, sigset_t *set,
|
||||
siginfo_t *info)
|
||||
static int setup_rt_frame(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Create siginfo. */
|
||||
err |= copy_siginfo_to_user(&frame->rs_info, info);
|
||||
err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
@ -493,7 +486,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
|
||||
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Arguments to signal handler:
|
||||
@ -505,22 +498,18 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
|
||||
* $25 and c0_epc point to the signal handler, $29 points to
|
||||
* the struct rt_sigframe.
|
||||
*/
|
||||
regs->regs[ 4] = signr;
|
||||
regs->regs[ 4] = ksig->sig;
|
||||
regs->regs[ 5] = (unsigned long) &frame->rs_info;
|
||||
regs->regs[ 6] = (unsigned long) &frame->rs_uc;
|
||||
regs->regs[29] = (unsigned long) frame;
|
||||
regs->regs[31] = (unsigned long) sig_return;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
struct mips_abi mips_abi = {
|
||||
@ -534,8 +523,7 @@ struct mips_abi mips_abi = {
|
||||
.restart = __NR_restart_syscall
|
||||
};
|
||||
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, struct pt_regs *regs)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
@ -557,7 +545,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
regs->regs[2] = EINTR;
|
||||
break;
|
||||
case ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->regs[2] = EINTR;
|
||||
break;
|
||||
}
|
||||
@ -571,29 +559,23 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
regs->regs[0] = 0; /* Don't deal with this again. */
|
||||
}
|
||||
|
||||
if (sig_uses_siginfo(ka))
|
||||
if (sig_uses_siginfo(&ksig->ka))
|
||||
ret = abi->setup_rt_frame(vdso + abi->rt_signal_return_offset,
|
||||
ka, regs, sig, oldset, info);
|
||||
ksig, regs, oldset);
|
||||
else
|
||||
ret = abi->setup_frame(vdso + abi->signal_return_offset,
|
||||
ka, regs, sig, oldset);
|
||||
ret = abi->setup_frame(vdso + abi->signal_return_offset, ksig,
|
||||
regs, oldset);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -490,21 +490,21 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
force_sig(SIGSEGV, current);
|
||||
}
|
||||
|
||||
static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr, sigset_t *set)
|
||||
static int setup_frame_32(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set)
|
||||
{
|
||||
struct sigframe32 __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
err |= setup_sigcontext32(regs, &frame->sf_sc);
|
||||
err |= __copy_conv_sigset_to_user(&frame->sf_mask, set);
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Arguments to signal handler:
|
||||
@ -516,37 +516,32 @@ static int setup_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
* $25 and c0_epc point to the signal handler, $29 points to the
|
||||
* struct sigframe.
|
||||
*/
|
||||
regs->regs[ 4] = signr;
|
||||
regs->regs[ 4] = ksig->sig;
|
||||
regs->regs[ 5] = 0;
|
||||
regs->regs[ 6] = (unsigned long) &frame->sf_sc;
|
||||
regs->regs[29] = (unsigned long) frame;
|
||||
regs->regs[31] = (unsigned long) sig_return;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr, sigset_t *set,
|
||||
siginfo_t *info)
|
||||
static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe32 __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
|
||||
err |= copy_siginfo_to_user32(&frame->rs_info, info);
|
||||
err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
@ -556,7 +551,7 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Arguments to signal handler:
|
||||
@ -568,22 +563,18 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
* $25 and c0_epc point to the signal handler, $29 points to
|
||||
* the struct rt_sigframe32.
|
||||
*/
|
||||
regs->regs[ 4] = signr;
|
||||
regs->regs[ 4] = ksig->sig;
|
||||
regs->regs[ 5] = (unsigned long) &frame->rs_info;
|
||||
regs->regs[ 6] = (unsigned long) &frame->rs_uc;
|
||||
regs->regs[29] = (unsigned long) frame;
|
||||
regs->regs[31] = (unsigned long) sig_return;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -102,18 +102,18 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
force_sig(SIGSEGV, current);
|
||||
}
|
||||
|
||||
static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
|
||||
static int setup_rt_frame_n32(void *sig_return, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe_n32 __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Create siginfo. */
|
||||
err |= copy_siginfo_to_user32(&frame->rs_info, info);
|
||||
err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
@ -123,7 +123,7 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
|
||||
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Arguments to signal handler:
|
||||
@ -135,22 +135,18 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
|
||||
* $25 and c0_epc point to the signal handler, $29 points to
|
||||
* the struct rt_sigframe.
|
||||
*/
|
||||
regs->regs[ 4] = signr;
|
||||
regs->regs[ 4] = ksig->sig;
|
||||
regs->regs[ 5] = (unsigned long) &frame->rs_info;
|
||||
regs->regs[ 6] = (unsigned long) &frame->rs_uc;
|
||||
regs->regs[29] = (unsigned long) frame;
|
||||
regs->regs[31] = (unsigned long) sig_return;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler;
|
||||
regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
|
||||
current->comm, current->pid,
|
||||
frame, regs->cp0_epc, regs->regs[31]);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
struct mips_abi mips_abi_n32 = {
|
||||
|
@ -186,20 +186,11 @@ static int setup_sigcontext(struct sigcontext __user *sc,
|
||||
/*
|
||||
* determine which stack to use..
|
||||
*/
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs,
|
||||
size_t frame_size)
|
||||
{
|
||||
unsigned long sp;
|
||||
|
||||
/* default to using normal stack */
|
||||
sp = regs->sp;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
unsigned long sp = sigsp(regs->sp, ksig);
|
||||
|
||||
return (void __user *) ((sp - frame_size) & ~7UL);
|
||||
}
|
||||
@ -207,16 +198,16 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
/*
|
||||
* set up a normal signal frame
|
||||
*/
|
||||
static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int rsig;
|
||||
int rsig, sig = ksig->sig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
rsig = sig;
|
||||
if (sig < 32 &&
|
||||
@ -226,40 +217,40 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
|
||||
if (__put_user(rsig, &frame->sig) < 0 ||
|
||||
__put_user(&frame->sc, &frame->psc) < 0)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (setup_sigcontext(&frame->sc, &frame->fpuctx, regs, set->sig[0]))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (_NSIG_WORDS > 1) {
|
||||
if (__copy_to_user(frame->extramask, &set->sig[1],
|
||||
sizeof(frame->extramask)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* set up to return from userspace. If provided, use a stub already in
|
||||
* userspace */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
|
||||
goto give_sigsegv;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
|
||||
return -EFAULT;
|
||||
} else {
|
||||
if (__put_user((void (*)(void))frame->retcode,
|
||||
&frame->pretcode))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
/* this is mov $,d0; syscall 0 */
|
||||
if (__put_user(0x2c, (char *)(frame->retcode + 0)) ||
|
||||
__put_user(__NR_sigreturn, (char *)(frame->retcode + 1)) ||
|
||||
__put_user(0x00, (char *)(frame->retcode + 2)) ||
|
||||
__put_user(0xf0, (char *)(frame->retcode + 3)) ||
|
||||
__put_user(0xe0, (char *)(frame->retcode + 4)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
flush_icache_range((unsigned long) frame->retcode,
|
||||
(unsigned long) frame->retcode + 5);
|
||||
}
|
||||
|
||||
/* set up registers for signal handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->d0 = sig;
|
||||
regs->d1 = (unsigned long) &frame->sc;
|
||||
|
||||
@ -270,25 +261,21 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* set up a realtime signal frame
|
||||
*/
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int rsig;
|
||||
int rsig, sig = ksig->sig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
rsig = sig;
|
||||
if (sig < 32 &&
|
||||
@ -299,8 +286,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (__put_user(rsig, &frame->sig) ||
|
||||
__put_user(&frame->info, &frame->pinfo) ||
|
||||
__put_user(&frame->uc, &frame->puc) ||
|
||||
copy_siginfo_to_user(&frame->info, info))
|
||||
goto give_sigsegv;
|
||||
copy_siginfo_to_user(&frame->info, &ksig->info))
|
||||
return -EFAULT;
|
||||
|
||||
/* create the ucontext. */
|
||||
if (__put_user(0, &frame->uc.uc_flags) ||
|
||||
@ -309,13 +296,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
setup_sigcontext(&frame->uc.uc_mcontext,
|
||||
&frame->fpuctx, regs, set->sig[0]) ||
|
||||
__copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* set up to return from userspace. If provided, use a stub already in
|
||||
* userspace */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ka->sa.sa_restorer, &frame->pretcode))
|
||||
goto give_sigsegv;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
if (__put_user(ksig->ka.sa.sa_restorer, &frame->pretcode))
|
||||
return -EFAULT;
|
||||
|
||||
} else {
|
||||
if (__put_user((void(*)(void))frame->retcode,
|
||||
&frame->pretcode) ||
|
||||
@ -326,7 +314,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
__put_user(0x00, (char *)(frame->retcode + 2)) ||
|
||||
__put_user(0xf0, (char *)(frame->retcode + 3)) ||
|
||||
__put_user(0xe0, (char *)(frame->retcode + 4)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
flush_icache_range((u_long) frame->retcode,
|
||||
(u_long) frame->retcode + 5);
|
||||
@ -334,7 +322,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->d0 = sig;
|
||||
regs->d1 = (long) &frame->info;
|
||||
|
||||
@ -345,10 +333,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void stepback(struct pt_regs *regs)
|
||||
@ -360,9 +344,7 @@ static inline void stepback(struct pt_regs *regs)
|
||||
/*
|
||||
* handle the actual delivery of a signal to userspace
|
||||
*/
|
||||
static int handle_signal(int sig,
|
||||
siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
static int handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
@ -377,7 +359,7 @@ static int handle_signal(int sig,
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->d0 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -390,15 +372,12 @@ static int handle_signal(int sig,
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -407,15 +386,10 @@ static int handle_signal(int sig,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (handle_signal(signr, &info, &ka, regs) == 0) {
|
||||
}
|
||||
struct ksignal ksig;
|
||||
|
||||
if (get_signal(&ksig)) {
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -132,30 +132,16 @@ static inline unsigned long align_sigframe(unsigned long sp)
|
||||
* or the alternate stack.
|
||||
*/
|
||||
|
||||
static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
static inline void __user *get_sigframe(struct ksignal *ksig,
|
||||
struct pt_regs *regs, size_t frame_size)
|
||||
{
|
||||
unsigned long sp = regs->sp;
|
||||
int onsigstack = on_sig_stack(sp);
|
||||
|
||||
/* redzone */
|
||||
sp -= STACK_FRAME_OVERHEAD;
|
||||
|
||||
/* This is the X/Open sanctioned signal stack switching. */
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && !onsigstack) {
|
||||
if (current->sas_ss_size)
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
|
||||
sp = sigsp(sp, ksig);
|
||||
sp = align_sigframe(sp - frame_size);
|
||||
|
||||
/*
|
||||
* If we are on the alternate signal stack and would overflow it, don't.
|
||||
* Return an always-bogus address instead so we will die with SIGSEGV.
|
||||
*/
|
||||
if (onsigstack && !likely(on_sig_stack(sp)))
|
||||
return (void __user *)-1L;
|
||||
|
||||
return (void __user *)sp;
|
||||
}
|
||||
|
||||
@ -173,7 +159,7 @@ static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
unsigned long return_ip;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(ksig, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
return -EFAULT;
|
||||
|
@ -227,8 +227,8 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, int in_sysc
|
||||
}
|
||||
|
||||
static long
|
||||
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs, int in_syscall)
|
||||
setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs,
|
||||
int in_syscall)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
unsigned long rp, usp;
|
||||
@ -241,10 +241,10 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
usp = (regs->gr[30] & ~(0x01UL));
|
||||
/*FIXME: frame_size parameter is unused, remove it. */
|
||||
frame = get_sigframe(ka, usp, sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, usp, sizeof(*frame));
|
||||
|
||||
DBG(1,"SETUP_RT_FRAME: START\n");
|
||||
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, info);
|
||||
DBG(1,"setup_rt_frame: frame %p info %p\n", frame, ksig->info);
|
||||
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
@ -253,7 +253,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
if (is_compat_task()) {
|
||||
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
|
||||
err |= copy_siginfo_to_user32(&compat_frame->info, info);
|
||||
err |= copy_siginfo_to_user32(&compat_frame->info, &ksig->info);
|
||||
err |= __compat_save_altstack( &compat_frame->uc.uc_stack, regs->gr[30]);
|
||||
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &compat_frame->uc);
|
||||
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext);
|
||||
@ -265,7 +265,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
#endif
|
||||
{
|
||||
DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &frame->info);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
err |= __save_altstack(&frame->uc.uc_stack, regs->gr[30]);
|
||||
DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
|
||||
DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
|
||||
@ -275,7 +275,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. The first words of tramp are used to
|
||||
@ -312,9 +312,9 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
rp = (unsigned long) &frame->tramp[SIGRESTARTBLOCK_TRAMP];
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
haddr = A(ka->sa.sa_handler);
|
||||
haddr = A(ksig->ka.sa.sa_handler);
|
||||
/* The sa_handler may be a pointer to a function descriptor */
|
||||
#ifdef CONFIG_64BIT
|
||||
if (is_compat_task()) {
|
||||
@ -326,7 +326,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
haddr = fdesc.addr;
|
||||
regs->gr[19] = fdesc.gp;
|
||||
@ -339,7 +339,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err = __copy_from_user(&fdesc, ufdesc, sizeof(fdesc));
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
haddr = fdesc.addr;
|
||||
regs->gr[19] = fdesc.gp;
|
||||
@ -386,7 +386,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
regs->gr[2] = rp; /* userland return pointer */
|
||||
regs->gr[26] = sig; /* signal number */
|
||||
regs->gr[26] = ksig->sig; /* signal number */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
if (is_compat_task()) {
|
||||
@ -410,11 +410,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
current->comm, current->pid, frame, regs->gr[30],
|
||||
regs->iaoq[0], regs->iaoq[1], rp);
|
||||
|
||||
return 1;
|
||||
|
||||
give_sigsegv:
|
||||
DBG(1,"setup_rt_frame: sending SIGSEGV\n");
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -423,20 +418,19 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int in_syscall)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs, int in_syscall)
|
||||
{
|
||||
int ret;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
|
||||
DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
|
||||
sig, ka, info, oldset, regs);
|
||||
ksig->sig, ksig->ka, ksig->info, oldset, regs);
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
|
||||
return;
|
||||
ret = setup_rt_frame(ksig, oldset, regs, in_syscall);
|
||||
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP) ||
|
||||
test_thread_flag(TIF_BLOCKSTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP) ||
|
||||
test_thread_flag(TIF_BLOCKSTEP));
|
||||
|
||||
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
|
||||
regs->gr[28]);
|
||||
@ -544,22 +538,18 @@ insert_restart_trampoline(struct pt_regs *regs)
|
||||
asmlinkage void
|
||||
do_signal(struct pt_regs *regs, long in_syscall)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
|
||||
regs, regs->sr[7], in_syscall);
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
|
||||
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
|
||||
/* Restart a system call if necessary. */
|
||||
if (in_syscall)
|
||||
syscall_restart(regs, &ka);
|
||||
syscall_restart(regs, &ksig.ka);
|
||||
|
||||
handle_signal(signr, &info, &ka, regs, in_syscall);
|
||||
handle_signal(&ksig, regs, in_syscall);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -31,20 +31,14 @@ int show_unhandled_signals = 1;
|
||||
/*
|
||||
* Allocate space for the signal frame
|
||||
*/
|
||||
void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
|
||||
void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
|
||||
size_t frame_size, int is_32)
|
||||
{
|
||||
unsigned long oldsp, newsp;
|
||||
|
||||
/* Default to using normal stack */
|
||||
oldsp = get_clean_sp(sp, is_32);
|
||||
|
||||
/* Check for alt stack */
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) &&
|
||||
current->sas_ss_size && !on_sig_stack(oldsp))
|
||||
oldsp = (current->sas_ss_sp + current->sas_ss_size);
|
||||
|
||||
/* Get aligned frame */
|
||||
oldsp = sigsp(oldsp, ksig);
|
||||
newsp = (oldsp - frame_size) & ~0xFUL;
|
||||
|
||||
/* Check access */
|
||||
@ -105,25 +99,23 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
|
||||
}
|
||||
}
|
||||
|
||||
static int do_signal(struct pt_regs *regs)
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
int ret;
|
||||
int is32 = is_32bit_task();
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
get_signal(&ksig);
|
||||
|
||||
/* Is there any syscall restart business here ? */
|
||||
check_syscall_restart(regs, &ka, signr > 0);
|
||||
check_syscall_restart(regs, &ksig.ka, ksig.sig > 0);
|
||||
|
||||
if (signr <= 0) {
|
||||
if (ksig.sig <= 0) {
|
||||
/* No signal to deliver -- put the saved sigmask back */
|
||||
restore_saved_sigmask();
|
||||
regs->trap = 0;
|
||||
return 0; /* no signals delivered */
|
||||
return; /* no signals delivered */
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_ADV_DEBUG_REGS
|
||||
@ -140,23 +132,16 @@ static int do_signal(struct pt_regs *regs)
|
||||
thread_change_pc(current, regs);
|
||||
|
||||
if (is32) {
|
||||
if (ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = handle_rt_signal32(signr, &ka, &info, oldset,
|
||||
regs);
|
||||
if (ksig.ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = handle_rt_signal32(&ksig, oldset, regs);
|
||||
else
|
||||
ret = handle_signal32(signr, &ka, &info, oldset,
|
||||
regs);
|
||||
ret = handle_signal32(&ksig, oldset, regs);
|
||||
} else {
|
||||
ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
|
||||
ret = handle_rt_signal64(&ksig, oldset, regs);
|
||||
}
|
||||
|
||||
regs->trap = 0;
|
||||
if (ret) {
|
||||
signal_delivered(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
return ret;
|
||||
signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
|
||||
|
@ -12,15 +12,13 @@
|
||||
|
||||
extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
|
||||
|
||||
extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp,
|
||||
extern void __user *get_sigframe(struct ksignal *ksig, unsigned long sp,
|
||||
size_t frame_size, int is_32);
|
||||
|
||||
extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
struct pt_regs *regs);
|
||||
|
||||
extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
struct pt_regs *regs);
|
||||
|
||||
extern unsigned long copy_fpr_to_user(void __user *to,
|
||||
@ -44,14 +42,12 @@ extern unsigned long copy_transact_vsx_from_user(struct task_struct *task,
|
||||
|
||||
#ifdef CONFIG_PPC64
|
||||
|
||||
extern int handle_rt_signal64(int signr, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *set,
|
||||
extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs);
|
||||
|
||||
#else /* CONFIG_PPC64 */
|
||||
|
||||
static inline int handle_rt_signal64(int signr, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *set,
|
||||
static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
return -EFAULT;
|
||||
|
@ -981,9 +981,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
|
||||
* Set up a signal frame for a "real-time" signal handler
|
||||
* (one which gets siginfo).
|
||||
*/
|
||||
int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *rt_sf;
|
||||
struct mcontext __user *frame;
|
||||
@ -995,13 +994,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
|
||||
/* Set up Signal Frame */
|
||||
/* Put a Real Time Context onto stack */
|
||||
rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
|
||||
rt_sf = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*rt_sf), 1);
|
||||
addr = rt_sf;
|
||||
if (unlikely(rt_sf == NULL))
|
||||
goto badframe;
|
||||
|
||||
/* Put the siginfo & fill in most of the ucontext */
|
||||
if (copy_siginfo_to_user(&rt_sf->info, info)
|
||||
if (copy_siginfo_to_user(&rt_sf->info, &ksig->info)
|
||||
|| __put_user(0, &rt_sf->uc.uc_flags)
|
||||
|| __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1])
|
||||
|| __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext),
|
||||
@ -1051,15 +1050,15 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
|
||||
/* Fill registers for signal handler */
|
||||
regs->gpr[1] = newsp;
|
||||
regs->gpr[3] = sig;
|
||||
regs->gpr[3] = ksig->sig;
|
||||
regs->gpr[4] = (unsigned long) &rt_sf->info;
|
||||
regs->gpr[5] = (unsigned long) &rt_sf->uc;
|
||||
regs->gpr[6] = (unsigned long) rt_sf;
|
||||
regs->nip = (unsigned long) ka->sa.sa_handler;
|
||||
regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
/* enter the signal handler in native-endian mode */
|
||||
regs->msr &= ~MSR_LE;
|
||||
regs->msr |= (MSR_KERNEL & MSR_LE);
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
badframe:
|
||||
if (show_unhandled_signals)
|
||||
@ -1069,8 +1068,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
current->comm, current->pid,
|
||||
addr, regs->nip, regs->link);
|
||||
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig)
|
||||
@ -1409,8 +1407,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
||||
int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs)
|
||||
{
|
||||
struct sigcontext __user *sc;
|
||||
struct sigframe __user *frame;
|
||||
@ -1420,7 +1417,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
unsigned long tramp;
|
||||
|
||||
/* Set up Signal Frame */
|
||||
frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1);
|
||||
frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 1);
|
||||
if (unlikely(frame == NULL))
|
||||
goto badframe;
|
||||
sc = (struct sigcontext __user *) &frame->sctx;
|
||||
@ -1428,7 +1425,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
#if _NSIG != 64
|
||||
#error "Please adjust handle_signal()"
|
||||
#endif
|
||||
if (__put_user(to_user_ptr(ka->sa.sa_handler), &sc->handler)
|
||||
if (__put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler)
|
||||
|| __put_user(oldset->sig[0], &sc->oldmask)
|
||||
#ifdef CONFIG_PPC64
|
||||
|| __put_user((oldset->sig[0] >> 32), &sc->_unused[3])
|
||||
@ -1436,7 +1433,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
|| __put_user(oldset->sig[1], &sc->_unused[3])
|
||||
#endif
|
||||
|| __put_user(to_user_ptr(&frame->mctx), &sc->regs)
|
||||
|| __put_user(sig, &sc->signal))
|
||||
|| __put_user(ksig->sig, &sc->signal))
|
||||
goto badframe;
|
||||
|
||||
if (vdso32_sigtramp && current->mm->context.vdso_base) {
|
||||
@ -1471,12 +1468,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
goto badframe;
|
||||
|
||||
regs->gpr[1] = newsp;
|
||||
regs->gpr[3] = sig;
|
||||
regs->gpr[3] = ksig->sig;
|
||||
regs->gpr[4] = (unsigned long) sc;
|
||||
regs->nip = (unsigned long) ka->sa.sa_handler;
|
||||
regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler;
|
||||
/* enter the signal handler in big-endian mode */
|
||||
regs->msr &= ~MSR_LE;
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
badframe:
|
||||
if (show_unhandled_signals)
|
||||
@ -1486,8 +1483,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
current->comm, current->pid,
|
||||
frame, regs->nip, regs->link);
|
||||
|
||||
force_sigsegv(sig, current);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -708,20 +708,19 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
unsigned long newsp = 0;
|
||||
long err = 0;
|
||||
|
||||
frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0);
|
||||
frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 0);
|
||||
if (unlikely(frame == NULL))
|
||||
goto badframe;
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
if (err)
|
||||
goto badframe;
|
||||
|
||||
@ -736,15 +735,15 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= __put_user(&frame->uc_transact, &frame->uc.uc_link);
|
||||
err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext,
|
||||
&frame->uc_transact.uc_mcontext,
|
||||
regs, signr,
|
||||
regs, ksig->sig,
|
||||
NULL,
|
||||
(unsigned long)ka->sa.sa_handler);
|
||||
(unsigned long)ksig->ka.sa.sa_handler);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
err |= __put_user(0, &frame->uc.uc_link);
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr,
|
||||
NULL, (unsigned long)ka->sa.sa_handler,
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, ksig->sig,
|
||||
NULL, (unsigned long)ksig->ka.sa.sa_handler,
|
||||
1);
|
||||
}
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
@ -770,7 +769,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
/* Set up "regs" so we "return" to the signal handler. */
|
||||
if (is_elf2_task()) {
|
||||
regs->nip = (unsigned long) ka->sa.sa_handler;
|
||||
regs->nip = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->gpr[12] = regs->nip;
|
||||
} else {
|
||||
/* Handler is *really* a pointer to the function descriptor for
|
||||
@ -779,7 +778,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
* entry is the TOC value we need to use.
|
||||
*/
|
||||
func_descr_t __user *funct_desc_ptr =
|
||||
(func_descr_t __user *) ka->sa.sa_handler;
|
||||
(func_descr_t __user *) ksig->ka.sa.sa_handler;
|
||||
|
||||
err |= get_user(regs->nip, &funct_desc_ptr->entry);
|
||||
err |= get_user(regs->gpr[2], &funct_desc_ptr->toc);
|
||||
@ -789,9 +788,9 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->msr &= ~MSR_LE;
|
||||
regs->msr |= (MSR_KERNEL & MSR_LE);
|
||||
regs->gpr[1] = newsp;
|
||||
regs->gpr[3] = signr;
|
||||
regs->gpr[3] = ksig->sig;
|
||||
regs->result = 0;
|
||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
|
||||
err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo);
|
||||
err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc);
|
||||
regs->gpr[6] = (unsigned long) frame;
|
||||
@ -801,7 +800,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (err)
|
||||
goto badframe;
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
badframe:
|
||||
if (show_unhandled_signals)
|
||||
@ -809,6 +808,5 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info,
|
||||
current->comm, current->pid, "setup_rt_frame",
|
||||
(long)frame, regs->nip, regs->link);
|
||||
|
||||
force_sigsegv(signr, current);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -320,38 +320,39 @@ static inline int map_signal(int sig)
|
||||
return sig;
|
||||
}
|
||||
|
||||
static int setup_frame32(int sig, struct k_sigaction *ka,
|
||||
sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_frame32(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
|
||||
int sig = ksig->sig;
|
||||
sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(sigframe32));
|
||||
|
||||
if (frame == (void __user *) -1UL)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE32))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (save_sigregs32(regs, &frame->sregs))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
if (save_sigregs_gprs_high(regs, frame->gprs_high))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
if (__put_user((unsigned long) &frame->sregs, &frame->sc.sregs))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
|
||||
} else {
|
||||
regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
|
||||
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
|
||||
(u16 __force __user *)(frame->retcode)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Set up backchain. */
|
||||
if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->gprs[15] = (__force __u64) frame;
|
||||
@ -359,7 +360,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
|
||||
regs->psw.mask = PSW_MASK_BA |
|
||||
(PSW_USER_BITS & PSW_MASK_ASC) |
|
||||
(regs->psw.mask & ~PSW_MASK_ASC);
|
||||
regs->psw.addr = (__force __u64) ka->sa.sa_handler;
|
||||
regs->psw.addr = (__force __u64) ksig->ka.sa.sa_handler;
|
||||
|
||||
regs->gprs[2] = map_signal(sig);
|
||||
regs->gprs[3] = (__force __u64) &frame->sc;
|
||||
@ -376,25 +377,21 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
|
||||
|
||||
/* Place signal number on stack to allow backtrace from handler. */
|
||||
if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));
|
||||
rt_sigframe32 __user *frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe32));
|
||||
|
||||
if (frame == (void __user *) -1UL)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_siginfo_to_user32(&frame->info, info))
|
||||
goto give_sigsegv;
|
||||
if (copy_siginfo_to_user32(&frame->info, &ksig->info))
|
||||
return -EFAULT;
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
|
||||
@ -404,22 +401,22 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= save_sigregs_gprs_high(regs, frame->gprs_high);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
regs->gprs[14] = (__u64 __force) ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
|
||||
} else {
|
||||
regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
|
||||
if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
|
||||
(u16 __force __user *)(frame->retcode)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Set up backchain. */
|
||||
if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->gprs[15] = (__force __u64) frame;
|
||||
@ -427,36 +424,30 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->psw.mask = PSW_MASK_BA |
|
||||
(PSW_USER_BITS & PSW_MASK_ASC) |
|
||||
(regs->psw.mask & ~PSW_MASK_ASC);
|
||||
regs->psw.addr = (__u64 __force) ka->sa.sa_handler;
|
||||
regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler;
|
||||
|
||||
regs->gprs[2] = map_signal(sig);
|
||||
regs->gprs[2] = map_signal(ksig->sig);
|
||||
regs->gprs[3] = (__force __u64) &frame->info;
|
||||
regs->gprs[4] = (__force __u64) &frame->uc;
|
||||
regs->gprs[5] = task_thread_info(current)->last_break;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
|
||||
void handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
||||
void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame32(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame32(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame32(sig, ka, oldset, regs);
|
||||
if (ret)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
ret = setup_frame32(ksig, oldset, regs);
|
||||
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
|
||||
|
@ -48,8 +48,8 @@ void do_per_trap(struct pt_regs *regs);
|
||||
void syscall_trace(struct pt_regs *regs, int entryexit);
|
||||
void kernel_stack_overflow(struct pt_regs * regs);
|
||||
void do_signal(struct pt_regs *regs);
|
||||
void handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
|
||||
void handle_signal32(struct ksignal *ksig, sigset_t *oldset,
|
||||
struct pt_regs *regs);
|
||||
void do_notify_resume(struct pt_regs *regs);
|
||||
|
||||
void __init init_IRQ(void);
|
||||
|
@ -200,15 +200,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
frame = get_sigframe(ka, regs, sizeof(sigframe));
|
||||
|
||||
if (frame == (void __user *) -1UL)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (__copy_to_user(&frame->sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (save_sigregs(regs, &frame->sregs))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
if (__put_user(&frame->sregs, &frame->sc.sregs))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
@ -220,12 +220,12 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
frame->retcode | PSW_ADDR_AMODE;
|
||||
if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
|
||||
(u16 __user *)(frame->retcode)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Set up backchain. */
|
||||
if (__put_user(regs->gprs[15], (addr_t __user *) frame))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->gprs[15] = (unsigned long) frame;
|
||||
@ -250,27 +250,23 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
|
||||
/* Place signal number on stack to allow backtrace from handler. */
|
||||
if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs * regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int err = 0;
|
||||
rt_sigframe __user *frame;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(rt_sigframe));
|
||||
frame = get_sigframe(&ksig->ka, regs, sizeof(rt_sigframe));
|
||||
|
||||
if (frame == (void __user *) -1UL)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (copy_siginfo_to_user(&frame->info, info))
|
||||
goto give_sigsegv;
|
||||
if (copy_siginfo_to_user(&frame->info, &ksig->info))
|
||||
return -EFAULT;
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -279,24 +275,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= save_sigregs(regs, &frame->uc.uc_mcontext);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
regs->gprs[14] = (unsigned long)
|
||||
ka->sa.sa_restorer | PSW_ADDR_AMODE;
|
||||
ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
|
||||
} else {
|
||||
regs->gprs[14] = (unsigned long)
|
||||
frame->retcode | PSW_ADDR_AMODE;
|
||||
if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
|
||||
(u16 __user *)(frame->retcode)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Set up backchain. */
|
||||
if (__put_user(regs->gprs[15], (addr_t __user *) frame))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->gprs[15] = (unsigned long) frame;
|
||||
@ -304,34 +300,27 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->psw.mask = PSW_MASK_EA | PSW_MASK_BA |
|
||||
(PSW_USER_BITS & PSW_MASK_ASC) |
|
||||
(regs->psw.mask & ~PSW_MASK_ASC);
|
||||
regs->psw.addr = (unsigned long) ka->sa.sa_handler | PSW_ADDR_AMODE;
|
||||
regs->psw.addr = (unsigned long) ksig->ka.sa.sa_handler | PSW_ADDR_AMODE;
|
||||
|
||||
regs->gprs[2] = map_signal(sig);
|
||||
regs->gprs[2] = map_signal(ksig->sig);
|
||||
regs->gprs[3] = (unsigned long) &frame->info;
|
||||
regs->gprs[4] = (unsigned long) &frame->uc;
|
||||
regs->gprs[5] = task_thread_info(current)->last_break;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
static void handle_signal(struct ksignal *ksig, sigset_t *oldset,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
if (ret)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
ret = setup_frame(ksig->sig, &ksig->ka, oldset, regs);
|
||||
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -345,9 +334,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
*/
|
||||
void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
|
||||
/*
|
||||
@ -357,9 +344,8 @@ void do_signal(struct pt_regs *regs)
|
||||
*/
|
||||
current_thread_info()->system_call =
|
||||
test_pt_regs_flag(regs, PIF_SYSCALL) ? regs->int_code : 0;
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (current_thread_info()->system_call) {
|
||||
regs->int_code = current_thread_info()->system_call;
|
||||
@ -370,7 +356,7 @@ void do_signal(struct pt_regs *regs)
|
||||
regs->gprs[2] = -EINTR;
|
||||
break;
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka.sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->gprs[2] = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -387,9 +373,9 @@ void do_signal(struct pt_regs *regs)
|
||||
clear_pt_regs_flag(regs, PIF_SYSCALL);
|
||||
|
||||
if (is_compat_task())
|
||||
handle_signal32(signr, &ka, &info, oldset, regs);
|
||||
handle_signal32(&ksig, oldset, regs);
|
||||
else
|
||||
handle_signal(signr, &ka, &info, oldset, regs);
|
||||
handle_signal(&ksig, oldset, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -173,15 +173,15 @@ score_rt_sigreturn(struct pt_regs *regs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
int signr, sigset_t *set, siginfo_t *info)
|
||||
static int setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs,
|
||||
sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/*
|
||||
* Set up the return code ...
|
||||
@ -194,7 +194,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __put_user(0x80008002, frame->rs_code + 1);
|
||||
flush_cache_sigtramp((unsigned long) frame->rs_code);
|
||||
|
||||
err |= copy_siginfo_to_user(&frame->rs_info, info);
|
||||
err |= copy_siginfo_to_user(&frame->rs_info, &ksig->info);
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
err |= __put_user(NULL, &frame->rs_uc.uc_link);
|
||||
err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[0]);
|
||||
@ -202,26 +202,23 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
regs->regs[0] = (unsigned long) frame;
|
||||
regs->regs[3] = (unsigned long) frame->rs_code;
|
||||
regs->regs[4] = signr;
|
||||
regs->regs[4] = ksig->sig;
|
||||
regs->regs[5] = (unsigned long) &frame->rs_info;
|
||||
regs->regs[6] = (unsigned long) &frame->rs_uc;
|
||||
regs->regs[29] = (unsigned long) ka->sa.sa_handler;
|
||||
regs->cp0_epc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->regs[29] = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->cp0_epc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(signr, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, struct pt_regs *regs)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (regs->is_syscall) {
|
||||
switch (regs->regs[4]) {
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
@ -229,7 +226,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
regs->regs[4] = EINTR;
|
||||
break;
|
||||
case ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->regs[4] = EINTR;
|
||||
break;
|
||||
}
|
||||
@ -245,17 +242,14 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
/*
|
||||
* Set up the stack frame
|
||||
*/
|
||||
if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0)
|
||||
return;
|
||||
ret = setup_rt_frame(ksig, regs, sigmask_to_save());
|
||||
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which is why we may in certain
|
||||
@ -265,10 +259,9 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -262,17 +262,17 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
|
||||
extern void __kernel_sigreturn(void);
|
||||
extern void __kernel_rt_sigreturn(void);
|
||||
|
||||
static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int signal;
|
||||
|
||||
frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -288,8 +288,8 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
regs->pr = (unsigned long) ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
|
||||
#ifdef CONFIG_VSYSCALL
|
||||
} else if (likely(current->mm->context.vdso)) {
|
||||
regs->pr = VDSO_SYM(&__kernel_sigreturn);
|
||||
@ -309,7 +309,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->regs[15] = (unsigned long) frame;
|
||||
@ -319,15 +319,15 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
|
||||
if (current->personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
|
||||
(struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
|
||||
|
||||
err |= __get_user(regs->pc, &funcptr->text);
|
||||
err |= __get_user(regs->regs[12], &funcptr->GOT);
|
||||
} else
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
@ -335,23 +335,19 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int signal;
|
||||
|
||||
frame = get_sigframe(ka, regs->regs[15], sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, regs->regs[15], sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -359,7 +355,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
? current_thread_info()->exec_domain->signal_invmap[sig]
|
||||
: sig;
|
||||
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -371,8 +367,8 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
regs->pr = (unsigned long) ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
regs->pr = (unsigned long) ksig->ka.sa.sa_restorer;
|
||||
#ifdef CONFIG_VSYSCALL
|
||||
} else if (likely(current->mm->context.vdso)) {
|
||||
regs->pr = VDSO_SYM(&__kernel_rt_sigreturn);
|
||||
@ -392,7 +388,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
regs->regs[15] = (unsigned long) frame;
|
||||
@ -402,15 +398,15 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
if (current->personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
|
||||
(struct fdpic_func_descriptor __user *)ksig->ka.sa.sa_handler;
|
||||
|
||||
err |= __get_user(regs->pc, &funcptr->text);
|
||||
err |= __get_user(regs->regs[12], &funcptr->GOT);
|
||||
} else
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
@ -418,10 +414,6 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
current->comm, task_pid_nr(current), frame, regs->pc, regs->pr);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline void
|
||||
@ -455,22 +447,18 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void
|
||||
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
struct pt_regs *regs, unsigned int save_r0)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs, unsigned int save_r0)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -484,9 +472,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, unsigned int save_r0)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -497,12 +483,11 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
handle_syscall_restart(save_r0, regs, &ka.sa);
|
||||
if (get_signal(&ksig)) {
|
||||
handle_syscall_restart(save_r0, regs, &ksig.ka.sa);
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &ka, &info, regs, save_r0);
|
||||
handle_signal(&ksig, regs, save_r0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,7 @@
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
static void
|
||||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs * regs);
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs);
|
||||
|
||||
static inline void
|
||||
handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
|
||||
@ -82,9 +81,7 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -95,12 +92,11 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, 0);
|
||||
if (signr > 0) {
|
||||
handle_syscall_restart(regs, &ka.sa);
|
||||
if (get_signal(&ksig)) {
|
||||
handle_syscall_restart(regs, &ksig.ka.sa);
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -378,17 +374,16 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
|
||||
void sa_default_restorer(void); /* See comments below */
|
||||
void sa_default_rt_restorer(void); /* See comments below */
|
||||
|
||||
static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int signal;
|
||||
|
||||
frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -400,7 +395,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
|
||||
/* Give up earlier as i386, in case */
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
if (_NSIG_WORDS > 1) {
|
||||
err |= __copy_to_user(frame->extramask, &set->sig[1],
|
||||
@ -408,16 +403,16 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
|
||||
/* Give up earlier as i386, in case */
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
/*
|
||||
* On SH5 all edited pointers are subject to NEFF
|
||||
*/
|
||||
DEREF_REG_PR = neff_sign_extend((unsigned long)
|
||||
ka->sa.sa_restorer | 0x1);
|
||||
ksig->ka->sa.sa_restorer | 0x1);
|
||||
} else {
|
||||
/*
|
||||
* Different approach on SH5.
|
||||
@ -435,7 +430,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
|
||||
if (__copy_to_user(frame->retcode,
|
||||
(void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Cohere the trampoline with the I-cache. */
|
||||
flush_cache_sigtramp(DEREF_REG_PR-1);
|
||||
@ -460,7 +455,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
|
||||
regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
|
||||
|
||||
regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
|
||||
regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
@ -471,23 +466,19 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
||||
DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *kig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int signal;
|
||||
|
||||
frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, regs->regs[REG_SP], sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -497,11 +488,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
/* Give up earlier as i386, in case */
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->uc.uc_flags);
|
||||
@ -513,16 +504,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
/* Give up earlier as i386, in case */
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
/*
|
||||
* On SH5 all edited pointers are subject to NEFF
|
||||
*/
|
||||
DEREF_REG_PR = neff_sign_extend((unsigned long)
|
||||
ka->sa.sa_restorer | 0x1);
|
||||
ksig->ka.sa.sa_restorer | 0x1);
|
||||
} else {
|
||||
/*
|
||||
* Different approach on SH5.
|
||||
@ -540,7 +531,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
if (__copy_to_user(frame->retcode,
|
||||
(void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Cohere the trampoline with the I-cache. */
|
||||
flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
|
||||
@ -554,7 +545,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
|
||||
regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
|
||||
regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
|
||||
regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
|
||||
regs->pc = neff_sign_extend((unsigned long)ksig->ka.sa.sa_handler);
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
@ -564,33 +555,24 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void
|
||||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs * regs)
|
||||
handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
|
||||
|
@ -267,8 +267,7 @@ static inline int is_compat_task(void)
|
||||
return current_thread_info()->status & TS_COMPAT;
|
||||
}
|
||||
|
||||
extern int compat_setup_rt_frame(int sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *set,
|
||||
extern int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs);
|
||||
|
||||
/* Compat syscalls. */
|
||||
|
@ -190,18 +190,18 @@ static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
|
||||
return (void __user *) sp;
|
||||
}
|
||||
|
||||
int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long restorer;
|
||||
struct compat_rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int usig;
|
||||
|
||||
frame = compat_get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
goto err;
|
||||
|
||||
usig = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -210,12 +210,12 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
: sig;
|
||||
|
||||
/* Always write at least the signal number for the stack backtracer. */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
|
||||
/* At sigreturn time, restore the callee-save registers too. */
|
||||
err |= copy_siginfo_to_user32(&frame->info, info);
|
||||
err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
|
||||
regs->flags |= PT_FLAGS_RESTORE_REGS;
|
||||
} else {
|
||||
err |= __put_user(info->si_signo, &frame->info.si_signo);
|
||||
err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
|
||||
}
|
||||
|
||||
/* Create the ucontext. */
|
||||
@ -226,11 +226,11 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
goto err;
|
||||
|
||||
restorer = VDSO_SYM(&__vdso_rt_sigreturn);
|
||||
if (ka->sa.sa_flags & SA_RESTORER)
|
||||
restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
|
||||
|
||||
/*
|
||||
* Set up registers for signal handler.
|
||||
@ -239,7 +239,7 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
* We always pass siginfo and mcontext, regardless of SA_SIGINFO,
|
||||
* since some things rely on this (e.g. glibc's debug/segfault.c).
|
||||
*/
|
||||
regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
|
||||
regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
|
||||
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
|
||||
regs->sp = ptr_to_compat_reg(frame);
|
||||
regs->lr = restorer;
|
||||
@ -249,7 +249,8 @@ int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->flags |= PT_FLAGS_CALLER_SAVES;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
signal_fault("bad setup frame", regs, frame, sig);
|
||||
err:
|
||||
trace_unhandled_signal("bad sigreturn frame", regs,
|
||||
(unsigned long)frame, SIGSEGV);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
@ -153,18 +153,18 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
|
||||
return (void __user *) sp;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
unsigned long restorer;
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int usig;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
goto err;
|
||||
|
||||
usig = current_thread_info()->exec_domain
|
||||
&& current_thread_info()->exec_domain->signal_invmap
|
||||
@ -173,12 +173,12 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
: sig;
|
||||
|
||||
/* Always write at least the signal number for the stack backtracer. */
|
||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
|
||||
/* At sigreturn time, restore the callee-save registers too. */
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
regs->flags |= PT_FLAGS_RESTORE_REGS;
|
||||
} else {
|
||||
err |= __put_user(info->si_signo, &frame->info.si_signo);
|
||||
err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
|
||||
}
|
||||
|
||||
/* Create the ucontext. */
|
||||
@ -189,11 +189,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
goto err;
|
||||
|
||||
restorer = VDSO_SYM(&__vdso_rt_sigreturn);
|
||||
if (ka->sa.sa_flags & SA_RESTORER)
|
||||
restorer = (unsigned long) ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
restorer = (unsigned long) ksig->ka.sa.sa_restorer;
|
||||
|
||||
/*
|
||||
* Set up registers for signal handler.
|
||||
@ -202,7 +202,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
* We always pass siginfo and mcontext, regardless of SA_SIGINFO,
|
||||
* since some things rely on this (e.g. glibc's debug/segfault.c).
|
||||
*/
|
||||
regs->pc = (unsigned long) ka->sa.sa_handler;
|
||||
regs->pc = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
|
||||
regs->sp = (unsigned long) frame;
|
||||
regs->lr = restorer;
|
||||
@ -212,8 +212,9 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
regs->flags |= PT_FLAGS_CALLER_SAVES;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
signal_fault("bad setup frame", regs, frame, sig);
|
||||
err:
|
||||
trace_unhandled_signal("bad sigreturn frame", regs,
|
||||
(unsigned long)frame, SIGSEGV);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -221,9 +222,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
@ -238,7 +237,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->regs[0] = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -254,14 +253,12 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
/* Set up the stack frame */
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (is_compat_task())
|
||||
ret = compat_setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
ret = compat_setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
#endif
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ret)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
|
||||
signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -271,9 +268,7 @@ static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
*/
|
||||
void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* i386 will check if we're coming from kernel mode and bail out
|
||||
@ -282,10 +277,9 @@ void do_signal(struct pt_regs *regs)
|
||||
* helpful, we can reinstate the check on "!user_mode(regs)".
|
||||
*/
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
handle_signal(&ksig, regs);
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
@ -6,14 +6,10 @@
|
||||
#ifndef __FRAME_KERN_H_
|
||||
#define __FRAME_KERN_H_
|
||||
|
||||
extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
|
||||
struct k_sigaction *ka,
|
||||
struct pt_regs *regs,
|
||||
sigset_t *mask);
|
||||
extern int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
struct k_sigaction *ka,
|
||||
struct pt_regs *regs, struct siginfo *info,
|
||||
sigset_t *mask);
|
||||
extern int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *mask);
|
||||
extern int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *mask);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -18,8 +18,7 @@ EXPORT_SYMBOL(unblock_signals);
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
struct k_sigaction *ka, struct siginfo *info)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int singlestep = 0;
|
||||
@ -39,7 +38,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
PT_REGS_SYSCALL_RET(regs) = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -52,32 +51,28 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
}
|
||||
|
||||
sp = PT_REGS_SP(regs);
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
|
||||
if ((ksig->ka.sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
|
||||
#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
|
||||
if (!(ka->sa.sa_flags & SA_SIGINFO))
|
||||
err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
|
||||
if (!(ksig->ka.sa.sa_flags & SA_SIGINFO))
|
||||
err = setup_signal_stack_sc(sp, ksig, regs, oldset);
|
||||
else
|
||||
#endif
|
||||
err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);
|
||||
err = setup_signal_stack_si(sp, ksig, regs, oldset);
|
||||
|
||||
if (err)
|
||||
force_sigsegv(signr, current);
|
||||
else
|
||||
signal_delivered(signr, info, ka, regs, singlestep);
|
||||
signal_setup_done(err, ksig, singlestep);
|
||||
}
|
||||
|
||||
static int kern_do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka_copy;
|
||||
struct siginfo info;
|
||||
int sig, handled_sig = 0;
|
||||
struct ksignal ksig;
|
||||
int handled_sig = 0;
|
||||
|
||||
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
|
||||
while (get_signal(&ksig)) {
|
||||
handled_sig = 1;
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(regs, sig, &ka_copy, &info);
|
||||
handle_signal(&ksig, regs);
|
||||
}
|
||||
|
||||
/* Did we come from a system call? */
|
||||
|
@ -238,10 +238,10 @@ static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setup_frame(int usig, struct k_sigaction *ka,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
struct sigframe __user *frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
|
||||
int err = 0;
|
||||
|
||||
if (!frame)
|
||||
@ -254,29 +254,29 @@ static int setup_frame(int usig, struct k_sigaction *ka,
|
||||
|
||||
err |= setup_sigframe(frame, regs, set);
|
||||
if (err == 0)
|
||||
err |= setup_return(regs, ka, frame->retcode, frame, usig);
|
||||
err |= setup_return(regs, &ksig->ka, frame->retcode, frame, usig);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe __user *frame =
|
||||
get_sigframe(ka, regs, sizeof(*frame));
|
||||
get_sigframe(&ksig->ka, regs, sizeof(*frame));
|
||||
int err = 0;
|
||||
|
||||
if (!frame)
|
||||
return 1;
|
||||
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
|
||||
err |= __put_user(0, &frame->sig.uc.uc_flags);
|
||||
err |= __put_user(NULL, &frame->sig.uc.uc_link);
|
||||
err |= __save_altstack(&frame->sig.uc.uc_stack, regs->UCreg_sp);
|
||||
err |= setup_sigframe(&frame->sig, regs, set);
|
||||
if (err == 0)
|
||||
err |= setup_return(regs, ka, frame->sig.retcode, frame, usig);
|
||||
err |= setup_return(regs, &ksig->ka, frame->sig.retcode, frame, usig);
|
||||
|
||||
if (err == 0) {
|
||||
/*
|
||||
@ -299,13 +299,13 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, struct pt_regs *regs, int syscall)
|
||||
static void handle_signal(struct ksignal *ksig, struct pt_regs *regs,
|
||||
int syscall)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
struct task_struct *tsk = current;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int usig = sig;
|
||||
int usig = ksig->sig;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -318,7 +318,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
regs->UCreg_00 = -EINTR;
|
||||
break;
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka->sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig->ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->UCreg_00 = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -338,22 +338,17 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
/*
|
||||
* Set up the stack frame
|
||||
*/
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(usig, ka, info, oldset, regs);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(ksig, oldset, regs);
|
||||
else
|
||||
ret = setup_frame(usig, ka, oldset, regs);
|
||||
ret = setup_frame(ksig, oldset, regs);
|
||||
|
||||
/*
|
||||
* Check that the resulting registers are actually sane.
|
||||
*/
|
||||
ret |= !valid_user_regs(regs);
|
||||
|
||||
if (ret != 0) {
|
||||
force_sigsegv(sig, tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
signal_setup_done(ret, ksig, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -367,9 +362,7 @@ static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs, int syscall)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct ksignal ksig;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -380,9 +373,8 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
handle_signal(signr, &ka, &info, regs, syscall);
|
||||
if (get_signsl(&ksig)) {
|
||||
handle_signal(&ksig, regs, syscall);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -370,13 +370,12 @@ struct rt_sigframe
|
||||
char retcode[8];
|
||||
};
|
||||
|
||||
int setup_signal_stack_sc(unsigned long stack_top, int sig,
|
||||
struct k_sigaction *ka, struct pt_regs *regs,
|
||||
sigset_t *mask)
|
||||
int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *mask)
|
||||
{
|
||||
struct sigframe __user *frame;
|
||||
void __user *restorer;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
|
||||
/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
|
||||
stack_top = ((stack_top + 4) & -16UL) - 4;
|
||||
@ -385,8 +384,8 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
|
||||
return 1;
|
||||
|
||||
restorer = frame->retcode;
|
||||
if (ka->sa.sa_flags & SA_RESTORER)
|
||||
restorer = ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
restorer = ksig->ka.sa.sa_restorer;
|
||||
|
||||
err |= __put_user(restorer, &frame->pretcode);
|
||||
err |= __put_user(sig, &frame->sig);
|
||||
@ -410,20 +409,19 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
|
||||
return err;
|
||||
|
||||
PT_REGS_SP(regs) = (unsigned long) frame;
|
||||
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
|
||||
PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
PT_REGS_AX(regs) = (unsigned long) sig;
|
||||
PT_REGS_DX(regs) = (unsigned long) 0;
|
||||
PT_REGS_CX(regs) = (unsigned long) 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
struct k_sigaction *ka, struct pt_regs *regs,
|
||||
siginfo_t *info, sigset_t *mask)
|
||||
int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *mask)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
void __user *restorer;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
|
||||
stack_top &= -8UL;
|
||||
frame = (struct rt_sigframe __user *) stack_top - 1;
|
||||
@ -431,14 +429,14 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
return 1;
|
||||
|
||||
restorer = frame->retcode;
|
||||
if (ka->sa.sa_flags & SA_RESTORER)
|
||||
restorer = ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
restorer = ksig->ka.sa.sa_restorer;
|
||||
|
||||
err |= __put_user(restorer, &frame->pretcode);
|
||||
err |= __put_user(sig, &frame->sig);
|
||||
err |= __put_user(&frame->info, &frame->pinfo);
|
||||
err |= __put_user(&frame->uc, &frame->puc);
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
|
||||
PT_REGS_SP(regs));
|
||||
|
||||
@ -457,7 +455,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
return err;
|
||||
|
||||
PT_REGS_SP(regs) = (unsigned long) frame;
|
||||
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
|
||||
PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
PT_REGS_AX(regs) = (unsigned long) sig;
|
||||
PT_REGS_DX(regs) = (unsigned long) &frame->info;
|
||||
PT_REGS_CX(regs) = (unsigned long) &frame->uc;
|
||||
@ -502,12 +500,11 @@ struct rt_sigframe
|
||||
struct _fpstate fpstate;
|
||||
};
|
||||
|
||||
int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
struct k_sigaction *ka, struct pt_regs * regs,
|
||||
siginfo_t *info, sigset_t *set)
|
||||
int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
|
||||
struct pt_regs *regs, sigset_t *set)
|
||||
{
|
||||
struct rt_sigframe __user *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
|
||||
frame = (struct rt_sigframe __user *)
|
||||
round_down(stack_top - sizeof(struct rt_sigframe), 16);
|
||||
@ -517,8 +514,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto out;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
@ -543,8 +540,8 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
* already in userspace.
|
||||
*/
|
||||
/* x86-64 should always use SA_RESTORER. */
|
||||
if (ka->sa.sa_flags & SA_RESTORER)
|
||||
err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER)
|
||||
err |= __put_user(ksig->ka.sa.sa_restorer, &frame->pretcode);
|
||||
else
|
||||
/* could use a vstub here */
|
||||
return err;
|
||||
@ -570,7 +567,7 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
|
||||
*/
|
||||
PT_REGS_SI(regs) = (unsigned long) &frame->info;
|
||||
PT_REGS_DX(regs) = (unsigned long) &frame->uc;
|
||||
PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
|
||||
PT_REGS_IP(regs) = (unsigned long) ksig->ka.sa.sa_handler;
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
@ -331,17 +331,17 @@ gen_return_code(unsigned char *codemem)
|
||||
}
|
||||
|
||||
|
||||
static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *set, struct pt_regs *regs)
|
||||
static int setup_frame(struct ksignal *ksig, sigset_t *set,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
struct rt_sigframe *frame;
|
||||
int err = 0;
|
||||
int err = 0, sig = ksig->sig;
|
||||
int signal;
|
||||
unsigned long sp, ra, tp;
|
||||
|
||||
sp = regs->areg[1];
|
||||
|
||||
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
|
||||
if ((ksig->ka.sa.sa_flags & SA_ONSTACK) != 0 && sas_ss_flags(sp) == 0) {
|
||||
sp = current->sas_ss_sp + current->sas_ss_size;
|
||||
}
|
||||
|
||||
@ -351,7 +351,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
panic ("Double exception sys_sigreturn\n");
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) {
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
signal = current_thread_info()->exec_domain
|
||||
@ -360,8 +360,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
? current_thread_info()->exec_domain->signal_invmap[sig]
|
||||
: sig;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO) {
|
||||
err |= copy_siginfo_to_user(&frame->info, info);
|
||||
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
|
||||
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
|
||||
}
|
||||
|
||||
/* Create the user context. */
|
||||
@ -372,8 +372,8 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= setup_sigcontext(frame, regs);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
|
||||
if (ka->sa.sa_flags & SA_RESTORER) {
|
||||
ra = (unsigned long)ka->sa.sa_restorer;
|
||||
if (ksig->ka.sa.sa_flags & SA_RESTORER) {
|
||||
ra = (unsigned long)ksig->ka.sa.sa_restorer;
|
||||
} else {
|
||||
|
||||
/* Create sys_rt_sigreturn syscall in stack frame */
|
||||
@ -381,7 +381,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
err |= gen_return_code(frame->retcode);
|
||||
|
||||
if (err) {
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
}
|
||||
ra = (unsigned long) frame->retcode;
|
||||
}
|
||||
@ -393,7 +393,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
|
||||
/* Set up registers for signal handler; preserve the threadptr */
|
||||
tp = regs->threadptr;
|
||||
start_thread(regs, (unsigned long) ka->sa.sa_handler,
|
||||
start_thread(regs, (unsigned long) ksig->ka.sa.sa_handler,
|
||||
(unsigned long) frame);
|
||||
|
||||
/* Set up a stack frame for a call4
|
||||
@ -416,10 +416,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -433,15 +429,11 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
*/
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
struct ksignal ksig;
|
||||
|
||||
task_pt_regs(current)->icountlevel = 0;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
if (signr > 0) {
|
||||
if (get_signal(&ksig)) {
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
@ -457,7 +449,7 @@ static void do_signal(struct pt_regs *regs)
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (!(ka.sa.sa_flags & SA_RESTART)) {
|
||||
if (!(ksig.ka.sa.sa_flags & SA_RESTART)) {
|
||||
regs->areg[2] = -EINTR;
|
||||
break;
|
||||
}
|
||||
@ -476,11 +468,8 @@ static void do_signal(struct pt_regs *regs)
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
/* Set up the stack frame */
|
||||
ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
signal_delivered(signr, &info, &ka, regs, 0);
|
||||
ret = setup_frame(&ksig, sigmask_to_save(), regs);
|
||||
signal_setup_done(ret, &ksig, 0);
|
||||
if (current->ptrace & PT_SINGLESTEP)
|
||||
task_pt_regs(current)->icountlevel = 1;
|
||||
|
||||
|
@ -2360,8 +2360,10 @@ static inline int on_sig_stack(unsigned long sp)
|
||||
|
||||
static inline int sas_ss_flags(unsigned long sp)
|
||||
{
|
||||
return (current->sas_ss_size == 0 ? SS_DISABLE
|
||||
: on_sig_stack(sp) ? SS_ONSTACK : 0);
|
||||
if (!current->sas_ss_size)
|
||||
return SS_DISABLE;
|
||||
|
||||
return on_sig_stack(sp) ? SS_ONSTACK : 0;
|
||||
}
|
||||
|
||||
static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig)
|
||||
|
@ -280,9 +280,8 @@ struct ksignal {
|
||||
int sig;
|
||||
};
|
||||
|
||||
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
|
||||
extern int get_signal(struct ksignal *ksig);
|
||||
extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
|
||||
extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping);
|
||||
extern void exit_signals(struct task_struct *tsk);
|
||||
extern void kernel_sigaction(int, __sighandler_t);
|
||||
|
||||
@ -301,18 +300,6 @@ static inline void disallow_signal(int sig)
|
||||
kernel_sigaction(sig, SIG_IGN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Eventually that'll replace get_signal_to_deliver(); macro for now,
|
||||
* to avoid nastiness with include order.
|
||||
*/
|
||||
#define get_signal(ksig) \
|
||||
({ \
|
||||
struct ksignal *p = (ksig); \
|
||||
p->sig = get_signal_to_deliver(&p->info, &p->ka, \
|
||||
signal_pt_regs(), NULL);\
|
||||
p->sig > 0; \
|
||||
})
|
||||
|
||||
extern struct kmem_cache *sighand_cachep;
|
||||
|
||||
int unhandled_signal(struct task_struct *tsk, int sig);
|
||||
|
@ -133,10 +133,6 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
|
||||
|
||||
/**
|
||||
* tracehook_signal_handler - signal handler setup is complete
|
||||
* @sig: number of signal being delivered
|
||||
* @info: siginfo_t of signal being delivered
|
||||
* @ka: sigaction setting that chose the handler
|
||||
* @regs: user register state
|
||||
* @stepping: nonzero if debugger single-step or block-step in use
|
||||
*
|
||||
* Called by the arch code after a signal handler has been set up.
|
||||
@ -146,9 +142,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
|
||||
* Called without locks, shortly before returning to user mode
|
||||
* (or handling more signals).
|
||||
*/
|
||||
static inline void tracehook_signal_handler(int sig, siginfo_t *info,
|
||||
const struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int stepping)
|
||||
static inline void tracehook_signal_handler(int stepping)
|
||||
{
|
||||
if (stepping)
|
||||
ptrace_notify(SIGTRAP);
|
||||
|
@ -2170,8 +2170,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
|
||||
return signr;
|
||||
}
|
||||
|
||||
int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
|
||||
struct pt_regs *regs, void *cookie)
|
||||
int get_signal(struct ksignal *ksig)
|
||||
{
|
||||
struct sighand_struct *sighand = current->sighand;
|
||||
struct signal_struct *signal = current->signal;
|
||||
@ -2241,13 +2240,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
|
||||
goto relock;
|
||||
}
|
||||
|
||||
signr = dequeue_signal(current, ¤t->blocked, info);
|
||||
signr = dequeue_signal(current, ¤t->blocked, &ksig->info);
|
||||
|
||||
if (!signr)
|
||||
break; /* will return 0 */
|
||||
|
||||
if (unlikely(current->ptrace) && signr != SIGKILL) {
|
||||
signr = ptrace_signal(signr, info);
|
||||
signr = ptrace_signal(signr, &ksig->info);
|
||||
if (!signr)
|
||||
continue;
|
||||
}
|
||||
@ -2255,13 +2254,13 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
|
||||
ka = &sighand->action[signr-1];
|
||||
|
||||
/* Trace actually delivered signals. */
|
||||
trace_signal_deliver(signr, info, ka);
|
||||
trace_signal_deliver(signr, &ksig->info, ka);
|
||||
|
||||
if (ka->sa.sa_handler == SIG_IGN) /* Do nothing. */
|
||||
continue;
|
||||
if (ka->sa.sa_handler != SIG_DFL) {
|
||||
/* Run the handler. */
|
||||
*return_ka = *ka;
|
||||
ksig->ka = *ka;
|
||||
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
@ -2311,7 +2310,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
|
||||
spin_lock_irq(&sighand->siglock);
|
||||
}
|
||||
|
||||
if (likely(do_signal_stop(info->si_signo))) {
|
||||
if (likely(do_signal_stop(ksig->info.si_signo))) {
|
||||
/* It released the siglock. */
|
||||
goto relock;
|
||||
}
|
||||
@ -2332,7 +2331,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
|
||||
|
||||
if (sig_kernel_coredump(signr)) {
|
||||
if (print_fatal_signals)
|
||||
print_fatal_signal(info->si_signo);
|
||||
print_fatal_signal(ksig->info.si_signo);
|
||||
proc_coredump_connector(current);
|
||||
/*
|
||||
* If it was able to dump core, this kills all
|
||||
@ -2342,34 +2341,32 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
|
||||
* first and our do_group_exit call below will use
|
||||
* that value and ignore the one we pass it.
|
||||
*/
|
||||
do_coredump(info);
|
||||
do_coredump(&ksig->info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Death signals, no core dump.
|
||||
*/
|
||||
do_group_exit(info->si_signo);
|
||||
do_group_exit(ksig->info.si_signo);
|
||||
/* NOTREACHED */
|
||||
}
|
||||
spin_unlock_irq(&sighand->siglock);
|
||||
return signr;
|
||||
|
||||
ksig->sig = signr;
|
||||
return ksig->sig > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* signal_delivered -
|
||||
* @sig: number of signal being delivered
|
||||
* @info: siginfo_t of signal being delivered
|
||||
* @ka: sigaction setting that chose the handler
|
||||
* @regs: user register state
|
||||
* @ksig: kernel signal struct
|
||||
* @stepping: nonzero if debugger single-step or block-step in use
|
||||
*
|
||||
* This function should be called when a signal has successfully been
|
||||
* delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask
|
||||
* delivered. It updates the blocked signals accordingly (@ksig->ka.sa.sa_mask
|
||||
* is always blocked, and the signal itself is blocked unless %SA_NODEFER
|
||||
* is set in @ka->sa.sa_flags. Tracing is notified.
|
||||
* is set in @ksig->ka.sa.sa_flags. Tracing is notified.
|
||||
*/
|
||||
void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int stepping)
|
||||
static void signal_delivered(struct ksignal *ksig, int stepping)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
@ -2379,11 +2376,11 @@ void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
simply clear the restore sigmask flag. */
|
||||
clear_restore_sigmask();
|
||||
|
||||
sigorsets(&blocked, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&blocked, sig);
|
||||
sigorsets(&blocked, ¤t->blocked, &ksig->ka.sa.sa_mask);
|
||||
if (!(ksig->ka.sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&blocked, ksig->sig);
|
||||
set_current_blocked(&blocked);
|
||||
tracehook_signal_handler(sig, info, ka, regs, stepping);
|
||||
tracehook_signal_handler(stepping);
|
||||
}
|
||||
|
||||
void signal_setup_done(int failed, struct ksignal *ksig, int stepping)
|
||||
@ -2391,8 +2388,7 @@ void signal_setup_done(int failed, struct ksignal *ksig, int stepping)
|
||||
if (failed)
|
||||
force_sigsegv(ksig->sig, current);
|
||||
else
|
||||
signal_delivered(ksig->sig, &ksig->info, &ksig->ka,
|
||||
signal_pt_regs(), stepping);
|
||||
signal_delivered(ksig, stepping);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user