Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull first series of signal handling cleanups from Al Viro: "This is just the first part of the queue (about a half of it); assorted fixes all over the place in signal handling. This one ends with all sigsuspend() implementations switched to generic one (->saved_sigmask-based). With this, a bunch of assorted old buglets are fixed and most of the missing bits of NOTIFY_RESUME hookup are in place. Two more fixes sit in arm and um trees respectively, and there's a couple of broken ones that need obvious fixes - parisc and avr32 check TIF_NOTIFY_RESUME only on one of two codepaths; fixes for that will happen in the next series" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (55 commits) unicore32: if there's no handler we need to restore sigmask, syscall or no syscall xtensa: add handling of TIF_NOTIFY_RESUME microblaze: drop 'oldset' argument of do_notify_resume() microblaze: handle TIF_NOTIFY_RESUME score: add handling of NOTIFY_RESUME to do_notify_resume() m68k: add TIF_NOTIFY_RESUME and handle it. sparc: kill ancient comment in sparc_sigaction() h8300: missing checks of __get_user()/__put_user() return values frv: missing checks of __get_user()/__put_user() return values cris: missing checks of __get_user()/__put_user() return values powerpc: missing checks of __get_user()/__put_user() return values sh: missing checks of __get_user()/__put_user() return values sparc: missing checks of __get_user()/__put_user() return values avr32: struct old_sigaction is never used m32r: struct old_sigaction is never used xtensa: xtensa_sigaction doesn't exist alpha: tidy signal delivery up score: don't open-code force_sigsegv() cris: don't open-code force_sigsegv() blackfin: don't open-code force_sigsegv() ...
This commit is contained in:
commit
f9369910a6
@ -34,9 +34,6 @@
|
|||||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||||
|
|
||||||
asmlinkage void ret_from_sys_call(void);
|
asmlinkage void ret_from_sys_call(void);
|
||||||
static void do_signal(struct pt_regs *, struct switch_stack *,
|
|
||||||
unsigned long, unsigned long);
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The OSF/1 sigprocmask calling sequence is different from the
|
* The OSF/1 sigprocmask calling sequence is different from the
|
||||||
@ -121,17 +118,8 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
|
|||||||
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
|
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
@ -376,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||||||
oldsp = rdusp();
|
oldsp = rdusp();
|
||||||
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
||||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||||
goto give_sigsegv;
|
return -EFAULT;
|
||||||
|
|
||||||
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
|
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
|
||||||
if (err)
|
if (err)
|
||||||
goto give_sigsegv;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Set up to return from userspace. If provided, use a stub
|
/* Set up to return from userspace. If provided, use a stub
|
||||||
already in userspace. */
|
already in userspace. */
|
||||||
@ -396,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||||||
|
|
||||||
/* Check that everything was written properly. */
|
/* Check that everything was written properly. */
|
||||||
if (err)
|
if (err)
|
||||||
goto give_sigsegv;
|
return err;
|
||||||
|
|
||||||
/* "Return" to the handler */
|
/* "Return" to the handler */
|
||||||
regs->r26 = r26;
|
regs->r26 = r26;
|
||||||
@ -410,12 +398,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||||||
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
|
printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
|
||||||
current->comm, current->pid, frame, regs->pc, regs->r26);
|
current->comm, current->pid, frame, regs->pc, regs->r26);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
|
||||||
force_sigsegv(sig, current);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -428,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
oldsp = rdusp();
|
oldsp = rdusp();
|
||||||
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
||||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||||
goto give_sigsegv;
|
return -EFAULT;
|
||||||
|
|
||||||
err |= copy_siginfo_to_user(&frame->info, info);
|
err |= copy_siginfo_to_user(&frame->info, info);
|
||||||
|
|
||||||
@ -443,7 +426,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
set->sig[0], oldsp);
|
set->sig[0], oldsp);
|
||||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||||
if (err)
|
if (err)
|
||||||
goto give_sigsegv;
|
return -EFAULT;
|
||||||
|
|
||||||
/* Set up to return from userspace. If provided, use a stub
|
/* Set up to return from userspace. If provided, use a stub
|
||||||
already in userspace. */
|
already in userspace. */
|
||||||
@ -459,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto give_sigsegv;
|
return -EFAULT;
|
||||||
|
|
||||||
/* "Return" to the handler */
|
/* "Return" to the handler */
|
||||||
regs->r26 = r26;
|
regs->r26 = r26;
|
||||||
@ -475,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
|
||||||
force_sigsegv(sig, current);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OK, we're invoking a handler.
|
* OK, we're invoking a handler.
|
||||||
*/
|
*/
|
||||||
static inline int
|
static inline void
|
||||||
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||||
sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
|
struct pt_regs * regs, struct switch_stack *sw)
|
||||||
{
|
{
|
||||||
|
sigset_t *oldset = ¤t->blocked;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
oldset = ¤t->saved_sigmask;
|
||||||
|
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||||
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
|
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
|
||||||
else
|
else
|
||||||
ret = setup_frame(sig, ka, oldset, regs, sw);
|
ret = setup_frame(sig, ka, oldset, regs, sw);
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret) {
|
||||||
block_sigmask(ka, sig);
|
force_sigsegv(sig, current);
|
||||||
|
return;
|
||||||
return ret;
|
}
|
||||||
|
block_sigmask(ka, sig);
|
||||||
|
/* A signal was successfully delivered, and the
|
||||||
|
saved sigmask was stored on the signal frame,
|
||||||
|
and will be restored by sigreturn. So we can
|
||||||
|
simply clear the restore sigmask flag. */
|
||||||
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
@ -547,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
|
|||||||
int signr;
|
int signr;
|
||||||
unsigned long single_stepping = ptrace_cancel_bpt(current);
|
unsigned long single_stepping = ptrace_cancel_bpt(current);
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
sigset_t *oldset;
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
|
||||||
oldset = ¤t->saved_sigmask;
|
|
||||||
else
|
|
||||||
oldset = ¤t->blocked;
|
|
||||||
|
|
||||||
/* This lets the debugger run, ... */
|
/* This lets the debugger run, ... */
|
||||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||||
@ -564,14 +547,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
|
|||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
if (r0)
|
if (r0)
|
||||||
syscall_restart(r0, r19, regs, &ka);
|
syscall_restart(r0, r19, regs, &ka);
|
||||||
if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
|
handle_signal(signr, &ka, &info, regs, sw);
|
||||||
/* A signal was successfully delivered, and the
|
|
||||||
saved sigmask was stored on the signal frame,
|
|
||||||
and will be restored by sigreturn. So we can
|
|
||||||
simply clear the restore sigmask flag. */
|
|
||||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
|
||||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
}
|
|
||||||
if (single_stepping)
|
if (single_stepping)
|
||||||
ptrace_set_bpt(current); /* re-set bpt */
|
ptrace_set_bpt(current); /* re-set bpt */
|
||||||
return;
|
return;
|
||||||
@ -596,10 +572,8 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no signal to deliver, we just restore the saved mask. */
|
/* If there's no signal to deliver, we just restore the saved mask. */
|
||||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
set_current_blocked(¤t->saved_sigmask);
|
||||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (single_stepping)
|
if (single_stepping)
|
||||||
ptrace_set_bpt(current); /* re-set breakpoint */
|
ptrace_set_bpt(current); /* re-set breakpoint */
|
||||||
@ -610,7 +584,7 @@ do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
|
|||||||
unsigned long thread_info_flags,
|
unsigned long thread_info_flags,
|
||||||
unsigned long r0, unsigned long r19)
|
unsigned long r0, unsigned long r19)
|
||||||
{
|
{
|
||||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
if (thread_info_flags & _TIF_SIGPENDING)
|
||||||
do_signal(regs, sw, r0, r19);
|
do_signal(regs, sw, r0, r19);
|
||||||
|
|
||||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
|
@ -67,17 +67,8 @@ const unsigned long syscall_restart_code[2] = {
|
|||||||
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
|
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
|
@ -115,13 +115,6 @@ typedef unsigned long sigset_t;
|
|||||||
#include <asm-generic/signal-defs.h>
|
#include <asm-generic/signal-defs.h>
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
struct old_sigaction {
|
|
||||||
__sighandler_t sa_handler;
|
|
||||||
old_sigset_t sa_mask;
|
|
||||||
unsigned long sa_flags;
|
|
||||||
__sigrestore_t sa_restorer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sigaction {
|
struct sigaction {
|
||||||
__sighandler_t sa_handler;
|
__sighandler_t sa_handler;
|
||||||
unsigned long sa_flags;
|
unsigned long sa_flags;
|
||||||
|
@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
|||||||
struct rt_sigframe __user *frame;
|
struct rt_sigframe __user *frame;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
frame = (struct rt_sigframe __user *)regs->sp;
|
frame = (struct rt_sigframe __user *)regs->sp;
|
||||||
pr_debug("SIG return: frame = %p\n", frame);
|
pr_debug("SIG return: frame = %p\n", frame);
|
||||||
|
|
||||||
@ -87,10 +90,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -238,22 +238,16 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
*/
|
*/
|
||||||
ret |= !valid_user_regs(regs);
|
ret |= !valid_user_regs(regs);
|
||||||
|
|
||||||
/*
|
if (ret != 0) {
|
||||||
* Block the signal if we were unsuccessful.
|
force_sigsegv(sig, current);
|
||||||
*/
|
return;
|
||||||
if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
sigorsets(¤t->blocked, ¤t->blocked,
|
|
||||||
&ka->sa.sa_mask);
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0)
|
/*
|
||||||
return;
|
* Block the signal if we were successful.
|
||||||
|
*/
|
||||||
force_sigsegv(sig, current);
|
block_sigmask(ka, sig);
|
||||||
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
|
if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -213,9 +210,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
if (sig == SIGSEGV)
|
force_sigsegv(sig, current);
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
|
||||||
force_sig(SIGSEGV, current);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,15 +261,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
|||||||
/* set up the stack frame */
|
/* set up the stack frame */
|
||||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked, ¤t->blocked,
|
|
||||||
&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
|
|||||||
struct rt_sigframe __user *frame;
|
struct rt_sigframe __user *frame;
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
|
||||||
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Since we stacked the signal on a dword boundary,
|
* Since we stacked the signal on a dword boundary,
|
||||||
* 'sp' should be dword aligned here. If it's
|
* 'sp' should be dword aligned here. If it's
|
||||||
|
@ -48,19 +48,11 @@ void do_signal(int canrestart, struct pt_regs *regs);
|
|||||||
* dummy arguments to be able to reach the regs argument. (Note that this
|
* dummy arguments to be able to reach the regs argument. (Note that this
|
||||||
* arrangement relies on old_sigset_t occupying one register.)
|
* arrangement relies on old_sigset_t occupying one register.)
|
||||||
*/
|
*/
|
||||||
int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
|
int sys_sigsuspend(old_sigset_t mask)
|
||||||
long srp, struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
mask &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, mask);
|
||||||
current->saved_sigmask = current->blocked;
|
return sigsuspend(&blocked);
|
||||||
siginitset(¤t->blocked, mask);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
||||||
@ -73,10 +65,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||||||
old_sigset_t mask;
|
old_sigset_t mask;
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka.sa.sa_mask, mask);
|
siginitset(&new_ka.sa.sa_mask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,10 +77,10 @@ int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||||||
if (!ret && oact) {
|
if (!ret && oact) {
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -185,10 +177,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->sc))
|
if (restore_sigcontext(regs, &frame->sc))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -224,10 +213,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -469,15 +455,9 @@ static inline int handle_signal(int canrestart, unsigned long sig,
|
|||||||
else
|
else
|
||||||
ret = setup_frame(sig, ka, oldset, regs);
|
ret = setup_frame(sig, ka, oldset, regs);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked, ¤t->blocked,
|
|
||||||
&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,19 +59,11 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc,
|
|||||||
* dummy arguments to be able to reach the regs argument.
|
* dummy arguments to be able to reach the regs argument.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
|
sys_sigsuspend(old_sigset_t mask)
|
||||||
long srp, struct pt_regs *regs)
|
|
||||||
{
|
{
|
||||||
mask &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, mask);
|
||||||
current->saved_sigmask = current->blocked;
|
return sigsuspend(&blocked);
|
||||||
siginitset(¤t->blocked, mask);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -87,11 +79,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
|
|||||||
|
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(newk.sa.sa_handler, &act->sa_handler) ||
|
__get_user(newk.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(newk.sa.sa_restorer, &act->sa_restorer))
|
__get_user(newk.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(newk.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
__get_user(newk.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&newk.sa.sa_mask, mask);
|
siginitset(&newk.sa.sa_mask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,11 +92,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
|
|||||||
if (!retval && oact) {
|
if (!retval && oact) {
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(oldk.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(oldk.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(oldk.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(oldk.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(oldk.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
__put_user(oldk.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
@ -176,12 +168,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
|
|
||||||
current->blocked = set;
|
|
||||||
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->sc))
|
if (restore_sigcontext(regs, &frame->sc))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -222,12 +209,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
|
|
||||||
current->blocked = set;
|
|
||||||
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -363,10 +345,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
if (sig == SIGSEGV)
|
force_sigsegv(sig, current);
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
|
||||||
|
|
||||||
force_sig(SIGSEGV, current);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -450,10 +429,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
if (sig == SIGSEGV)
|
force_sigsegv(sig, current);
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
|
||||||
|
|
||||||
force_sig(SIGSEGV, current);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,18 +488,8 @@ handle_signal(int canrestart, unsigned long sig,
|
|||||||
else
|
else
|
||||||
ret = setup_frame(sig, ka, oldset, regs);
|
ret = setup_frame(sig, ka, oldset, regs);
|
||||||
|
|
||||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
if (ret == 0)
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
block_sigmask(ka, sig);
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
sigorsets(¤t->blocked, ¤t->blocked,
|
|
||||||
&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -40,17 +40,9 @@ struct fdpic_func_descriptor {
|
|||||||
*/
|
*/
|
||||||
asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
mask &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, mask);
|
||||||
current->saved_sigmask = current->blocked;
|
return sigsuspend(&blocked);
|
||||||
siginitset(¤t->blocked, mask);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int sys_sigaction(int sig,
|
asmlinkage int sys_sigaction(int sig,
|
||||||
@ -64,10 +56,10 @@ asmlinkage int sys_sigaction(int sig,
|
|||||||
old_sigset_t mask;
|
old_sigset_t mask;
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka.sa.sa_mask, mask);
|
siginitset(&new_ka.sa.sa_mask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,10 +68,10 @@ asmlinkage int sys_sigaction(int sig,
|
|||||||
if (!ret && oact) {
|
if (!ret && oact) {
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -158,10 +150,7 @@ asmlinkage int sys_sigreturn(void)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(&frame->sc, &gr8))
|
if (restore_sigcontext(&frame->sc, &gr8))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -184,10 +173,7 @@ asmlinkage int sys_rt_sigreturn(void)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
|
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -474,15 +460,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
|||||||
else
|
else
|
||||||
ret = setup_frame(sig, ka, oldset);
|
ret = setup_frame(sig, ka, oldset);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked, ¤t->blocked,
|
|
||||||
&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -356,6 +356,7 @@
|
|||||||
#define __ARCH_WANT_SYS_SIGPENDING
|
#define __ARCH_WANT_SYS_SIGPENDING
|
||||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||||
|
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Conditional" syscalls
|
* "Conditional" syscalls
|
||||||
|
@ -49,60 +49,15 @@
|
|||||||
|
|
||||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||||
|
|
||||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
* Atomically swap in the new signal mask, and wait for a signal.
|
||||||
*/
|
*/
|
||||||
asmlinkage int do_sigsuspend(struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
old_sigset_t mask = regs->er3;
|
|
||||||
sigset_t saveset;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
saveset = current->blocked;
|
|
||||||
siginitset(¤t->blocked, mask);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
regs->er0 = -EINTR;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
if (do_signal(regs, &saveset))
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
do_rt_sigsuspend(struct pt_regs *regs)
|
sys_sigsuspend(int unused1, int unused2, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
sigset_t *unewset = (sigset_t *)regs->er1;
|
sigset_t blocked;
|
||||||
size_t sigsetsize = (size_t)regs->er2;
|
siginitset(&blocked, mask);
|
||||||
sigset_t saveset, newset;
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
|
||||||
if (sigsetsize != sizeof(sigset_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
|
||||||
return -EFAULT;
|
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
saveset = current->blocked;
|
|
||||||
current->blocked = newset;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
regs->er0 = -EINTR;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
if (do_signal(regs, &saveset))
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
@ -116,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
|
|||||||
old_sigset_t mask;
|
old_sigset_t mask;
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka.sa.sa_mask, mask);
|
siginitset(&new_ka.sa.sa_mask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
|
|||||||
if (!ret && oact) {
|
if (!ret && oact) {
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->sc, &er0))
|
if (restore_sigcontext(regs, &frame->sc, &er0))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -260,10 +212,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -314,7 +263,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
|||||||
return (void *)((usp - frame_size) & -8UL);
|
return (void *)((usp - frame_size) & -8UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_frame (int sig, struct k_sigaction *ka,
|
static int setup_frame (int sig, struct k_sigaction *ka,
|
||||||
sigset_t *set, struct pt_regs *regs)
|
sigset_t *set, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct sigframe *frame;
|
struct sigframe *frame;
|
||||||
@ -375,13 +324,14 @@ static void setup_frame (int sig, struct k_sigaction *ka,
|
|||||||
regs->er1 = (unsigned long)&(frame->sc);
|
regs->er1 = (unsigned long)&(frame->sc);
|
||||||
regs->er5 = current->mm->start_data; /* GOT base */
|
regs->er5 = current->mm->start_data; /* GOT base */
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
force_sigsegv(sig, current);
|
force_sigsegv(sig, current);
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||||
sigset_t *set, struct pt_regs *regs)
|
sigset_t *set, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct rt_sigframe *frame;
|
struct rt_sigframe *frame;
|
||||||
@ -450,10 +400,11 @@ static void setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
regs->er2 = (unsigned long)&frame->uc;
|
regs->er2 = (unsigned long)&frame->uc;
|
||||||
regs->er5 = current->mm->start_data; /* GOT base */
|
regs->er5 = current->mm->start_data; /* GOT base */
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
force_sigsegv(sig, current);
|
force_sigsegv(sig, current);
|
||||||
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -463,6 +414,7 @@ static void
|
|||||||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||||
sigset_t *oldset, struct pt_regs * regs)
|
sigset_t *oldset, struct pt_regs * regs)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
/* are we from a system call? */
|
/* are we from a system call? */
|
||||||
if (regs->orig_er0 >= 0) {
|
if (regs->orig_er0 >= 0) {
|
||||||
switch (regs->er0) {
|
switch (regs->er0) {
|
||||||
@ -485,16 +437,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
|||||||
|
|
||||||
/* set up the stack frame */
|
/* set up the stack frame */
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||||
setup_rt_frame(sig, ka, info, oldset, regs);
|
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||||
else
|
else
|
||||||
setup_frame(sig, ka, oldset, regs);
|
ret = setup_frame(sig, ka, oldset, regs);
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
if (!ret) {
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
block_sigmask(ka, sig);
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
sigaddset(¤t->blocked,sig);
|
}
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -502,11 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
|||||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||||
* mistake.
|
* mistake.
|
||||||
*/
|
*/
|
||||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
statis void do_signal(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
|
sigset_t *oldset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want the common case to go fast, which
|
* We want the common case to go fast, which
|
||||||
@ -515,21 +466,23 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||||||
* if so.
|
* if so.
|
||||||
*/
|
*/
|
||||||
if ((regs->ccr & 0x10))
|
if ((regs->ccr & 0x10))
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
if (try_to_freeze())
|
if (try_to_freeze())
|
||||||
goto no_signal;
|
goto no_signal;
|
||||||
|
|
||||||
current->thread.esp0 = (unsigned long) regs;
|
current->thread.esp0 = (unsigned long) regs;
|
||||||
|
|
||||||
if (!oldset)
|
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
oldset = ¤t->saved_sigmask;
|
||||||
|
else
|
||||||
oldset = ¤t->blocked;
|
oldset = ¤t->blocked;
|
||||||
|
|
||||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||||
if (signr > 0) {
|
if (signr > 0) {
|
||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
handle_signal(signr, &info, &ka, oldset, regs);
|
handle_signal(signr, &info, &ka, oldset, regs);
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
no_signal:
|
no_signal:
|
||||||
/* Did we come from a system call? */
|
/* Did we come from a system call? */
|
||||||
@ -546,13 +499,16 @@ asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||||||
regs->pc -= 2;
|
regs->pc -= 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
/* If there's no signal to deliver, we just restore the saved mask. */
|
||||||
|
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
set_current_blocked(¤t->saved_sigmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
|
asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
|
||||||
{
|
{
|
||||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
if (thread_info_flags & _TIF_SIGPENDING)
|
||||||
do_signal(regs, NULL);
|
do_signal(regs);
|
||||||
|
|
||||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
|
@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table)
|
|||||||
SYMBOL_NAME_LABEL(sys_clone)
|
SYMBOL_NAME_LABEL(sys_clone)
|
||||||
call_sp h8300_clone
|
call_sp h8300_clone
|
||||||
|
|
||||||
SYMBOL_NAME_LABEL(sys_sigsuspend)
|
|
||||||
call_sp do_sigsuspend
|
|
||||||
|
|
||||||
SYMBOL_NAME_LABEL(sys_rt_sigsuspend)
|
|
||||||
call_sp do_rt_sigsuspend
|
|
||||||
|
|
||||||
SYMBOL_NAME_LABEL(sys_sigreturn)
|
SYMBOL_NAME_LABEL(sys_sigreturn)
|
||||||
call_sp do_sigreturn
|
call_sp do_sigreturn
|
||||||
|
|
||||||
|
@ -272,6 +272,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
|
|||||||
|
|
||||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
|
tracehook_notify_resume(regs);
|
||||||
if (current->replacement_session_keyring)
|
if (current->replacement_session_keyring)
|
||||||
key_replace_session_keyring();
|
key_replace_session_keyring();
|
||||||
}
|
}
|
||||||
@ -293,6 +294,9 @@ asmlinkage int sys_rt_sigreturn(void)
|
|||||||
struct rt_sigframe __user *frame;
|
struct rt_sigframe __user *frame;
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
frame = (struct rt_sigframe __user *)pt_psp(regs);
|
frame = (struct rt_sigframe __user *)pt_psp(regs);
|
||||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
@ -201,13 +201,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
|
|||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
|
set_current_blocked(&set);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
{
|
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
}
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(sc, scr))
|
if (restore_sigcontext(sc, scr))
|
||||||
goto give_sigsegv;
|
goto give_sigsegv;
|
||||||
@ -427,12 +421,7 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse
|
|||||||
if (!setup_frame(sig, ka, info, oldset, scr))
|
if (!setup_frame(sig, ka, info, oldset, scr))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Let tracing know that we've done the handler setup.
|
* Let tracing know that we've done the handler setup.
|
||||||
|
@ -110,13 +110,6 @@ typedef unsigned long sigset_t;
|
|||||||
#include <asm-generic/signal-defs.h>
|
#include <asm-generic/signal-defs.h>
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
struct old_sigaction {
|
|
||||||
__sighandler_t sa_handler;
|
|
||||||
old_sigset_t sa_mask;
|
|
||||||
unsigned long sa_flags;
|
|
||||||
__sigrestore_t sa_restorer;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sigaction {
|
struct sigaction {
|
||||||
__sighandler_t sa_handler;
|
__sighandler_t sa_handler;
|
||||||
unsigned long sa_flags;
|
unsigned long sa_flags;
|
||||||
|
@ -112,10 +112,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -300,12 +297,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
if (setup_rt_frame(sig, ka, info, oldset, regs))
|
if (setup_rt_frame(sig, ka, info, oldset, regs))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked,sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ static inline struct thread_info *current_thread_info(void)
|
|||||||
* bits 0-7 are tested at every exception exit
|
* bits 0-7 are tested at every exception exit
|
||||||
* bits 8-15 are also tested at syscall exit
|
* bits 8-15 are also tested at syscall exit
|
||||||
*/
|
*/
|
||||||
|
#define TIF_NOTIFY_RESUME 5 /* callback before returning to user */
|
||||||
#define TIF_SIGPENDING 6 /* signal pending */
|
#define TIF_SIGPENDING 6 /* signal pending */
|
||||||
#define TIF_NEED_RESCHED 7 /* rescheduling necessary */
|
#define TIF_NEED_RESCHED 7 /* rescheduling necessary */
|
||||||
#define TIF_DELAYED_TRACE 14 /* single step a syscall */
|
#define TIF_DELAYED_TRACE 14 /* single step a syscall */
|
||||||
|
@ -148,7 +148,7 @@ syscall_exit_work:
|
|||||||
jcs do_trace_exit
|
jcs do_trace_exit
|
||||||
jmi do_delayed_trace
|
jmi do_delayed_trace
|
||||||
lslw #8,%d0
|
lslw #8,%d0
|
||||||
jmi do_signal_return
|
jne do_signal_return
|
||||||
pea resume_userspace
|
pea resume_userspace
|
||||||
jra schedule
|
jra schedule
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ exit_work:
|
|||||||
| save top of frame
|
| save top of frame
|
||||||
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
||||||
lslb #1,%d0
|
lslb #1,%d0
|
||||||
jmi do_signal_return
|
jne do_signal_return
|
||||||
pea resume_userspace
|
pea resume_userspace
|
||||||
jra schedule
|
jra schedule
|
||||||
|
|
||||||
@ -182,7 +182,7 @@ do_signal_return:
|
|||||||
subql #4,%sp | dummy return address
|
subql #4,%sp | dummy return address
|
||||||
SAVE_SWITCH_STACK
|
SAVE_SWITCH_STACK
|
||||||
pea %sp@(SWITCH_STACK_SIZE)
|
pea %sp@(SWITCH_STACK_SIZE)
|
||||||
bsrl do_signal
|
bsrl do_notify_resume
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
RESTORE_SWITCH_STACK
|
RESTORE_SWITCH_STACK
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include <linux/tty.h>
|
#include <linux/tty.h>
|
||||||
#include <linux/binfmts.h>
|
#include <linux/binfmts.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
|
|
||||||
#include <asm/setup.h>
|
#include <asm/setup.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -230,18 +231,9 @@ static inline void push_cache(unsigned long vaddr)
|
|||||||
asmlinkage int
|
asmlinkage int
|
||||||
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
|
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
mask &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, mask);
|
||||||
current->saved_sigmask = current->blocked;
|
return sigsuspend(&blocked);
|
||||||
siginitset(¤t->blocked, mask);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
@ -804,8 +796,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
current->blocked = set;
|
set_current_blocked(&set);
|
||||||
recalc_sigpending();
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->sc, frame + 1))
|
if (restore_sigcontext(regs, &frame->sc, frame + 1))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -830,8 +821,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
current->blocked = set;
|
set_current_blocked(&set);
|
||||||
recalc_sigpending();
|
|
||||||
|
|
||||||
if (rt_restore_ucontext(regs, sw, &frame->uc))
|
if (rt_restore_ucontext(regs, sw, &frame->uc))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -1150,10 +1140,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
if (err)
|
if (err)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
block_sigmask(ka, sig);
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked,sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
|
|
||||||
if (test_thread_flag(TIF_DELAYED_TRACE)) {
|
if (test_thread_flag(TIF_DELAYED_TRACE)) {
|
||||||
regs->sr &= ~0x8000;
|
regs->sr &= ~0x8000;
|
||||||
@ -1168,7 +1155,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
* want to handle. Thus you cannot kill init even with a SIGKILL even by
|
||||||
* mistake.
|
* mistake.
|
||||||
*/
|
*/
|
||||||
asmlinkage void do_signal(struct pt_regs *regs)
|
static void do_signal(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
@ -1200,3 +1187,15 @@ asmlinkage void do_signal(struct pt_regs *regs)
|
|||||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_notify_resume(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (test_thread_flag(TIF_SIGPENDING))
|
||||||
|
do_signal(regs);
|
||||||
|
|
||||||
|
if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
|
||||||
|
tracehook_notify_resume(regs);
|
||||||
|
if (current->replacement_session_keyring)
|
||||||
|
key_replace_session_keyring();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -119,7 +119,7 @@ Lsignal_return:
|
|||||||
subql #4,%sp /* dummy return address*/
|
subql #4,%sp /* dummy return address*/
|
||||||
SAVE_SWITCH_STACK
|
SAVE_SWITCH_STACK
|
||||||
pea %sp@(SWITCH_STACK_SIZE)
|
pea %sp@(SWITCH_STACK_SIZE)
|
||||||
bsrw do_signal
|
bsrw do_notify_resume
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
RESTORE_SWITCH_STACK
|
RESTORE_SWITCH_STACK
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
|
@ -115,7 +115,7 @@ Lsignal_return:
|
|||||||
subql #4,%sp /* dummy return address*/
|
subql #4,%sp /* dummy return address*/
|
||||||
SAVE_SWITCH_STACK
|
SAVE_SWITCH_STACK
|
||||||
pea %sp@(SWITCH_STACK_SIZE)
|
pea %sp@(SWITCH_STACK_SIZE)
|
||||||
bsrw do_signal
|
bsrw do_notify_resume
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
RESTORE_SWITCH_STACK
|
RESTORE_SWITCH_STACK
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
|
@ -152,7 +152,7 @@ Lsignal_return:
|
|||||||
subql #4,%sp /* dummy return address */
|
subql #4,%sp /* dummy return address */
|
||||||
SAVE_SWITCH_STACK
|
SAVE_SWITCH_STACK
|
||||||
pea %sp@(SWITCH_STACK_SIZE)
|
pea %sp@(SWITCH_STACK_SIZE)
|
||||||
jsr do_signal
|
jsr do_notify_resume
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
RESTORE_SWITCH_STACK
|
RESTORE_SWITCH_STACK
|
||||||
addql #4,%sp
|
addql #4,%sp
|
||||||
|
@ -132,11 +132,10 @@ ret_from_intr:
|
|||||||
beqi r11, 1f
|
beqi r11, 1f
|
||||||
bralid r15, schedule
|
bralid r15, schedule
|
||||||
nop
|
nop
|
||||||
1: andi r11, r19, _TIF_SIGPENDING
|
1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||||
beqid r11, no_intr_resched
|
beqid r11, no_intr_resched
|
||||||
addk r5, r1, r0
|
addk r5, r1, r0
|
||||||
addk r7, r0, r0
|
bralid r15, do_notify_resume
|
||||||
bralid r15, do_signal
|
|
||||||
addk r6, r0, r0
|
addk r6, r0, r0
|
||||||
|
|
||||||
no_intr_resched:
|
no_intr_resched:
|
||||||
@ -292,8 +291,8 @@ ENTRY(_user_exception)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Debug traps are like a system call, but entered via brki r14, 0x60
|
* Debug traps are like a system call, but entered via brki r14, 0x60
|
||||||
* All we need to do is send the SIGTRAP signal to current, ptrace and do_signal
|
* All we need to do is send the SIGTRAP signal to current, ptrace and
|
||||||
* will handle the rest
|
* do_notify_resume will handle the rest
|
||||||
*/
|
*/
|
||||||
ENTRY(_debug_exception)
|
ENTRY(_debug_exception)
|
||||||
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
|
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
|
||||||
@ -482,12 +481,11 @@ work_pending:
|
|||||||
beqi r11, 1f
|
beqi r11, 1f
|
||||||
bralid r15, schedule
|
bralid r15, schedule
|
||||||
nop
|
nop
|
||||||
1: andi r11, r19, _TIF_SIGPENDING
|
1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||||
beqi r11, no_work_pending
|
beqi r11, no_work_pending
|
||||||
addk r5, r1, r0
|
addk r5, r1, r0
|
||||||
addik r7, r0, 1
|
bralid r15, do_notify_resume
|
||||||
bralid r15, do_signal
|
addik r6, r0, 1
|
||||||
addk r6, r0, r0
|
|
||||||
bri no_work_pending
|
bri no_work_pending
|
||||||
|
|
||||||
ENTRY(ret_to_user)
|
ENTRY(ret_to_user)
|
||||||
@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper:
|
|||||||
brid sys_rt_sigreturn
|
brid sys_rt_sigreturn
|
||||||
addk r5, r1, r0
|
addk r5, r1, r0
|
||||||
|
|
||||||
sys_rt_sigsuspend_wrapper:
|
|
||||||
brid sys_rt_sigsuspend
|
|
||||||
addk r7, r1, r0
|
|
||||||
|
|
||||||
/* Interrupt vector table */
|
/* Interrupt vector table */
|
||||||
.section .init.ivt, "ax"
|
.section .init.ivt, "ax"
|
||||||
.org 0x0
|
.org 0x0
|
||||||
|
@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap):
|
|||||||
5: /* get thread info from current task*/
|
5: /* get thread info from current task*/
|
||||||
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
|
lwi r11, CURRENT_TASK, TS_THREAD_INFO;
|
||||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||||
andi r11, r11, _TIF_SIGPENDING;
|
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||||
beqi r11, 1f; /* Signals to handle, handle them */
|
beqi r11, 1f; /* Signals to handle, handle them */
|
||||||
|
|
||||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||||
addi r7, r0, 1; /* Arg 3: int in_syscall */
|
bralid r15, do_notify_resume; /* Handle any signals */
|
||||||
bralid r15, do_signal; /* Handle any signals */
|
addi r6, r0, 1; /* Arg 2: int in_syscall */
|
||||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
|
||||||
|
|
||||||
/* Finally, return to user state. */
|
/* Finally, return to user state. */
|
||||||
1: set_bip; /* Ints masked for state restore */
|
1: set_bip; /* Ints masked for state restore */
|
||||||
@ -622,7 +621,7 @@ C_ENTRY(ret_from_exc):
|
|||||||
/* Maybe handle a signal */
|
/* Maybe handle a signal */
|
||||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
||||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||||
andi r11, r11, _TIF_SIGPENDING;
|
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||||
beqi r11, 1f; /* Signals to handle, handle them */
|
beqi r11, 1f; /* Signals to handle, handle them */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -635,11 +634,10 @@ C_ENTRY(ret_from_exc):
|
|||||||
* traps), but signal handlers may want to examine or change the
|
* traps), but signal handlers may want to examine or change the
|
||||||
* complete register state. Here we save anything not saved by
|
* complete register state. Here we save anything not saved by
|
||||||
* the normal entry sequence, so that it may be safely restored
|
* the normal entry sequence, so that it may be safely restored
|
||||||
* (in a possibly modified form) after do_signal returns. */
|
* (in a possibly modified form) after do_notify_resume returns. */
|
||||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||||
addi r7, r0, 0; /* Arg 3: int in_syscall */
|
bralid r15, do_notify_resume; /* Handle any signals */
|
||||||
bralid r15, do_signal; /* Handle any signals */
|
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
|
||||||
|
|
||||||
/* Finally, return to user state. */
|
/* Finally, return to user state. */
|
||||||
1: set_bip; /* Ints masked for state restore */
|
1: set_bip; /* Ints masked for state restore */
|
||||||
@ -732,13 +730,12 @@ ret_from_irq:
|
|||||||
/* Maybe handle a signal */
|
/* Maybe handle a signal */
|
||||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
|
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get thread info */
|
||||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||||
andi r11, r11, _TIF_SIGPENDING;
|
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||||
beqid r11, no_intr_resched
|
beqid r11, no_intr_resched
|
||||||
/* Handle a signal return; Pending signals should be in r18. */
|
/* Handle a signal return; Pending signals should be in r18. */
|
||||||
addi r7, r0, 0; /* Arg 3: int in_syscall */
|
|
||||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||||
bralid r15, do_signal; /* Handle any signals */
|
bralid r15, do_notify_resume; /* Handle any signals */
|
||||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||||
|
|
||||||
/* Finally, return to user state. */
|
/* Finally, return to user state. */
|
||||||
no_intr_resched:
|
no_intr_resched:
|
||||||
@ -869,13 +866,12 @@ dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
|
|||||||
/* Maybe handle a signal */
|
/* Maybe handle a signal */
|
||||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get thread info */
|
||||||
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
lwi r11, r11, TI_FLAGS; /* get flags in thread info */
|
||||||
andi r11, r11, _TIF_SIGPENDING;
|
andi r11, r11, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME;
|
||||||
beqi r11, 1f; /* Signals to handle, handle them */
|
beqi r11, 1f; /* Signals to handle, handle them */
|
||||||
|
|
||||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||||
addi r7, r0, 0; /* Arg 3: int in_syscall */
|
bralid r15, do_notify_resume; /* Handle any signals */
|
||||||
bralid r15, do_signal; /* Handle any signals */
|
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
|
||||||
|
|
||||||
/* Finally, return to user state. */
|
/* Finally, return to user state. */
|
||||||
1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include <linux/personality.h>
|
#include <linux/personality.h>
|
||||||
#include <linux/percpu.h>
|
#include <linux/percpu.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
#include <asm/entry.h>
|
#include <asm/entry.h>
|
||||||
#include <asm/ucontext.h>
|
#include <asm/ucontext.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
@ -42,8 +43,6 @@
|
|||||||
|
|
||||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||||
|
|
||||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
|
|
||||||
|
|
||||||
asmlinkage long
|
asmlinkage long
|
||||||
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
@ -98,6 +97,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
|
|||||||
sigset_t set;
|
sigset_t set;
|
||||||
int rval;
|
int rval;
|
||||||
|
|
||||||
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
@ -105,10 +107,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
|
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -169,7 +168,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
|
|||||||
return (void __user *)((sp - frame_size) & -8UL);
|
return (void __user *)((sp - frame_size) & -8UL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||||
sigset_t *set, struct pt_regs *regs)
|
sigset_t *set, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
struct rt_sigframe __user *frame;
|
struct rt_sigframe __user *frame;
|
||||||
@ -267,12 +266,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
current->comm, current->pid, frame, regs->pc);
|
current->comm, current->pid, frame, regs->pc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
if (sig == SIGSEGV)
|
force_sigsegv(sig, current);
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
return -EFAULT;
|
||||||
force_sig(SIGSEGV, current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle restarting system calls */
|
/* Handle restarting system calls */
|
||||||
@ -316,24 +314,20 @@ static int
|
|||||||
handle_signal(unsigned long sig, struct k_sigaction *ka,
|
handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||||
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
/* Set up the stack frame */
|
/* Set up the stack frame */
|
||||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||||
setup_rt_frame(sig, ka, info, oldset, regs);
|
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||||
else
|
else
|
||||||
setup_rt_frame(sig, ka, NULL, oldset, regs);
|
ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
|
||||||
|
|
||||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
if (ret)
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
return ret;
|
||||||
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER)) {
|
block_sigmask(ka, sig);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
|
||||||
sigorsets(¤t->blocked,
|
return 0;
|
||||||
¤t->blocked, &ka->sa.sa_mask);
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -345,24 +339,17 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
|||||||
* the kernel can handle, and then we build all the user-level signal handling
|
* the kernel can handle, and then we build all the user-level signal handling
|
||||||
* stack-frames in one go after that.
|
* stack-frames in one go after that.
|
||||||
*/
|
*/
|
||||||
int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
|
static void do_signal(struct pt_regs *regs, int in_syscall)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
|
sigset_t *oldset;
|
||||||
#ifdef DEBUG_SIG
|
#ifdef DEBUG_SIG
|
||||||
printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall);
|
printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall);
|
||||||
printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
|
printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
|
||||||
regs->r12, current_thread_info()->flags);
|
regs->r12, current_thread_info()->flags);
|
||||||
#endif
|
#endif
|
||||||
/*
|
|
||||||
* We want the common case to go fast, which
|
|
||||||
* is why we may in certain cases get here from
|
|
||||||
* kernel mode. Just return without doing anything
|
|
||||||
* if so.
|
|
||||||
*/
|
|
||||||
if (kernel_mode(regs))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||||
oldset = ¤t->saved_sigmask;
|
oldset = ¤t->saved_sigmask;
|
||||||
@ -374,7 +361,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
|
|||||||
/* Whee! Actually deliver the signal. */
|
/* Whee! Actually deliver the signal. */
|
||||||
if (in_syscall)
|
if (in_syscall)
|
||||||
handle_restart(regs, &ka, 1);
|
handle_restart(regs, &ka, 1);
|
||||||
if (handle_signal(signr, &ka, &info, oldset, regs)) {
|
if (!handle_signal(signr, &ka, &info, oldset, regs)) {
|
||||||
/*
|
/*
|
||||||
* A signal was successfully delivered; the saved
|
* A signal was successfully delivered; the saved
|
||||||
* sigmask will have been stored in the signal frame,
|
* sigmask will have been stored in the signal frame,
|
||||||
@ -384,7 +371,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
|
|||||||
current_thread_info()->status &=
|
current_thread_info()->status &=
|
||||||
~TS_RESTORE_SIGMASK;
|
~TS_RESTORE_SIGMASK;
|
||||||
}
|
}
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_syscall)
|
if (in_syscall)
|
||||||
@ -398,7 +385,25 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
|
|||||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/* Did we come from a system call? */
|
|
||||||
return 0;
|
void do_notify_resume(struct pt_regs *regs, int in_syscall)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* We want the common case to go fast, which
|
||||||
|
* is why we may in certain cases get here from
|
||||||
|
* kernel mode. Just return without doing anything
|
||||||
|
* if so.
|
||||||
|
*/
|
||||||
|
if (kernel_mode(regs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (test_thread_flag(TIF_SIGPENDING))
|
||||||
|
do_signal(regs, in_syscall);
|
||||||
|
|
||||||
|
if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
|
||||||
|
tracehook_notify_resume(regs);
|
||||||
|
if (current->replacement_session_keyring)
|
||||||
|
key_replace_session_keyring();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,15 +255,7 @@ asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||||||
uset = (sigset_t __user *) regs.regs[4];
|
uset = (sigset_t __user *) regs.regs[4];
|
||||||
if (copy_from_user(&newset, uset, sizeof(sigset_t)))
|
if (copy_from_user(&newset, uset, sizeof(sigset_t)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -281,15 +273,7 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||||||
unewset = (sigset_t __user *) regs.regs[4];
|
unewset = (sigset_t __user *) regs.regs[4];
|
||||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_TRAD_SIGNALS
|
#ifdef CONFIG_TRAD_SIGNALS
|
||||||
|
@ -288,15 +288,7 @@ asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||||||
uset = (compat_sigset_t __user *) regs.regs[4];
|
uset = (compat_sigset_t __user *) regs.regs[4];
|
||||||
if (get_sigset(&newset, uset))
|
if (get_sigset(&newset, uset))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||||
@ -313,15 +305,7 @@ asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||||||
uset = (compat_sigset_t __user *) regs.regs[4];
|
uset = (compat_sigset_t __user *) regs.regs[4];
|
||||||
if (get_sigset(&newset, uset))
|
if (get_sigset(&newset, uset))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
|
SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
|
||||||
|
@ -91,15 +91,7 @@ asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||||||
if (copy_from_user(&uset, unewset, sizeof(uset)))
|
if (copy_from_user(&uset, unewset, sizeof(uset)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigset_from_compat(&newset, &uset);
|
sigset_from_compat(&newset, &uset);
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||||
|
@ -38,17 +38,9 @@
|
|||||||
*/
|
*/
|
||||||
asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
asmlinkage long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
mask &= _BLOCKABLE;
|
sigset_t blocked;
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
siginitset(&blocked, mask);
|
||||||
current->saved_sigmask = current->blocked;
|
return sigsuspend(&blocked);
|
||||||
siginitset(¤t->blocked, mask);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -172,10 +164,7 @@ asmlinkage long sys_sigreturn(void)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(current_frame(), &frame->sc, &d0))
|
if (restore_sigcontext(current_frame(), &frame->sc, &d0))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -203,10 +192,7 @@ asmlinkage long sys_rt_sigreturn(void)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
|
if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -476,15 +462,8 @@ static int handle_signal(int sig,
|
|||||||
else
|
else
|
||||||
ret = setup_frame(sig, ka, oldset, regs);
|
ret = setup_frame(sig, ka, oldset, regs);
|
||||||
|
|
||||||
if (ret == 0) {
|
if (ret == 0)
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked, ¤t->blocked,
|
|
||||||
&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -109,6 +109,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
|||||||
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
|
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
/* Unwind the user stack to get the rt_sigframe structure. */
|
/* Unwind the user stack to get the rt_sigframe structure. */
|
||||||
frame = (struct rt_sigframe __user *)
|
frame = (struct rt_sigframe __user *)
|
||||||
@ -131,10 +132,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
/* Good thing we saved the old gr[30], eh? */
|
/* Good thing we saved the old gr[30], eh? */
|
||||||
#ifdef CONFIG_64BIT
|
#ifdef CONFIG_64BIT
|
||||||
@ -454,12 +452,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
|||||||
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
|
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
block_sigmask(ka, sig);
|
||||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked,sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
tracehook_signal_handler(sig, info, ka, regs,
|
tracehook_signal_handler(sig, info, ka, regs,
|
||||||
test_thread_flag(TIF_SINGLESTEP) ||
|
test_thread_flag(TIF_SINGLESTEP) ||
|
||||||
@ -474,8 +467,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
|||||||
/* Check the return code */
|
/* Check the return code */
|
||||||
switch (regs->gr[28]) {
|
switch (regs->gr[28]) {
|
||||||
case -ERESTART_RESTARTBLOCK:
|
case -ERESTART_RESTARTBLOCK:
|
||||||
current_thread_info()->restart_block.fn =
|
|
||||||
do_no_restart_syscall;
|
|
||||||
case -ERESTARTNOHAND:
|
case -ERESTARTNOHAND:
|
||||||
DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
|
DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
|
||||||
regs->gr[28] = -EINTR;
|
regs->gr[28] = -EINTR;
|
||||||
|
@ -204,10 +204,10 @@ static inline int get_old_sigaction(struct k_sigaction *new_ka,
|
|||||||
|
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka->sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka->sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka->sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka->sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka->sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka->sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka->sa.sa_mask, mask);
|
siginitset(&new_ka->sa.sa_mask, mask);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -244,17 +244,8 @@ static inline int restore_general_regs(struct pt_regs *regs,
|
|||||||
long sys_sigsuspend(old_sigset_t mask)
|
long sys_sigsuspend(old_sigset_t mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long sys_sigaction(int sig, struct old_sigaction __user *act,
|
long sys_sigaction(int sig, struct old_sigaction __user *act,
|
||||||
|
@ -59,15 +59,8 @@ typedef struct
|
|||||||
SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
|
SYSCALL_DEFINE3(sigsuspend, int, history0, int, history1, old_sigset_t, mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
set_current_state(TASK_INTERRUPTIBLE);
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act,
|
SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act,
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/syscalls.h>
|
#include <asm/syscalls.h>
|
||||||
@ -152,6 +153,9 @@ score_rt_sigreturn(struct pt_regs *regs)
|
|||||||
stack_t st;
|
stack_t st;
|
||||||
int sig;
|
int sig;
|
||||||
|
|
||||||
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
frame = (struct rt_sigframe __user *) regs->regs[0];
|
frame = (struct rt_sigframe __user *) regs->regs[0];
|
||||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||||
goto badframe;
|
goto badframe;
|
||||||
@ -159,10 +163,7 @@ score_rt_sigreturn(struct pt_regs *regs)
|
|||||||
goto badframe;
|
goto badframe;
|
||||||
|
|
||||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
set_current_blocked(&set);
|
||||||
current->blocked = set;
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
|
sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
|
||||||
if (sig < 0)
|
if (sig < 0)
|
||||||
@ -236,9 +237,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
give_sigsegv:
|
give_sigsegv:
|
||||||
if (signr == SIGSEGV)
|
force_sigsegv(signr, current);
|
||||||
ka->sa.sa_handler = SIG_DFL;
|
|
||||||
force_sig(SIGSEGV, current);
|
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,12 +271,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
|||||||
*/
|
*/
|
||||||
ret = setup_rt_frame(ka, regs, sig, oldset, info);
|
ret = setup_rt_frame(ka, regs, sig, oldset, info);
|
||||||
|
|
||||||
spin_lock_irq(¤t->sighand->siglock);
|
if (ret == 0)
|
||||||
sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask);
|
block_sigmask(ka, sig);
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(¤t->blocked, sig);
|
|
||||||
recalc_sigpending();
|
|
||||||
spin_unlock_irq(¤t->sighand->siglock);
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -356,6 +351,12 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
|
|||||||
__u32 thread_info_flags)
|
__u32 thread_info_flags)
|
||||||
{
|
{
|
||||||
/* deal with pending signal delivery */
|
/* deal with pending signal delivery */
|
||||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
if (thread_info_flags & _TIF_SIGPENDING)
|
||||||
do_signal(regs);
|
do_signal(regs);
|
||||||
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
|
tracehook_notify_resume(regs);
|
||||||
|
if (current->replacement_session_keyring)
|
||||||
|
key_replace_session_keyring();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,7 @@ asmlinkage int sys_execve(const char __user *ufilename,
|
|||||||
const char __user *const __user *uargv,
|
const char __user *const __user *uargv,
|
||||||
const char __user *const __user *uenvp,
|
const char __user *const __user *uenvp,
|
||||||
unsigned long r7, struct pt_regs __regs);
|
unsigned long r7, struct pt_regs __regs);
|
||||||
asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
|
asmlinkage int sys_sigsuspend(old_sigset_t mask);
|
||||||
unsigned long r6, unsigned long r7,
|
|
||||||
struct pt_regs __regs);
|
|
||||||
asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
||||||
struct old_sigaction __user *oact);
|
struct old_sigaction __user *oact);
|
||||||
asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
# ifdef CONFIG_SUPERH32
|
# ifdef CONFIG_SUPERH32
|
||||||
|
|
||||||
# include "unistd_32.h"
|
# include "unistd_32.h"
|
||||||
# define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
|
||||||
|
|
||||||
# else
|
# else
|
||||||
# include "unistd_64.h"
|
# include "unistd_64.h"
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
# define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
# define __ARCH_WANT_IPC_PARSE_VERSION
|
# define __ARCH_WANT_IPC_PARSE_VERSION
|
||||||
# define __ARCH_WANT_OLD_READDIR
|
# define __ARCH_WANT_OLD_READDIR
|
||||||
# define __ARCH_WANT_OLD_STAT
|
# define __ARCH_WANT_OLD_STAT
|
||||||
|
@ -53,23 +53,11 @@ struct fdpic_func_descriptor {
|
|||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
* Atomically swap in the new signal mask, and wait for a signal.
|
||||||
*/
|
*/
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
sys_sigsuspend(old_sigset_t mask,
|
sys_sigsuspend(old_sigset_t mask)
|
||||||
unsigned long r5, unsigned long r6, unsigned long r7,
|
|
||||||
struct pt_regs __regs)
|
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
@ -83,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||||||
old_sigset_t mask;
|
old_sigset_t mask;
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka.sa.sa_mask, mask);
|
siginitset(&new_ka.sa.sa_mask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,10 +83,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||||||
if (!ret && oact) {
|
if (!ret && oact) {
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -162,12 +150,11 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
|
|||||||
if (!(boot_cpu_data.flags & CPU_HAS_FPU))
|
if (!(boot_cpu_data.flags & CPU_HAS_FPU))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!used_math()) {
|
if (!used_math())
|
||||||
__put_user(0, &sc->sc_ownedfp);
|
return __put_user(0, &sc->sc_ownedfp);
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__put_user(1, &sc->sc_ownedfp);
|
if (__put_user(1, &sc->sc_ownedfp))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
/* This will cause a "finit" to be triggered by the next
|
/* This will cause a "finit" to be triggered by the next
|
||||||
attempted FPU operation by the 'current' process.
|
attempted FPU operation by the 'current' process.
|
||||||
@ -207,7 +194,7 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p
|
|||||||
regs->sr |= SR_FD; /* Release FPU */
|
regs->sr |= SR_FD; /* Release FPU */
|
||||||
clear_fpu(tsk, regs);
|
clear_fpu(tsk, regs);
|
||||||
clear_used_math();
|
clear_used_math();
|
||||||
__get_user (owned_fp, &sc->sc_ownedfp);
|
err |= __get_user (owned_fp, &sc->sc_ownedfp);
|
||||||
if (owned_fp)
|
if (owned_fp)
|
||||||
err |= restore_sigcontext_fpu(sc);
|
err |= restore_sigcontext_fpu(sc);
|
||||||
}
|
}
|
||||||
@ -398,11 +385,14 @@ static int setup_frame(int sig, struct k_sigaction *ka,
|
|||||||
struct fdpic_func_descriptor __user *funcptr =
|
struct fdpic_func_descriptor __user *funcptr =
|
||||||
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
|
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
|
||||||
|
|
||||||
__get_user(regs->pc, &funcptr->text);
|
err |= __get_user(regs->pc, &funcptr->text);
|
||||||
__get_user(regs->regs[12], &funcptr->GOT);
|
err |= __get_user(regs->regs[12], &funcptr->GOT);
|
||||||
} else
|
} else
|
||||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto give_sigsegv;
|
||||||
|
|
||||||
set_fs(USER_DS);
|
set_fs(USER_DS);
|
||||||
|
|
||||||
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
||||||
@ -482,11 +472,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||||||
struct fdpic_func_descriptor __user *funcptr =
|
struct fdpic_func_descriptor __user *funcptr =
|
||||||
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
|
(struct fdpic_func_descriptor __user *)ka->sa.sa_handler;
|
||||||
|
|
||||||
__get_user(regs->pc, &funcptr->text);
|
err |= __get_user(regs->pc, &funcptr->text);
|
||||||
__get_user(regs->regs[12], &funcptr->GOT);
|
err |= __get_user(regs->regs[12], &funcptr->GOT);
|
||||||
} else
|
} else
|
||||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto give_sigsegv;
|
||||||
|
|
||||||
set_fs(USER_DS);
|
set_fs(USER_DS);
|
||||||
|
|
||||||
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n",
|
||||||
|
@ -83,11 +83,12 @@ handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
|
|||||||
* the kernel can handle, and then we build all the user-level signal handling
|
* the kernel can handle, and then we build all the user-level signal handling
|
||||||
* stack-frames in one go after that.
|
* stack-frames in one go after that.
|
||||||
*/
|
*/
|
||||||
static int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
static void do_signal(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
|
sigset_t *oldset;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want the common case to go fast, which
|
* We want the common case to go fast, which
|
||||||
@ -96,11 +97,11 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||||||
* if so.
|
* if so.
|
||||||
*/
|
*/
|
||||||
if (!user_mode(regs))
|
if (!user_mode(regs))
|
||||||
return 1;
|
return;
|
||||||
|
|
||||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||||
oldset = ¤t->saved_sigmask;
|
oldset = ¤t->saved_sigmask;
|
||||||
else if (!oldset)
|
else
|
||||||
oldset = ¤t->blocked;
|
oldset = ¤t->blocked;
|
||||||
|
|
||||||
signr = get_signal_to_deliver(&info, &ka, regs, 0);
|
signr = get_signal_to_deliver(&info, &ka, regs, 0);
|
||||||
@ -118,7 +119,7 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||||||
|
|
||||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||||
test_thread_flag(TIF_SINGLESTEP));
|
test_thread_flag(TIF_SINGLESTEP));
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,71 +148,18 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
* Atomically swap in the new signal mask, and wait for a signal.
|
||||||
*/
|
*/
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
sys_sigsuspend(old_sigset_t mask,
|
sys_sigsuspend(old_sigset_t mask)
|
||||||
unsigned long r3, unsigned long r4, unsigned long r5,
|
|
||||||
unsigned long r6, unsigned long r7,
|
|
||||||
struct pt_regs * regs)
|
|
||||||
{
|
{
|
||||||
sigset_t saveset, blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
saveset = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
REF_REG_RET = -EINTR;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
regs->pc += 4; /* because sys_sigreturn decrements the pc */
|
|
||||||
if (do_signal(regs, &saveset)) {
|
|
||||||
/* pc now points at signal handler. Need to decrement
|
|
||||||
it because entry.S will increment it. */
|
|
||||||
regs->pc -= 4;
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage int
|
|
||||||
sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize,
|
|
||||||
unsigned long r4, unsigned long r5, unsigned long r6,
|
|
||||||
unsigned long r7,
|
|
||||||
struct pt_regs * regs)
|
|
||||||
{
|
|
||||||
sigset_t saveset, newset;
|
|
||||||
|
|
||||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
|
||||||
if (sigsetsize != sizeof(sigset_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
|
||||||
return -EFAULT;
|
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
||||||
saveset = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
REF_REG_RET = -EINTR;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
regs->pc += 4; /* because sys_sigreturn decrements the pc */
|
|
||||||
if (do_signal(regs, &saveset)) {
|
|
||||||
/* pc now points at signal handler. Need to decrement
|
|
||||||
it because entry.S will increment it. */
|
|
||||||
regs->pc -= 4;
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
@ -225,10 +173,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||||||
old_sigset_t mask;
|
old_sigset_t mask;
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka.sa.sa_mask, mask);
|
siginitset(&new_ka.sa.sa_mask, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,10 +185,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||||||
if (!ret && oact) {
|
if (!ret && oact) {
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@ -732,7 +680,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
|||||||
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
|
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
|
||||||
{
|
{
|
||||||
if (thread_info_flags & _TIF_SIGPENDING)
|
if (thread_info_flags & _TIF_SIGPENDING)
|
||||||
do_signal(regs, 0);
|
do_signal(regs);
|
||||||
|
|
||||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||||
|
@ -215,8 +215,9 @@ void do_sigreturn32(struct pt_regs *regs)
|
|||||||
(((unsigned long) sf) & 3))
|
(((unsigned long) sf) & 3))
|
||||||
goto segv;
|
goto segv;
|
||||||
|
|
||||||
get_user(pc, &sf->info.si_regs.pc);
|
if (get_user(pc, &sf->info.si_regs.pc) ||
|
||||||
__get_user(npc, &sf->info.si_regs.npc);
|
__get_user(npc, &sf->info.si_regs.npc))
|
||||||
|
goto segv;
|
||||||
|
|
||||||
if ((pc | npc) & 3)
|
if ((pc | npc) & 3)
|
||||||
goto segv;
|
goto segv;
|
||||||
@ -305,8 +306,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
|||||||
(((unsigned long) sf) & 3))
|
(((unsigned long) sf) & 3))
|
||||||
goto segv;
|
goto segv;
|
||||||
|
|
||||||
get_user(pc, &sf->regs.pc);
|
if (get_user(pc, &sf->regs.pc) ||
|
||||||
__get_user(npc, &sf->regs.npc);
|
__get_user(npc, &sf->regs.npc))
|
||||||
|
goto segv;
|
||||||
|
|
||||||
if ((pc | npc) & 3)
|
if ((pc | npc) & 3)
|
||||||
goto segv;
|
goto segv;
|
||||||
|
@ -64,18 +64,8 @@ struct rt_signal_frame {
|
|||||||
static int _sigpause_common(old_sigset_t set)
|
static int _sigpause_common(old_sigset_t set)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
set &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, set);
|
siginitset(&blocked, set);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int sys_sigsuspend(old_sigset_t set)
|
asmlinkage int sys_sigsuspend(old_sigset_t set)
|
||||||
|
@ -242,19 +242,8 @@ struct rt_signal_frame {
|
|||||||
static long _sigpause_common(old_sigset_t set)
|
static long _sigpause_common(old_sigset_t set)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
set &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, set);
|
siginitset(&blocked, set);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
|
|
||||||
set_restore_sigmask();
|
|
||||||
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage long sys_sigpause(unsigned int set)
|
asmlinkage long sys_sigpause(unsigned int set)
|
||||||
|
@ -184,10 +184,10 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
|
|||||||
|
|
||||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
|
||||||
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
|
__get_user(new_ka.sa.sa_restorer, &act->sa_restorer) ||
|
||||||
|
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
|
||||||
|
__get_user(mask, &act->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
|
||||||
__get_user(mask, &act->sa_mask);
|
|
||||||
siginitset(&new_ka.sa.sa_mask, mask);
|
siginitset(&new_ka.sa.sa_mask, mask);
|
||||||
new_ka.ka_restorer = NULL;
|
new_ka.ka_restorer = NULL;
|
||||||
}
|
}
|
||||||
@ -195,17 +195,12 @@ sparc_sigaction (int sig, const struct old_sigaction __user *act,
|
|||||||
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
|
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
|
||||||
|
|
||||||
if (!ret && oact) {
|
if (!ret && oact) {
|
||||||
/* In the clone() case we could copy half consistent
|
|
||||||
* state to the user, however this could sleep and
|
|
||||||
* deadlock us if we held the signal lock on SMP. So for
|
|
||||||
* now I take the easy way out and do no locking.
|
|
||||||
*/
|
|
||||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
|
||||||
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
|
__put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) ||
|
||||||
|
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
|
||||||
|
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
|
||||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -148,15 +148,8 @@ int do_signal(void)
|
|||||||
long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
|
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
|
||||||
|
@ -370,10 +370,7 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
|
|||||||
/*
|
/*
|
||||||
* Block the signal if we were successful.
|
* Block the signal if we were successful.
|
||||||
*/
|
*/
|
||||||
sigorsets(&blocked, &tsk->blocked, &ka->sa.sa_mask);
|
block_sigmask(ka, sig);
|
||||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
|
||||||
sigaddset(&blocked, sig);
|
|
||||||
set_current_blocked(&blocked);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -450,15 +447,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|||||||
regs->UCreg_00 == -ERESTARTNOINTR) {
|
regs->UCreg_00 == -ERESTARTNOINTR) {
|
||||||
setup_syscall_restart(regs);
|
setup_syscall_restart(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no signal to deliver, we just put the saved
|
|
||||||
* sigmask back.
|
|
||||||
*/
|
|
||||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
|
||||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
|
||||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
/* If there's no signal to deliver, we just put the saved
|
||||||
|
* sigmask back.
|
||||||
|
*/
|
||||||
|
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
set_current_blocked(¤t->saved_sigmask);
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage void do_notify_resume(struct pt_regs *regs,
|
asmlinkage void do_notify_resume(struct pt_regs *regs,
|
||||||
|
@ -131,18 +131,8 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
|
|||||||
asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
|
asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
|
asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
|
||||||
|
@ -478,18 +478,8 @@ asmlinkage int
|
|||||||
sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||||
{
|
{
|
||||||
sigset_t blocked;
|
sigset_t blocked;
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
|
|
||||||
mask &= _BLOCKABLE;
|
|
||||||
siginitset(&blocked, mask);
|
siginitset(&blocked, mask);
|
||||||
set_current_blocked(&blocked);
|
return sigsuspend(&blocked);
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
asmlinkage int
|
asmlinkage int
|
||||||
|
@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int);
|
|||||||
#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
|
#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
|
||||||
|
|
||||||
#ifdef __KERNEL__
|
#ifdef __KERNEL__
|
||||||
struct old_sigaction {
|
|
||||||
__sighandler_t sa_handler;
|
|
||||||
old_sigset_t sa_mask;
|
|
||||||
unsigned long sa_flags;
|
|
||||||
void (*sa_restorer)(void);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sigaction {
|
struct sigaction {
|
||||||
__sighandler_t sa_handler;
|
__sighandler_t sa_handler;
|
||||||
unsigned long sa_flags;
|
unsigned long sa_flags;
|
||||||
|
@ -15,10 +15,6 @@ asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);
|
|||||||
asmlinkage long xtensa_ptrace(long, long, long, long);
|
asmlinkage long xtensa_ptrace(long, long, long, long);
|
||||||
asmlinkage long xtensa_sigreturn(struct pt_regs*);
|
asmlinkage long xtensa_sigreturn(struct pt_regs*);
|
||||||
asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
|
asmlinkage long xtensa_rt_sigreturn(struct pt_regs*);
|
||||||
asmlinkage long xtensa_sigsuspend(struct pt_regs*);
|
|
||||||
asmlinkage long xtensa_rt_sigsuspend(struct pt_regs*);
|
|
||||||
asmlinkage long xtensa_sigaction(int, const struct old_sigaction*,
|
|
||||||
struct old_sigaction*);
|
|
||||||
asmlinkage long xtensa_sigaltstack(struct pt_regs *regs);
|
asmlinkage long xtensa_sigaltstack(struct pt_regs *regs);
|
||||||
asmlinkage long sys_rt_sigaction(int,
|
asmlinkage long sys_rt_sigaction(int,
|
||||||
const struct sigaction __user *,
|
const struct sigaction __user *,
|
||||||
|
@ -131,6 +131,7 @@ static inline struct thread_info *current_thread_info(void)
|
|||||||
#define TIF_IRET 4 /* return with iret */
|
#define TIF_IRET 4 /* return with iret */
|
||||||
#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
|
#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
|
||||||
#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
|
#define TIF_RESTORE_SIGMASK 6 /* restore signal mask in do_signal() */
|
||||||
|
#define TIF_NOTIFY_RESUME 7 /* callback before returning to user */
|
||||||
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||||
|
|
||||||
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
||||||
|
@ -507,7 +507,7 @@ __SYSCALL(229, sys_rt_sigtimedwait, 4)
|
|||||||
#define __NR_rt_sigqueueinfo 230
|
#define __NR_rt_sigqueueinfo 230
|
||||||
__SYSCALL(230, sys_rt_sigqueueinfo, 3)
|
__SYSCALL(230, sys_rt_sigqueueinfo, 3)
|
||||||
#define __NR_rt_sigsuspend 231
|
#define __NR_rt_sigsuspend 231
|
||||||
__SYSCALL(231, xtensa_rt_sigsuspend, 2)
|
__SYSCALL(231, sys_rt_sigsuspend, 2)
|
||||||
|
|
||||||
/* Message */
|
/* Message */
|
||||||
|
|
||||||
|
@ -409,16 +409,16 @@ common_exception_return:
|
|||||||
l32i a4, a2, TI_FLAGS
|
l32i a4, a2, TI_FLAGS
|
||||||
|
|
||||||
_bbsi.l a4, TIF_NEED_RESCHED, 3f
|
_bbsi.l a4, TIF_NEED_RESCHED, 3f
|
||||||
|
_bbsi.l a4, TIF_NOTIFY_RESUME, 2f
|
||||||
_bbci.l a4, TIF_SIGPENDING, 4f
|
_bbci.l a4, TIF_SIGPENDING, 4f
|
||||||
|
|
||||||
l32i a4, a1, PT_DEPC
|
2: l32i a4, a1, PT_DEPC
|
||||||
bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
|
bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
|
||||||
|
|
||||||
/* Call do_signal() */
|
/* Call do_signal() */
|
||||||
|
|
||||||
movi a4, do_signal # int do_signal(struct pt_regs*, sigset_t*)
|
movi a4, do_notify_resume # int do_notify_resume(struct pt_regs*)
|
||||||
mov a6, a1
|
mov a6, a1
|
||||||
movi a7, 0
|
|
||||||
callx4 a4
|
callx4 a4
|
||||||
j 1b
|
j 1b
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include <linux/ptrace.h>
|
#include <linux/ptrace.h>
|
||||||
#include <linux/personality.h>
|
#include <linux/personality.h>
|
||||||
#include <linux/freezer.h>
|
#include <linux/freezer.h>
|
||||||
|
#include <linux/tracehook.h>
|
||||||
|
|
||||||
#include <asm/ucontext.h>
|
#include <asm/ucontext.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
@ -31,8 +32,6 @@
|
|||||||
|
|
||||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||||
|
|
||||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
|
|
||||||
|
|
||||||
extern struct task_struct *coproc_owners[];
|
extern struct task_struct *coproc_owners[];
|
||||||
|
|
||||||
struct rt_sigframe
|
struct rt_sigframe
|
||||||
@ -248,6 +247,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
|
|||||||
sigset_t set;
|
sigset_t set;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Always make any pending restarted system calls return -EINTR */
|
||||||
|
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||||
|
|
||||||
if (regs->depc > 64)
|
if (regs->depc > 64)
|
||||||
panic("rt_sigreturn in double exception!\n");
|
panic("rt_sigreturn in double exception!\n");
|
||||||
|
|
||||||
@ -426,37 +428,6 @@ give_sigsegv:
|
|||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Atomically swap in the new signal mask, and wait for a signal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset,
|
|
||||||
size_t sigsetsize,
|
|
||||||
long a2, long a3, long a4, long a5,
|
|
||||||
struct pt_regs *regs)
|
|
||||||
{
|
|
||||||
sigset_t saveset, newset;
|
|
||||||
|
|
||||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
|
||||||
if (sigsetsize != sizeof(sigset_t))
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
|
||||||
saveset = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
regs->areg[2] = -EINTR;
|
|
||||||
while (1) {
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
if (do_signal(regs, &saveset))
|
|
||||||
return -EINTR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
|
asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
|
||||||
stack_t __user *uoss,
|
stack_t __user *uoss,
|
||||||
long a2, long a3, long a4, long a5,
|
long a2, long a3, long a4, long a5,
|
||||||
@ -476,19 +447,19 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss,
|
|||||||
* the kernel can handle, and then we build all the user-level signal handling
|
* the kernel can handle, and then we build all the user-level signal handling
|
||||||
* stack-frames in one go after that.
|
* stack-frames in one go after that.
|
||||||
*/
|
*/
|
||||||
int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
static void do_signal(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
int signr;
|
int signr;
|
||||||
struct k_sigaction ka;
|
struct k_sigaction ka;
|
||||||
|
sigset_t oldset;
|
||||||
if (!user_mode(regs))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (try_to_freeze())
|
if (try_to_freeze())
|
||||||
goto no_signal;
|
goto no_signal;
|
||||||
|
|
||||||
if (!oldset)
|
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
oldset = ¤t->saved_sigmask;
|
||||||
|
else
|
||||||
oldset = ¤t->blocked;
|
oldset = ¤t->blocked;
|
||||||
|
|
||||||
task_pt_regs(current)->icountlevel = 0;
|
task_pt_regs(current)->icountlevel = 0;
|
||||||
@ -532,13 +503,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
|||||||
/* Set up the stack frame */
|
/* Set up the stack frame */
|
||||||
ret = setup_frame(signr, &ka, &info, oldset, regs);
|
ret = setup_frame(signr, &ka, &info, oldset, regs);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return;
|
||||||
|
|
||||||
|
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||||
block_sigmask(&ka, signr);
|
block_sigmask(&ka, signr);
|
||||||
if (current->ptrace & PT_SINGLESTEP)
|
if (current->ptrace & PT_SINGLESTEP)
|
||||||
task_pt_regs(current)->icountlevel = 1;
|
task_pt_regs(current)->icountlevel = 1;
|
||||||
|
|
||||||
return 1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
no_signal:
|
no_signal:
|
||||||
@ -558,8 +530,27 @@ no_signal:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If there's no signal to deliver, we just restore the saved mask. */
|
||||||
|
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||||
|
set_current_blocked(¤t->saved_sigmask);
|
||||||
|
|
||||||
if (current->ptrace & PT_SINGLESTEP)
|
if (current->ptrace & PT_SINGLESTEP)
|
||||||
task_pt_regs(current)->icountlevel = 1;
|
task_pt_regs(current)->icountlevel = 1;
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void do_notify_resume(struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
if (!user_mode(regs))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (test_thread_flag(TIF_SIGPENDING))
|
||||||
|
do_signal(regs);
|
||||||
|
|
||||||
|
if (test_and_clear_thread_flag(TIF_NOTIFY_RESUME)) {
|
||||||
|
tracehook_notify_resume(regs);
|
||||||
|
if (current->replacement_session_keyring)
|
||||||
|
key_replace_session_keyring();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -252,6 +252,7 @@ extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
|
|||||||
extern int sigprocmask(int, sigset_t *, sigset_t *);
|
extern int sigprocmask(int, sigset_t *, sigset_t *);
|
||||||
extern void set_current_blocked(const sigset_t *);
|
extern void set_current_blocked(const sigset_t *);
|
||||||
extern int show_unhandled_signals;
|
extern int show_unhandled_signals;
|
||||||
|
extern int sigsuspend(sigset_t *);
|
||||||
|
|
||||||
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
|
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
|
||||||
extern void block_sigmask(struct k_sigaction *ka, int signr);
|
extern void block_sigmask(struct k_sigaction *ka, int signr);
|
||||||
|
@ -1073,15 +1073,7 @@ asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat
|
|||||||
if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
|
if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigset_from_compat(&newset, &newset32);
|
sigset_from_compat(&newset, &newset32);
|
||||||
sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
|
#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
|
||||||
|
|
||||||
|
@ -3232,6 +3232,21 @@ SYSCALL_DEFINE0(pause)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||||
|
int sigsuspend(sigset_t *set)
|
||||||
|
{
|
||||||
|
sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||||
|
|
||||||
|
current->saved_sigmask = current->blocked;
|
||||||
|
set_current_blocked(set);
|
||||||
|
|
||||||
|
current->state = TASK_INTERRUPTIBLE;
|
||||||
|
schedule();
|
||||||
|
set_restore_sigmask();
|
||||||
|
return -ERESTARTNOHAND;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
|
#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||||
/**
|
/**
|
||||||
* sys_rt_sigsuspend - replace the signal mask for a value with the
|
* sys_rt_sigsuspend - replace the signal mask for a value with the
|
||||||
@ -3249,15 +3264,7 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)
|
|||||||
|
|
||||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
return sigsuspend(&newset);
|
||||||
|
|
||||||
current->saved_sigmask = current->blocked;
|
|
||||||
set_current_blocked(&newset);
|
|
||||||
|
|
||||||
current->state = TASK_INTERRUPTIBLE;
|
|
||||||
schedule();
|
|
||||||
set_restore_sigmask();
|
|
||||||
return -ERESTARTNOHAND;
|
|
||||||
}
|
}
|
||||||
#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
|
#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user