Commit f9369910 authored by Linus Torvalds's avatar Linus Torvalds

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()
  ...
parents 05f144a0 415d04d0
...@@ -34,9 +34,6 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 = &current->blocked;
int ret; int ret;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->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, ...@@ -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 = &current->saved_sigmask;
else
oldset = &current->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, ...@@ -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, ...@@ -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(&current->saved_sigmask);
sigprocmask(SIG_SETMASK, &current->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, ...@@ -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] = { ...@@ -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; ...@@ -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) ...@@ -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) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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);
*/
if (ret != 0 || !(ka->sa.sa_flags & SA_NODEFER)) {
spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
if (ret == 0)
return; 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) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret; return ret;
} }
......
...@@ -69,6 +69,9 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs) ...@@ -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); ...@@ -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(&current->sighand->siglock); siginitset(&blocked, mask);
current->saved_sigmask = current->blocked; return sigsuspend(&blocked);
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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, ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret; return ret;
} }
......
...@@ -59,19 +59,11 @@ void keep_debug_flags(unsigned long oldccs, unsigned long oldspc, ...@@ -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(&current->sighand->siglock); siginitset(&blocked, mask);
current->saved_sigmask = current->blocked; return sigsuspend(&blocked);
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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, ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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, ...@@ -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(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret; return ret;
} }
......
...@@ -40,17 +40,9 @@ struct fdpic_func_descriptor { ...@@ -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(&current->sighand->siglock); siginitset(&blocked, mask);
current->saved_sigmask = current->blocked; return sigsuspend(&blocked);
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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) ...@@ -158,10 +150,7 @@ asmlinkage int sys_sigreturn(void)
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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) ...@@ -184,10 +173,7 @@ asmlinkage int sys_rt_sigreturn(void)
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret; return ret;
......
...@@ -356,6 +356,7 @@ ...@@ -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 @@ ...@@ -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(&current->sighand->siglock);
saveset = current->blocked;
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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(&current->sighand->siglock);
saveset = current->blocked;
current->blocked = newset;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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,...) ...@@ -232,10 +187,7 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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,...) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_lock_irq(&current->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) ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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, ...@@ -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(&current->sighand->siglock); if (!ret) {
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); block_sigmask(ka, sig);
if (!(ka->sa.sa_flags & SA_NODEFER)) clear_thread_flag(TIF_RESTORE_SIGMASK);
sigaddset(&current->blocked,sig); }
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
} }
/* /*
...@@ -502,11 +452,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, ...@@ -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) ...@@ -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 = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->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) ...@@ -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(&current->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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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(&current->sighand->siglock);
{
current->blocked = set;
recalc_sigpending();
}
spin_unlock_irq(&current->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 ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->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; ...@@ -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, ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return 0; return 0;
} }
......
...@@ -71,6 +71,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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 @@ ...@@ -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) ...@@ -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(&current->sighand->siglock); siginitset(&blocked, mask);
current->saved_sigmask = current->blocked; return sigsuspend(&blocked);
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->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) ...@@ -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) ...@@ -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, ...@@ -1150,10 +1140,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err) if (err)
return; return;
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); block_sigmask(ka, sig);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->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, ...@@ -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) ...@@ -1200,3 +1187,15 @@ asmlinkage void do_signal(struct pt_regs *regs)
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); sigprocmask(SIG_SETMASK, &current->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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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: ...@@ -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: ...@@ -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): ...@@ -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): ...@@ -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): ...@@ -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: ...@@ -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 */ ...@@ -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 @@ ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -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(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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) ...@@ -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, ...@@ -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 ...@@ -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(&current->sighand->siglock);
sigorsets(&current->blocked, return 0;
&current->blocked, &ka->sa.sa_mask);
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return 1;
} }
/* /*
...@@ -345,24 +339,17 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, ...@@ -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 = &current->saved_sigmask; oldset = &current->saved_sigmask;
...@@ -374,7 +361,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall) ...@@ -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) ...@@ -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) ...@@ -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, &current->saved_sigmask, NULL); sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
} }
}
/* Did we come from a system call? */ void do_notify_resume(struct pt_regs *regs, int in_syscall)
return 0; {
/*
* 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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 @@ ...@@ -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(&current->sighand->siglock); siginitset(&blocked, mask);
current->saved_sigmask = current->blocked; return sigsuspend(&blocked);
siginitset(&current->blocked, mask);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
current->state = TASK_INTERRUPTIBLE;
schedule();
set_thread_flag(TIF_RESTORE_SIGMASK);
return -ERESTARTNOHAND;
} }
/* /*
...@@ -172,10 +164,7 @@ asmlinkage long sys_sigreturn(void) ...@@ -172,10 +164,7 @@ asmlinkage long sys_sigreturn(void)
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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) ...@@ -203,10 +192,7 @@ asmlinkage long sys_rt_sigreturn(void)
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked, &current->blocked,
&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
}
return ret; return ret;
} }
......
...@@ -109,6 +109,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) ...@@ -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) ...@@ -131,10 +132,7 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
} }
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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(&current->sighand->siglock); block_sigmask(ka, sig);
sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked,sig);
recalc_sigpending();
spin_unlock_irq(&current->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) ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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 @@ ...@@ -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) ...@@ -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) ...@@ -159,10 +163,7 @@ score_rt_sigreturn(struct pt_regs *regs)
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE); sigdelsetmask(&set, ~_BLOCKABLE);
spin_lock_irq(&current->sighand->siglock); set_current_blocked(&set);
current->blocked = set;
recalc_sigpending();
spin_unlock_irq(&current->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, ...@@ -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, ...@@ -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(&current->sighand->siglock); if (ret == 0)
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask); block_sigmask(ka, sig);
if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&current->blocked, sig);
recalc_sigpending();
spin_unlock_irq(&current->sighand->siglock);
return ret; return ret;
} }
...@@ -356,6 +351,12 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused, ...@@ -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, ...@@ -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,
......
#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 { ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 = &current->saved_sigmask; oldset = &current->saved_sigmask;
else if (!oldset) else
oldset = &current->blocked; oldset = &current->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) ...@@ -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) ...@@ -147,71 +148,18 @@ static int do_signal(struct pt_regs *regs, sigset_t *oldset)
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); sigprocmask(SIG_SETMASK, &current->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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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 { ...@@ -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 { ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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, &current->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(&current->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) ...@@ -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 ...@@ -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); ...@@ -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*); ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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 @@ ...@@ -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 @@ ...@@ -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, ...@@ -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 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -426,37 +428,6 @@ static int setup_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
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, ...@@ -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 = &current->saved_sigmask;
else
oldset = &current->blocked; oldset = &current->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) ...@@ -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 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) ...@@ -558,8 +530,27 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
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(&current->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 *, ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment