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:
Коммит
f9369910a6
|
@ -34,9 +34,6 @@
|
|||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
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
|
||||
|
@ -121,17 +118,8 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, const struct sigaction __user *, act,
|
|||
SYSCALL_DEFINE1(sigsuspend, old_sigset_t, mask)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
@ -376,11 +364,11 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||
oldsp = rdusp();
|
||||
frame = get_sigframe(ka, oldsp, 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);
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
|
@ -396,7 +384,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||
|
||||
/* Check that everything was written properly. */
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return err;
|
||||
|
||||
/* "Return" to the handler */
|
||||
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",
|
||||
current->comm, current->pid, frame, regs->pc, regs->r26);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -428,7 +411,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
oldsp = rdusp();
|
||||
frame = get_sigframe(ka, oldsp, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
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);
|
||||
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up to return from userspace. If provided, use a stub
|
||||
already in userspace. */
|
||||
|
@ -459,7 +442,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
}
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* "Return" to the handler */
|
||||
regs->r26 = r26;
|
||||
|
@ -475,31 +458,37 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
#endif
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* OK, we're invoking a handler.
|
||||
*/
|
||||
static inline int
|
||||
static inline void
|
||||
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;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs, sw);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
if (ret) {
|
||||
force_sigsegv(sig, current);
|
||||
return;
|
||||
}
|
||||
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
|
||||
|
@ -547,12 +536,6 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
|
|||
int signr;
|
||||
unsigned long single_stepping = ptrace_cancel_bpt(current);
|
||||
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, ... */
|
||||
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. */
|
||||
if (r0)
|
||||
syscall_restart(r0, r19, regs, &ka);
|
||||
if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
|
||||
/* 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);
|
||||
}
|
||||
handle_signal(signr, &ka, &info, regs, sw);
|
||||
if (single_stepping)
|
||||
ptrace_set_bpt(current); /* re-set bpt */
|
||||
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 (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
|
||||
if (single_stepping)
|
||||
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 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);
|
||||
|
||||
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)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
|
|
@ -115,13 +115,6 @@ typedef unsigned long sigset_t;
|
|||
#include <asm-generic/signal-defs.h>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct old_sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
old_sigset_t sa_mask;
|
||||
unsigned long sa_flags;
|
||||
__sigrestore_t sa_restorer;
|
||||
};
|
||||
|
||||
struct sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
unsigned long sa_flags;
|
||||
|
|
|
@ -77,6 +77,9 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
|||
struct rt_sigframe __user *frame;
|
||||
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;
|
||||
pr_debug("SIG return: frame = %p\n", frame);
|
||||
|
||||
|
@ -87,10 +90,7 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
goto badframe;
|
||||
|
@ -238,22 +238,16 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
*/
|
||||
ret |= !valid_user_regs(regs);
|
||||
|
||||
/*
|
||||
* Block the signal if we were unsuccessful.
|
||||
*/
|
||||
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) {
|
||||
force_sigsegv(sig, current);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
return;
|
||||
|
||||
force_sigsegv(sig, current);
|
||||
/*
|
||||
* Block the signal if we were successful.
|
||||
*/
|
||||
block_sigmask(ka, sig);
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -99,10 +99,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
|
||||
goto badframe;
|
||||
|
@ -213,9 +210,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
|
|||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
force_sig(SIGSEGV, current);
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -266,15 +261,9 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
|||
/* set up the stack frame */
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
|
||||
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);
|
||||
}
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
|
|||
struct rt_sigframe __user *frame;
|
||||
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,
|
||||
* '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
|
||||
* arrangement relies on old_sigset_t occupying one register.)
|
||||
*/
|
||||
int sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
|
||||
long srp, struct pt_regs *regs)
|
||||
int sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->saved_sigmask = current->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;
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
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;
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__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;
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_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 (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||
__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;
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -185,10 +177,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->sc))
|
||||
goto badframe;
|
||||
|
@ -224,10 +213,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
goto badframe;
|
||||
|
@ -469,15 +455,9 @@ static inline int handle_signal(int canrestart, unsigned long sig,
|
|||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
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);
|
||||
}
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
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.
|
||||
*/
|
||||
int
|
||||
sys_sigsuspend(old_sigset_t mask, long r11, long r12, long r13, long mof,
|
||||
long srp, struct pt_regs *regs)
|
||||
sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->saved_sigmask = current->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;
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -87,11 +79,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
|
|||
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__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;
|
||||
|
||||
__get_user(newk.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_mask);
|
||||
siginitset(&newk.sa.sa_mask, mask);
|
||||
}
|
||||
|
||||
|
@ -100,11 +92,11 @@ sys_sigaction(int signal, const struct old_sigaction *act,
|
|||
if (!retval && oact) {
|
||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||
__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;
|
||||
|
||||
__put_user(oldk.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(oldk.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return retval;
|
||||
|
@ -176,12 +168,7 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
|
||||
current->blocked = set;
|
||||
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->sc))
|
||||
goto badframe;
|
||||
|
@ -222,12 +209,7 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
|
||||
current->blocked = set;
|
||||
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
goto badframe;
|
||||
|
@ -363,10 +345,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
|
|||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -450,10 +429,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
force_sig(SIGSEGV, current);
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
@ -512,18 +488,8 @@ handle_signal(int canrestart, unsigned long sig,
|
|||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
|
||||
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);
|
||||
}
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -40,17 +40,9 @@ struct fdpic_func_descriptor {
|
|||
*/
|
||||
asmlinkage int sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||
{
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->saved_sigmask = current->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;
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int sys_sigaction(int sig,
|
||||
|
@ -64,10 +56,10 @@ asmlinkage int sys_sigaction(int sig,
|
|||
old_sigset_t mask;
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__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;
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_mask);
|
||||
siginitset(&new_ka.sa.sa_mask, mask);
|
||||
}
|
||||
|
||||
|
@ -76,10 +68,10 @@ asmlinkage int sys_sigaction(int sig,
|
|||
if (!ret && 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_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;
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -158,10 +150,7 @@ asmlinkage int sys_sigreturn(void)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(&frame->sc, &gr8))
|
||||
goto badframe;
|
||||
|
@ -184,10 +173,7 @@ asmlinkage int sys_rt_sigreturn(void)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
|
||||
goto badframe;
|
||||
|
@ -474,15 +460,8 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
|||
else
|
||||
ret = setup_frame(sig, ka, oldset);
|
||||
|
||||
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);
|
||||
}
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
|
||||
|
|
|
@ -356,6 +356,7 @@
|
|||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
|
||||
/*
|
||||
* "Conditional" syscalls
|
||||
|
|
|
@ -49,60 +49,15 @@
|
|||
|
||||
#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.
|
||||
*/
|
||||
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
|
||||
do_rt_sigsuspend(struct pt_regs *regs)
|
||||
sys_sigsuspend(int unused1, int unused2, old_sigset_t mask)
|
||||
{
|
||||
sigset_t *unewset = (sigset_t *)regs->er1;
|
||||
size_t sigsetsize = (size_t)regs->er2;
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
@ -116,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction *act,
|
|||
old_sigset_t mask;
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__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;
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_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 (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||
__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;
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->sc, &er0))
|
||||
goto badframe;
|
||||
|
@ -260,10 +212,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct sigframe *frame;
|
||||
|
@ -375,13 +324,14 @@ static void setup_frame (int sig, struct k_sigaction *ka,
|
|||
regs->er1 = (unsigned long)&(frame->sc);
|
||||
regs->er5 = current->mm->start_data; /* GOT base */
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
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)
|
||||
{
|
||||
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->er5 = current->mm->start_data; /* GOT base */
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -463,6 +414,7 @@ static void
|
|||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
sigset_t *oldset, struct pt_regs * regs)
|
||||
{
|
||||
int ret;
|
||||
/* are we from a system call? */
|
||||
if (regs->orig_er0 >= 0) {
|
||||
switch (regs->er0) {
|
||||
|
@ -485,16 +437,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
|||
|
||||
/* set up the stack frame */
|
||||
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
|
||||
setup_frame(sig, ka, oldset, regs);
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
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);
|
||||
if (!ret) {
|
||||
block_sigmask(ka, sig);
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
* mistake.
|
||||
*/
|
||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset)
|
||||
statis void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* 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 ((regs->ccr & 0x10))
|
||||
return 1;
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
current->thread.esp0 = (unsigned long) regs;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, oldset, regs);
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
no_signal:
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
do_signal(regs, NULL);
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(regs);
|
||||
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
|
|
|
@ -343,12 +343,6 @@ SYMBOL_NAME_LABEL(sys_call_table)
|
|||
SYMBOL_NAME_LABEL(sys_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)
|
||||
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) {
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
tracehook_notify_resume(regs);
|
||||
if (current->replacement_session_keyring)
|
||||
key_replace_session_keyring();
|
||||
}
|
||||
|
@ -293,6 +294,9 @@ asmlinkage int sys_rt_sigreturn(void)
|
|||
struct rt_sigframe __user *frame;
|
||||
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);
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
|
|
|
@ -201,13 +201,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
|
|||
goto give_sigsegv;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
{
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
}
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(sc, scr))
|
||||
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))
|
||||
return 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);
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct old_sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
old_sigset_t sa_mask;
|
||||
unsigned long sa_flags;
|
||||
__sigrestore_t sa_restorer;
|
||||
};
|
||||
|
||||
struct sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
unsigned long sa_flags;
|
||||
|
|
|
@ -112,10 +112,7 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
|
||||
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))
|
||||
return -EFAULT;
|
||||
|
||||
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);
|
||||
block_sigmask(ka, sig);
|
||||
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 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_NEED_RESCHED 7 /* rescheduling necessary */
|
||||
#define TIF_DELAYED_TRACE 14 /* single step a syscall */
|
||||
|
|
|
@ -148,7 +148,7 @@ syscall_exit_work:
|
|||
jcs do_trace_exit
|
||||
jmi do_delayed_trace
|
||||
lslw #8,%d0
|
||||
jmi do_signal_return
|
||||
jne do_signal_return
|
||||
pea resume_userspace
|
||||
jra schedule
|
||||
|
||||
|
@ -172,7 +172,7 @@ exit_work:
|
|||
| save top of frame
|
||||
movel %sp,%curptr@(TASK_THREAD+THREAD_ESP0)
|
||||
lslb #1,%d0
|
||||
jmi do_signal_return
|
||||
jne do_signal_return
|
||||
pea resume_userspace
|
||||
jra schedule
|
||||
|
||||
|
@ -182,7 +182,7 @@ do_signal_return:
|
|||
subql #4,%sp | dummy return address
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
bsrl do_signal
|
||||
bsrl do_notify_resume
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <linux/tty.h>
|
||||
#include <linux/binfmts.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/tracehook.h>
|
||||
|
||||
#include <asm/setup.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -230,18 +231,9 @@ static inline void push_cache(unsigned long vaddr)
|
|||
asmlinkage int
|
||||
sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
|
||||
{
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->saved_sigmask = current->blocked;
|
||||
siginitset(¤t->blocked, mask);
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
|
||||
return -ERESTARTNOHAND;
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
@ -804,8 +796,7 @@ asmlinkage int do_sigreturn(unsigned long __unused)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->sc, frame + 1))
|
||||
goto badframe;
|
||||
|
@ -830,8 +821,7 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (rt_restore_ucontext(regs, sw, &frame->uc))
|
||||
goto badframe;
|
||||
|
@ -1150,10 +1140,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
|||
if (err)
|
||||
return;
|
||||
|
||||
sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(¤t->blocked,sig);
|
||||
recalc_sigpending();
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
if (test_thread_flag(TIF_DELAYED_TRACE)) {
|
||||
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
|
||||
* mistake.
|
||||
*/
|
||||
asmlinkage void do_signal(struct pt_regs *regs)
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
|
@ -1200,3 +1187,15 @@ asmlinkage void do_signal(struct pt_regs *regs)
|
|||
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*/
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
bsrw do_signal
|
||||
bsrw do_notify_resume
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
|
|
|
@ -115,7 +115,7 @@ Lsignal_return:
|
|||
subql #4,%sp /* dummy return address*/
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
bsrw do_signal
|
||||
bsrw do_notify_resume
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
|
|
|
@ -152,7 +152,7 @@ Lsignal_return:
|
|||
subql #4,%sp /* dummy return address */
|
||||
SAVE_SWITCH_STACK
|
||||
pea %sp@(SWITCH_STACK_SIZE)
|
||||
jsr do_signal
|
||||
jsr do_notify_resume
|
||||
addql #4,%sp
|
||||
RESTORE_SWITCH_STACK
|
||||
addql #4,%sp
|
||||
|
|
|
@ -132,11 +132,10 @@ ret_from_intr:
|
|||
beqi r11, 1f
|
||||
bralid r15, schedule
|
||||
nop
|
||||
1: andi r11, r19, _TIF_SIGPENDING
|
||||
1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||
beqid r11, no_intr_resched
|
||||
addk r5, r1, r0
|
||||
addk r7, r0, r0
|
||||
bralid r15, do_signal
|
||||
bralid r15, do_notify_resume
|
||||
addk r6, r0, r0
|
||||
|
||||
no_intr_resched:
|
||||
|
@ -292,8 +291,8 @@ ENTRY(_user_exception)
|
|||
|
||||
/*
|
||||
* 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
|
||||
* will handle the rest
|
||||
* All we need to do is send the SIGTRAP signal to current, ptrace and
|
||||
* do_notify_resume will handle the rest
|
||||
*/
|
||||
ENTRY(_debug_exception)
|
||||
swi r1, r0, PER_CPU(ENTRY_SP) /* save the current sp */
|
||||
|
@ -482,12 +481,11 @@ work_pending:
|
|||
beqi r11, 1f
|
||||
bralid r15, schedule
|
||||
nop
|
||||
1: andi r11, r19, _TIF_SIGPENDING
|
||||
1: andi r11, r19, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||
beqi r11, no_work_pending
|
||||
addk r5, r1, r0
|
||||
addik r7, r0, 1
|
||||
bralid r15, do_signal
|
||||
addk r6, r0, r0
|
||||
bralid r15, do_notify_resume
|
||||
addik r6, r0, 1
|
||||
bri no_work_pending
|
||||
|
||||
ENTRY(ret_to_user)
|
||||
|
@ -569,10 +567,6 @@ sys_rt_sigreturn_wrapper:
|
|||
brid sys_rt_sigreturn
|
||||
addk r5, r1, r0
|
||||
|
||||
sys_rt_sigsuspend_wrapper:
|
||||
brid sys_rt_sigsuspend
|
||||
addk r7, r1, r0
|
||||
|
||||
/* Interrupt vector table */
|
||||
.section .init.ivt, "ax"
|
||||
.org 0x0
|
||||
|
|
|
@ -430,13 +430,12 @@ C_ENTRY(ret_from_trap):
|
|||
5: /* get thread info from current task*/
|
||||
lwi r11, CURRENT_TASK, TS_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 */
|
||||
|
||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||
addi r7, r0, 1; /* Arg 3: int in_syscall */
|
||||
bralid r15, do_signal; /* Handle any signals */
|
||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 1; /* Arg 2: int in_syscall */
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: set_bip; /* Ints masked for state restore */
|
||||
|
@ -622,7 +621,7 @@ C_ENTRY(ret_from_exc):
|
|||
/* Maybe handle a signal */
|
||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get 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 */
|
||||
|
||||
/*
|
||||
|
@ -635,11 +634,10 @@ C_ENTRY(ret_from_exc):
|
|||
* traps), but signal handlers may want to examine or change the
|
||||
* complete register state. Here we save anything not saved by
|
||||
* 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 */
|
||||
addi r7, r0, 0; /* Arg 3: int in_syscall */
|
||||
bralid r15, do_signal; /* Handle any signals */
|
||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: set_bip; /* Ints masked for state restore */
|
||||
|
@ -732,13 +730,12 @@ ret_from_irq:
|
|||
/* Maybe handle a signal */
|
||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* MS: get 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
|
||||
/* 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 */
|
||||
bralid r15, do_signal; /* Handle any signals */
|
||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||
|
||||
/* Finally, return to user state. */
|
||||
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 */
|
||||
5: lwi r11, CURRENT_TASK, TS_THREAD_INFO; /* get 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 */
|
||||
|
||||
addik r5, r1, 0; /* Arg 1: struct pt_regs *regs */
|
||||
addi r7, r0, 0; /* Arg 3: int in_syscall */
|
||||
bralid r15, do_signal; /* Handle any signals */
|
||||
add r6, r0, r0; /* Arg 2: sigset_t *oldset */
|
||||
bralid r15, do_notify_resume; /* Handle any signals */
|
||||
addi r6, r0, 0; /* Arg 2: int in_syscall */
|
||||
|
||||
/* Finally, return to user state. */
|
||||
1: swi CURRENT_TASK, r0, PER_CPU(CURRENT_SAVE); /* save current */
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/personality.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/linkage.h>
|
||||
#include <linux/tracehook.h>
|
||||
#include <asm/entry.h>
|
||||
#include <asm/ucontext.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
@ -42,8 +43,6 @@
|
|||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
|
||||
|
||||
asmlinkage long
|
||||
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||
struct pt_regs *regs)
|
||||
|
@ -98,6 +97,9 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
|
|||
sigset_t set;
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
|
@ -105,10 +107,7 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
#endif
|
||||
|
||||
return;
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
if (sig == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
force_sig(SIGSEGV, current);
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
/* Handle restarting system calls */
|
||||
|
@ -316,24 +314,20 @@ static int
|
|||
handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Set up the stack frame */
|
||||
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
|
||||
setup_rt_frame(sig, ka, NULL, oldset, regs);
|
||||
ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
|
||||
|
||||
if (ka->sa.sa_flags & SA_ONESHOT)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (!(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);
|
||||
}
|
||||
return 1;
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
* 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;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
#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,
|
||||
regs->r12, current_thread_info()->flags);
|
||||
#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)
|
||||
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. */
|
||||
if (in_syscall)
|
||||
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
|
||||
* 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 &=
|
||||
~TS_RESTORE_SIGMASK;
|
||||
}
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
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];
|
||||
if (copy_from_user(&newset, uset, sizeof(sigset_t)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -281,15 +273,7 @@ asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
|||
unewset = (sigset_t __user *) regs.regs[4];
|
||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
#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];
|
||||
if (get_sigset(&newset, uset))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
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];
|
||||
if (get_sigset(&newset, uset))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
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)))
|
||||
return -EFAULT;
|
||||
sigset_from_compat(&newset, &uset);
|
||||
sigdelsetmask(&newset, ~_BLOCKABLE);
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
mask &= _BLOCKABLE;
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->saved_sigmask = current->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;
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -172,10 +164,7 @@ asmlinkage long sys_sigreturn(void)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(current_frame(), &frame->sc, &d0))
|
||||
goto badframe;
|
||||
|
@ -203,10 +192,7 @@ asmlinkage long sys_rt_sigreturn(void)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
|
||||
goto badframe;
|
||||
|
@ -476,15 +462,8 @@ static int handle_signal(int sig,
|
|||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
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);
|
||||
}
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -109,6 +109,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
|||
sigframe_size = PARISC_RT_SIGFRAME_SIZE32;
|
||||
#endif
|
||||
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* Unwind the user stack to get the rt_sigframe structure. */
|
||||
frame = (struct rt_sigframe __user *)
|
||||
|
@ -131,10 +132,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
|||
}
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
/* Good thing we saved the old gr[30], eh? */
|
||||
#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))
|
||||
return 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);
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
tracehook_signal_handler(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP) ||
|
||||
|
@ -474,8 +467,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
|||
/* Check the return code */
|
||||
switch (regs->gr[28]) {
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
current_thread_info()->restart_block.fn =
|
||||
do_no_restart_syscall;
|
||||
case -ERESTARTNOHAND:
|
||||
DBG(1,"ERESTARTNOHAND: returning -EINTR\n");
|
||||
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)) ||
|
||||
__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;
|
||||
__get_user(new_ka->sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_mask);
|
||||
siginitset(&new_ka->sa.sa_mask, mask);
|
||||
return 0;
|
||||
}
|
||||
|
@ -244,17 +244,8 @@ static inline int restore_general_regs(struct pt_regs *regs,
|
|||
long sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
set_current_state(TASK_INTERRUPTIBLE);
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(sigaction, int, sig, const struct old_sigaction __user *, act,
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/ptrace.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/tracehook.h>
|
||||
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/syscalls.h>
|
||||
|
@ -152,6 +153,9 @@ score_rt_sigreturn(struct pt_regs *regs)
|
|||
stack_t st;
|
||||
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];
|
||||
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
|
||||
goto badframe;
|
||||
|
@ -159,10 +163,7 @@ score_rt_sigreturn(struct pt_regs *regs)
|
|||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
recalc_sigpending();
|
||||
spin_unlock_irq(¤t->sighand->siglock);
|
||||
set_current_blocked(&set);
|
||||
|
||||
sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
|
||||
if (sig < 0)
|
||||
|
@ -236,9 +237,7 @@ static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
|
|||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
if (signr == SIGSEGV)
|
||||
ka->sa.sa_handler = SIG_DFL;
|
||||
force_sig(SIGSEGV, current);
|
||||
force_sigsegv(signr, current);
|
||||
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);
|
||||
|
||||
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);
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -356,6 +351,12 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
|
|||
__u32 thread_info_flags)
|
||||
{
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
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 *uenvp,
|
||||
unsigned long r7, struct pt_regs __regs);
|
||||
asmlinkage int sys_sigsuspend(old_sigset_t mask, unsigned long r5,
|
||||
unsigned long r6, unsigned long r7,
|
||||
struct pt_regs __regs);
|
||||
asmlinkage int sys_sigsuspend(old_sigset_t mask);
|
||||
asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,
|
||||
struct old_sigaction __user *oact);
|
||||
asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
#ifdef __KERNEL__
|
||||
# ifdef CONFIG_SUPERH32
|
||||
|
||||
# include "unistd_32.h"
|
||||
# define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
|
||||
# else
|
||||
# include "unistd_64.h"
|
||||
# endif
|
||||
|
||||
# define __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
# define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
# define __ARCH_WANT_OLD_READDIR
|
||||
# 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.
|
||||
*/
|
||||
asmlinkage int
|
||||
sys_sigsuspend(old_sigset_t mask,
|
||||
unsigned long r5, unsigned long r6, unsigned long r7,
|
||||
struct pt_regs __regs)
|
||||
sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
@ -83,10 +71,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||
old_sigset_t mask;
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__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;
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_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 (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||
__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;
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -162,12 +150,11 @@ static inline int save_sigcontext_fpu(struct sigcontext __user *sc,
|
|||
if (!(boot_cpu_data.flags & CPU_HAS_FPU))
|
||||
return 0;
|
||||
|
||||
if (!used_math()) {
|
||||
__put_user(0, &sc->sc_ownedfp);
|
||||
return 0;
|
||||
}
|
||||
if (!used_math())
|
||||
return __put_user(0, &sc->sc_ownedfp);
|
||||
|
||||
__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
|
||||
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 */
|
||||
clear_fpu(tsk, regs);
|
||||
clear_used_math();
|
||||
__get_user (owned_fp, &sc->sc_ownedfp);
|
||||
err |= __get_user (owned_fp, &sc->sc_ownedfp);
|
||||
if (owned_fp)
|
||||
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 *)ka->sa.sa_handler;
|
||||
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->regs[12], &funcptr->GOT);
|
||||
err |= __get_user(regs->pc, &funcptr->text);
|
||||
err |= __get_user(regs->regs[12], &funcptr->GOT);
|
||||
} else
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
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 *)ka->sa.sa_handler;
|
||||
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->regs[12], &funcptr->GOT);
|
||||
err |= __get_user(regs->pc, &funcptr->text);
|
||||
err |= __get_user(regs->regs[12], &funcptr->GOT);
|
||||
} else
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
|
||||
set_fs(USER_DS);
|
||||
|
||||
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
|
||||
* 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;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* 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 (!user_mode(regs))
|
||||
return 1;
|
||||
return;
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
asmlinkage int
|
||||
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)
|
||||
sys_sigsuspend(old_sigset_t mask)
|
||||
{
|
||||
sigset_t saveset, blocked;
|
||||
|
||||
saveset = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
sigset_t blocked;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&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;
|
||||
}
|
||||
}
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
@ -225,10 +173,10 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
|
|||
old_sigset_t mask;
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
|
||||
__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;
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_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 (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
|
||||
__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;
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(regs, 0);
|
||||
do_signal(regs);
|
||||
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
|
|
|
@ -215,8 +215,9 @@ void do_sigreturn32(struct pt_regs *regs)
|
|||
(((unsigned long) sf) & 3))
|
||||
goto segv;
|
||||
|
||||
get_user(pc, &sf->info.si_regs.pc);
|
||||
__get_user(npc, &sf->info.si_regs.npc);
|
||||
if (get_user(pc, &sf->info.si_regs.pc) ||
|
||||
__get_user(npc, &sf->info.si_regs.npc))
|
||||
goto segv;
|
||||
|
||||
if ((pc | npc) & 3)
|
||||
goto segv;
|
||||
|
@ -305,8 +306,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
|||
(((unsigned long) sf) & 3))
|
||||
goto segv;
|
||||
|
||||
get_user(pc, &sf->regs.pc);
|
||||
__get_user(npc, &sf->regs.npc);
|
||||
if (get_user(pc, &sf->regs.pc) ||
|
||||
__get_user(npc, &sf->regs.npc))
|
||||
goto segv;
|
||||
|
||||
if ((pc | npc) & 3)
|
||||
goto segv;
|
||||
|
|
|
@ -64,18 +64,8 @@ struct rt_signal_frame {
|
|||
static int _sigpause_common(old_sigset_t set)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
set &= _BLOCKABLE;
|
||||
siginitset(&blocked, set);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int sys_sigsuspend(old_sigset_t set)
|
||||
|
|
|
@ -242,19 +242,8 @@ struct rt_signal_frame {
|
|||
static long _sigpause_common(old_sigset_t set)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
set &= _BLOCKABLE;
|
||||
siginitset(&blocked, set);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
|
||||
set_restore_sigmask();
|
||||
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
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)) ||
|
||||
__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;
|
||||
__get_user(new_ka.sa.sa_flags, &act->sa_flags);
|
||||
__get_user(mask, &act->sa_mask);
|
||||
siginitset(&new_ka.sa.sa_mask, mask);
|
||||
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);
|
||||
|
||||
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)) ||
|
||||
__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;
|
||||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
|
||||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -148,15 +148,8 @@ int do_signal(void)
|
|||
long sys_sigsuspend(int history0, int history1, old_sigset_t mask)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
sigorsets(&blocked, &tsk->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&blocked, sig);
|
||||
set_current_blocked(&blocked);
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -450,15 +447,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
|||
regs->UCreg_00 == -ERESTARTNOINTR) {
|
||||
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,
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
sigset_t blocked;
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
|
||||
mask &= _BLOCKABLE;
|
||||
siginitset(&blocked, mask);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&blocked);
|
||||
}
|
||||
|
||||
asmlinkage int
|
||||
|
|
|
@ -120,13 +120,6 @@ typedef void (*__sighandler_t)(int);
|
|||
#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
|
||||
|
||||
#ifdef __KERNEL__
|
||||
struct old_sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
old_sigset_t sa_mask;
|
||||
unsigned long sa_flags;
|
||||
void (*sa_restorer)(void);
|
||||
};
|
||||
|
||||
struct sigaction {
|
||||
__sighandler_t sa_handler;
|
||||
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_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 sys_rt_sigaction(int,
|
||||
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_MEMDIE 5 /* is terminating due to OOM killer */
|
||||
#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_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
|
||||
|
|
|
@ -507,7 +507,7 @@ __SYSCALL(229, sys_rt_sigtimedwait, 4)
|
|||
#define __NR_rt_sigqueueinfo 230
|
||||
__SYSCALL(230, sys_rt_sigqueueinfo, 3)
|
||||
#define __NR_rt_sigsuspend 231
|
||||
__SYSCALL(231, xtensa_rt_sigsuspend, 2)
|
||||
__SYSCALL(231, sys_rt_sigsuspend, 2)
|
||||
|
||||
/* Message */
|
||||
|
||||
|
|
|
@ -409,16 +409,16 @@ common_exception_return:
|
|||
l32i a4, a2, TI_FLAGS
|
||||
|
||||
_bbsi.l a4, TIF_NEED_RESCHED, 3f
|
||||
_bbsi.l a4, TIF_NOTIFY_RESUME, 2f
|
||||
_bbci.l a4, TIF_SIGPENDING, 4f
|
||||
|
||||
l32i a4, a1, PT_DEPC
|
||||
2: l32i a4, a1, PT_DEPC
|
||||
bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f
|
||||
|
||||
/* 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
|
||||
movi a7, 0
|
||||
callx4 a4
|
||||
j 1b
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <linux/ptrace.h>
|
||||
#include <linux/personality.h>
|
||||
#include <linux/freezer.h>
|
||||
#include <linux/tracehook.h>
|
||||
|
||||
#include <asm/ucontext.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
@ -31,8 +32,6 @@
|
|||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
|
||||
|
||||
extern struct task_struct *coproc_owners[];
|
||||
|
||||
struct rt_sigframe
|
||||
|
@ -248,6 +247,9 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
|
|||
sigset_t set;
|
||||
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)
|
||||
panic("rt_sigreturn in double exception!\n");
|
||||
|
||||
|
@ -426,37 +428,6 @@ give_sigsegv:
|
|||
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,
|
||||
stack_t __user *uoss,
|
||||
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
|
||||
* 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;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
|
||||
if (!user_mode(regs))
|
||||
return 0;
|
||||
sigset_t oldset;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (!oldset)
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
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 */
|
||||
ret = setup_frame(signr, &ka, &info, oldset, regs);
|
||||
if (ret)
|
||||
return ret;
|
||||
return;
|
||||
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
block_sigmask(&ka, signr);
|
||||
if (current->ptrace & PT_SINGLESTEP)
|
||||
task_pt_regs(current)->icountlevel = 1;
|
||||
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
|
@ -558,8 +530,27 @@ no_signal:
|
|||
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)
|
||||
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 void set_current_blocked(const sigset_t *);
|
||||
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 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)))
|
||||
return -EFAULT;
|
||||
sigset_from_compat(&newset, &newset32);
|
||||
sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
#endif /* __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND */
|
||||
|
||||
|
|
|
@ -3232,6 +3232,21 @@ SYSCALL_DEFINE0(pause)
|
|||
|
||||
#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
|
||||
/**
|
||||
* 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)))
|
||||
return -EFAULT;
|
||||
sigdelsetmask(&newset, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(&newset);
|
||||
|
||||
current->state = TASK_INTERRUPTIBLE;
|
||||
schedule();
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
#endif /* __ARCH_WANT_SYS_RT_SIGSUSPEND */
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче