dect
/
linux-2.6
Archived
13
0
Fork 0

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal

Pull third pile of signal handling patches from Al Viro:
 "This time it's mostly helpers and conversions to them; there's a lot
  of stuff remaining in the tree, but that'll either go in -rc2
  (isolated bug fixes, ideally via arch maintainers' trees) or will sit
  there until the next cycle."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal:
  x86: get rid of calling do_notify_resume() when returning to kernel mode
  blackfin: check __get_user() return value
  whack-a-mole with TIF_FREEZE
  FRV: Optimise the system call exit path in entry.S [ver #2]
  FRV: Shrink TIF_WORK_MASK [ver #2]
  FRV: Prevent syscall exit tracing and notify_resume at end of kernel exceptions
  new helper: signal_delivered()
  powerpc: get rid of restore_sigmask()
  most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set
  set_restore_sigmask() is never called without SIGPENDING (and never should be)
  TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set
  don't call try_to_freeze() from do_signal()
  pull clearing RESTORE_SIGMASK into block_sigmask()
  sh64: failure to build sigframe != signal without handler
  openrisc: tracehook_signal_handler() is supposed to be called on success
  new helper: sigmask_to_save()
  new helper: restore_saved_sigmask()
  new helpers: {clear,test,test_and_clear}_restore_sigmask()
  HAVE_RESTORE_SIGMASK is defined on all architectures now
This commit is contained in:
Linus Torvalds 2012-06-01 11:53:44 -07:00
commit 86c47b70f6
68 changed files with 482 additions and 1091 deletions

View File

@ -226,7 +226,6 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
if (__get_user(set.sig[0], &sc->sc_mask)) if (__get_user(set.sig[0], &sc->sc_mask))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(sc, regs, sw)) if (restore_sigcontext(sc, regs, sw))
@ -261,7 +260,6 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw)) if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
@ -468,12 +466,9 @@ 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,
struct pt_regs * regs, struct switch_stack *sw) struct pt_regs * regs, struct switch_stack *sw)
{ {
sigset_t *oldset = &current->blocked; sigset_t *oldset = sigmask_to_save();
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
@ -483,12 +478,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
force_sigsegv(sig, current); force_sigsegv(sig, current);
return; return;
} }
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
/* A signal was successfully delivered, and the
saved sigmask was stored on the signal frame,
and will be restored by sigreturn. So we can
simply clear the restore sigmask flag. */
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
static inline void static inline void
@ -572,9 +562,7 @@ 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_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) restore_saved_sigmask();
set_current_blocked(&current->saved_sigmask);
if (single_stepping) if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */ ptrace_set_bpt(current); /* re-set breakpoint */
} }

View File

@ -22,8 +22,6 @@
#include "signal.h" #include "signal.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* For ARM syscalls, we encode the syscall number into the instruction. * For ARM syscalls, we encode the syscall number into the instruction.
*/ */
@ -210,10 +208,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
int err; int err;
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
if (err == 0) { if (err == 0)
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
}
__get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err); __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
__get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err); __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
@ -528,13 +524,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, struct pt_regs *regs)
struct pt_regs * regs)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current; struct task_struct *tsk = current;
sigset_t *oldset = sigmask_to_save();
int usig = sig; int usig = sig;
int ret; int ret;
@ -559,17 +555,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
if (ret != 0) { if (ret != 0) {
force_sigsegv(sig, tsk); force_sigsegv(sig, tsk);
return ret; return;
} }
signal_delivered(sig, info, ka, regs, 0);
/*
* Block the signal if we were successful.
*/
block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, regs, 0);
return 0;
} }
/* /*
@ -617,8 +605,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
*/ */
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
sigset_t *oldset;
/* /*
* Depending on the signal settings we may need to revert the * Depending on the signal settings we may need to revert the
* decision to restart the system call. But skip this if a * decision to restart the system call. But skip this if a
@ -635,20 +621,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
clear_thread_flag(TIF_SYSCALL_RESTARTSYS); clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
} }
if (test_thread_flag(TIF_RESTORE_SIGMASK)) handle_signal(signr, &ka, &info, regs);
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
@ -663,11 +636,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
set_thread_flag(TIF_SYSCALL_RESTARTSYS); set_thread_flag(TIF_SYSCALL_RESTARTSYS);
} }
/* If there's no signal to deliver, we just put the saved sigmask restore_saved_sigmask();
* back.
*/
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
set_current_blocked(&current->saved_sigmask);
} }
asmlinkage void asmlinkage void

View File

@ -281,7 +281,7 @@ syscall_exit_work:
ld.w r1, r0[TI_flags] ld.w r1, r0[TI_flags]
rjmp 1b rjmp 1b
2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME 2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
tst r1, r2 tst r1, r2
breq 3f breq 3f
unmask_interrupts unmask_interrupts
@ -587,7 +587,7 @@ fault_exit_work:
ld.w r1, r0[TI_flags] ld.w r1, r0[TI_flags]
rjmp fault_exit_work rjmp fault_exit_work
1: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME 1: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
tst r1, r2 tst r1, r2
breq 2f breq 2f
unmask_interrupts unmask_interrupts

View File

@ -22,8 +22,6 @@
#include <asm/ucontext.h> #include <asm/ucontext.h>
#include <asm/syscalls.h> #include <asm/syscalls.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
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,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -89,7 +87,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@ -224,30 +221,27 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
static inline void static inline void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs, int syscall) struct pt_regs *regs, int syscall)
{ {
int ret; int ret;
/* /*
* 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, sigmask_to_save(), regs);
/* /*
* Check that the resulting registers are sane * Check that the resulting registers are sane
*/ */
ret |= !valid_user_regs(regs); ret |= !valid_user_regs(regs);
if (ret != 0) {
force_sigsegv(sig, current);
return;
}
/* /*
* Block the signal if we were successful. * Block the signal if we were successful.
*/ */
block_sigmask(ka, sig); if (ret != 0)
clear_thread_flag(TIF_RESTORE_SIGMASK); force_sigsegv(sig, current);
else
signal_delivered(sig, info, ka, regs, 0);
} }
/* /*
@ -255,7 +249,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
* doesn't want to handle. Thus you cannot kill init even with a * doesn't want to handle. Thus you cannot kill init even with a
* SIGKILL even by mistake. * SIGKILL even by mistake.
*/ */
int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall) static void do_signal(struct pt_regs *regs, int syscall)
{ {
siginfo_t info; siginfo_t info;
int signr; int signr;
@ -267,12 +261,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
* without doing anything if so. * without doing anything if so.
*/ */
if (!user_mode(regs)) if (!user_mode(regs))
return 0; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (syscall) { if (syscall) {
@ -297,15 +286,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
if (signr == 0) { if (signr == 0) {
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK); return;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return 0;
} }
handle_signal(signr, &ka, &info, oldset, regs, syscall); handle_signal(signr, &ka, &info, regs, syscall);
return 1;
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
@ -315,8 +300,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
syscall = 1; syscall = 1;
if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (ti->flags & _TIF_SIGPENDING))
do_signal(regs, &current->blocked, syscall); do_signal(regs, syscall);
if (ti->flags & _TIF_NOTIFY_RESUME) { if (ti->flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME); clear_thread_flag(TIF_NOTIFY_RESUME);

View File

@ -100,7 +100,6 @@ static inline struct thread_info *current_thread_info(void)
TIF_NEED_RESCHED */ TIF_NEED_RESCHED */
#define TIF_MEMDIE 4 /* is terminating due to OOM killer */ #define TIF_MEMDIE 4 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
#define TIF_FREEZE 6 /* is freezing for suspend */
#define TIF_IRQ_SYNC 7 /* sync pipeline stage */ #define TIF_IRQ_SYNC 7 /* sync pipeline stage */
#define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ #define TIF_NOTIFY_RESUME 8 /* callback before returning to user */
#define TIF_SINGLESTEP 9 #define TIF_SINGLESTEP 9
@ -111,7 +110,6 @@ static inline struct thread_info *current_thread_info(void)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_FREEZE (1<<TIF_FREEZE)
#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC) #define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP) #define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)

View File

@ -19,8 +19,6 @@
#include <asm/fixed_code.h> #include <asm/fixed_code.h>
#include <asm/syscall.h> #include <asm/syscall.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* Location of the trace bit in SYSCFG. */ /* Location of the trace bit in SYSCFG. */
#define TRACE_BITS 0x0001 #define TRACE_BITS 0x0001
@ -98,7 +96,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
@ -190,17 +187,22 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
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 registers for signal handler */ /* Set up registers for signal handler */
wrusp((unsigned long)frame);
if (current->personality & FDPIC_FUNCPTRS) { if (current->personality & FDPIC_FUNCPTRS) {
struct fdpic_func_descriptor __user *funcptr = struct fdpic_func_descriptor __user *funcptr =
(struct fdpic_func_descriptor *) ka->sa.sa_handler; (struct fdpic_func_descriptor *) ka->sa.sa_handler;
__get_user(regs->pc, &funcptr->text); u32 pc, p3;
__get_user(regs->p3, &funcptr->GOT); err |= __get_user(pc, &funcptr->text);
err |= __get_user(p3, &funcptr->GOT);
if (err)
return -EFAULT;
regs->pc = pc;
regs->p3 = p3;
} else } else
regs->pc = (unsigned long)ka->sa.sa_handler; regs->pc = (unsigned long)ka->sa.sa_handler;
wrusp((unsigned long)frame);
regs->rets = SIGRETURN_STUB; regs->rets = SIGRETURN_STUB;
regs->r0 = frame->sig; regs->r0 = frame->sig;
@ -208,10 +210,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
regs->r2 = (unsigned long)(&frame->uc); regs->r2 = (unsigned long)(&frame->uc);
return 0; return 0;
give_sigsegv:
force_sigsegv(sig, current);
return -EFAULT;
} }
static inline void static inline void
@ -247,24 +245,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
int ret;
/* are we from a system call? to see pt_regs->orig_p0 */ /* are we from a system call? to see pt_regs->orig_p0 */
if (regs->orig_p0 >= 0) if (regs->orig_p0 >= 0)
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
handle_restart(regs, ka, 1); handle_restart(regs, ka, 1);
/* set up the stack frame */ /* set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs); if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
force_sigsegv(sig, current);
if (ret == 0) else
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return ret;
} }
/* /*
@ -281,37 +276,16 @@ asmlinkage 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;
current->thread.esp0 = (unsigned long)regs; current->thread.esp0 = (unsigned long)regs;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->orig_p0 >= 0) if (regs->orig_p0 >= 0)
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
@ -319,10 +293,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
@ -330,7 +301,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
*/ */
asmlinkage void do_notify_resume(struct pt_regs *regs) asmlinkage void do_notify_resume(struct pt_regs *regs)
{ {
if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK)) if (test_thread_flag(TIF_SIGPENDING))
do_signal(regs); do_signal(regs);
if (test_thread_flag(TIF_NOTIFY_RESUME)) { if (test_thread_flag(TIF_NOTIFY_RESUME)) {

View File

@ -711,8 +711,6 @@ ENTRY(_system_call)
jump .Lresume_userspace_1; jump .Lresume_userspace_1;
.Lsyscall_sigpending: .Lsyscall_sigpending:
cc = BITTST(r7, TIF_RESTORE_SIGMASK);
if cc jump .Lsyscall_do_signals;
cc = BITTST(r7, TIF_SIGPENDING); cc = BITTST(r7, TIF_SIGPENDING);
if cc jump .Lsyscall_do_signals; if cc jump .Lsyscall_do_signals;
cc = BITTST(r7, TIF_NOTIFY_RESUME); cc = BITTST(r7, TIF_NOTIFY_RESUME);

View File

@ -20,8 +20,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* Do a signal return, undo the signal stack. * Do a signal return, undo the signal stack.
*/ */
@ -87,7 +85,6 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@ -248,10 +245,9 @@ do_restart:
/* /*
* handle the actual delivery of a signal to userspace * handle the actual delivery of a signal to userspace
*/ */
static int handle_signal(int sig, static void handle_signal(int sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs, struct pt_regs *regs, int syscall)
int syscall)
{ {
int ret; int ret;
@ -278,11 +274,9 @@ static int handle_signal(int sig,
} }
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_rt_frame(sig, ka, info, oldset, regs); if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
if (ret == 0) return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
/* /*
@ -292,7 +286,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
sigset_t *oldset;
int signr; int signr;
/* we want the common case to go fast, which is why we may in certain /* we want the common case to go fast, which is why we may in certain
@ -300,25 +293,9 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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) {
if (handle_signal(signr, &info, &ka, oldset, handle_signal(signr, &info, &ka, regs, syscall);
regs, syscall) == 0) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs, 0);
}
return; return;
} }
@ -343,10 +320,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
@ -357,8 +331,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
int syscall) int syscall)
{ {
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & ((1 << TIF_SIGPENDING) | if (thread_info_flags & (1 << TIF_SIGPENDING))
(1 << TIF_RESTORE_SIGMASK)))
do_signal(regs, syscall); do_signal(regs, syscall);
if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) { if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) {

View File

@ -31,8 +31,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */ /* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */
/* manipulate regs so that upon return, it will be re-executed */ /* manipulate regs so that upon return, it will be re-executed */
@ -176,7 +174,6 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc)) if (restore_sigcontext(regs, &frame->sc))
@ -212,7 +209,6 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@ -415,10 +411,11 @@ give_sigsegv:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static inline int handle_signal(int canrestart, unsigned long sig, static inline void handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
@ -456,9 +453,7 @@ static inline int handle_signal(int canrestart, unsigned long sig,
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret == 0)
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
/* /*
@ -478,7 +473,6 @@ void do_signal(int canrestart, 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
@ -489,23 +483,10 @@ void do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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. */
if (handle_signal(canrestart, signr, &info, &ka, handle_signal(canrestart, signr, &info, &ka, regs);
oldset, regs)) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
@ -525,8 +506,5 @@ void do_signal(int canrestart, struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }

View File

@ -24,9 +24,6 @@
extern unsigned long cris_signal_return_page; extern unsigned long cris_signal_return_page;
/* Flag to check if a signal is blockable. */
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* A syscall in CRIS is really a "break 13" instruction, which is 2 * A syscall in CRIS is really a "break 13" instruction, which is 2
* bytes. The registers is manipulated so upon return the instruction * bytes. The registers is manipulated so upon return the instruction
@ -167,7 +164,6 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc)) if (restore_sigcontext(regs, &frame->sc))
@ -208,7 +204,6 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@ -434,11 +429,12 @@ give_sigsegv:
} }
/* Invoke a signal handler to, well, handle the signal. */ /* Invoke a signal handler to, well, handle the signal. */
static inline int static inline void
handle_signal(int canrestart, unsigned long sig, handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs * regs) struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Check if this got called from a system call. */ /* Check if this got called from a system call. */
@ -489,9 +485,7 @@ handle_signal(int canrestart, unsigned long sig,
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret == 0)
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
/* /*
@ -511,7 +505,6 @@ do_signal(int canrestart, struct pt_regs *regs)
int signr; int signr;
siginfo_t info; siginfo_t info;
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
/* /*
* The common case should go fast, which is why this point is * The common case should go fast, which is why this point is
@ -521,25 +514,11 @@ do_signal(int canrestart, struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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. */
if (handle_signal(canrestart, signr, &info, &ka, handle_signal(canrestart, signr, &info, &ka, regs);
oldset, regs)) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
@ -560,10 +539,7 @@ do_signal(int canrestart, struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
asmlinkage void asmlinkage void

View File

@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15");
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */ #define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ #define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */ #define TIF_MEMDIE 7 /* is terminating due to OOM killer */
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
@ -105,8 +105,16 @@ register struct thread_info *__current_thread_info asm("gr15");
#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ /* work to do on interrupt/exception return */
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */ #define _TIF_WORK_MASK \
(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP)
/* work to do on any return to u-space */
#define _TIF_ALLWORK_MASK (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
#if _TIF_ALLWORK_MASK >= 0x2000
#error "_TIF_ALLWORK_MASK won't fit in an ANDI now (see entry.S)"
#endif
/* /*
* Thread-synchronous status. * Thread-synchronous status.

View File

@ -905,18 +905,19 @@ __syscall_call:
__syscall_exit: __syscall_exit:
LEDS 0x6300 LEDS 0x6300
sti gr8,@(gr28,#REG_GR(8)) ; save return value # keep current PSR in GR23
movsg psr,gr23
ldi @(gr28,#REG_PSR),gr22
sti.p gr8,@(gr28,#REG_GR(8)) ; save return value
# rebuild saved psr - execve will change it for init/main.c # rebuild saved psr - execve will change it for init/main.c
ldi @(gr28,#REG_PSR),gr22
srli gr22,#1,gr5 srli gr22,#1,gr5
andi.p gr22,#~PSR_PS,gr22 andi.p gr22,#~PSR_PS,gr22
andi gr5,#PSR_PS,gr5 andi gr5,#PSR_PS,gr5
or gr5,gr22,gr22 or gr5,gr22,gr22
ori gr22,#PSR_S,gr22 ori.p gr22,#PSR_S,gr22
# keep current PSR in GR23
movsg psr,gr23
# make sure we don't miss an interrupt setting need_resched or sigpending between # make sure we don't miss an interrupt setting need_resched or sigpending between
# sampling and the RETT # sampling and the RETT
@ -924,9 +925,7 @@ __syscall_exit:
movgs gr23,psr movgs gr23,psr
ldi @(gr15,#TI_FLAGS),gr4 ldi @(gr15,#TI_FLAGS),gr4
sethi.p %hi(_TIF_ALLWORK_MASK),gr5 andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0
setlo %lo(_TIF_ALLWORK_MASK),gr5
andcc gr4,gr5,gr0,icc0
bne icc0,#0,__syscall_exit_work bne icc0,#0,__syscall_exit_work
# restore all registers and return # restore all registers and return
@ -1111,9 +1110,7 @@ __entry_resume_userspace:
__entry_return_from_user_interrupt: __entry_return_from_user_interrupt:
LEDS 0x6402 LEDS 0x6402
ldi @(gr15,#TI_FLAGS),gr4 ldi @(gr15,#TI_FLAGS),gr4
sethi.p %hi(_TIF_WORK_MASK),gr5 andicc gr4,#_TIF_WORK_MASK,gr0,icc0
setlo %lo(_TIF_WORK_MASK),gr5
andcc gr4,gr5,gr0,icc0
beq icc0,#1,__entry_return_direct beq icc0,#1,__entry_return_direct
__entry_work_pending: __entry_work_pending:
@ -1133,9 +1130,7 @@ __entry_work_resched:
LEDS 0x6401 LEDS 0x6401
ldi @(gr15,#TI_FLAGS),gr4 ldi @(gr15,#TI_FLAGS),gr4
sethi.p %hi(_TIF_WORK_MASK),gr5 andicc gr4,#_TIF_WORK_MASK,gr0,icc0
setlo %lo(_TIF_WORK_MASK),gr5
andcc gr4,gr5,gr0,icc0
beq icc0,#1,__entry_return_direct beq icc0,#1,__entry_return_direct
andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0 andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
bne icc0,#1,__entry_work_resched bne icc0,#1,__entry_work_resched
@ -1163,7 +1158,9 @@ __syscall_trace_entry:
# perform syscall exit tracing # perform syscall exit tracing
__syscall_exit_work: __syscall_exit_work:
LEDS 0x6340 LEDS 0x6340
andicc gr4,#_TIF_SYSCALL_TRACE,gr0,icc0 andicc gr22,#PSR_PS,gr0,icc1 ; don't handle on return to kernel mode
andicc.p gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
bne icc1,#0,__entry_return_direct
beq icc0,#1,__entry_work_pending beq icc0,#1,__entry_work_pending
movsg psr,gr23 movsg psr,gr23

View File

@ -28,8 +28,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
struct fdpic_func_descriptor { struct fdpic_func_descriptor {
unsigned long text; unsigned long text;
unsigned long GOT; unsigned long GOT;
@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void)
__copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask))) __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(&frame->sc, &gr8)) if (restore_sigcontext(&frame->sc, &gr8))
@ -172,7 +169,6 @@ asmlinkage int sys_rt_sigreturn(void)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8)) if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
@ -426,9 +422,10 @@ give_sigsegv:
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset) struct k_sigaction *ka)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
@ -460,11 +457,11 @@ 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)
block_sigmask(ka, sig); return;
return ret;
signal_delivered(sig, info, ka, __frame,
test_thread_flag(TIF_SINGLESTEP));
} /* end handle_signal() */ } /* end handle_signal() */
/*****************************************************************************/ /*****************************************************************************/
@ -477,44 +474,14 @@ static void do_signal(void)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
sigset_t *oldset;
int signr; int signr;
/*
* 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 (!user_mode(__frame))
return;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, __frame, NULL); signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &info, &ka, oldset) == 0) { handle_signal(signr, &info, &ka);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, __frame,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (__frame->syscallno != -1) { if (__frame->syscallno != -1) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
@ -536,11 +503,7 @@ no_signal:
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} /* end do_signal() */ } /* end do_signal() */
/*****************************************************************************/ /*****************************************************************************/
@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
clear_thread_flag(TIF_SINGLESTEP); clear_thread_flag(TIF_SINGLESTEP);
/* 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(); do_signal();
/* deal with notification on about to resume userspace execution */ /* deal with notification on about to resume userspace execution */

View File

@ -47,8 +47,6 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* Atomically swap in the new signal mask, and wait for a signal. * Atomically swap in the new signal mask, and wait for a signal.
*/ */
@ -186,7 +184,6 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, &er0)) if (restore_sigcontext(regs, &frame->sc, &er0))
@ -211,7 +208,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
@ -412,8 +408,9 @@ give_sigsegv:
*/ */
static void 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) struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_er0 >= 0) { if (regs->orig_er0 >= 0) {
@ -441,10 +438,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (!ret) { if (!ret)
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
} }
/* /*
@ -457,7 +452,6 @@ 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
@ -468,23 +462,14 @@ statis void do_signal(struct pt_regs *regs)
if ((regs->ccr & 0x10)) if ((regs->ccr & 0x10))
return; return;
if (try_to_freeze())
goto no_signal;
current->thread.esp0 = (unsigned long) regs; current->thread.esp0 = (unsigned long) regs;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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, regs);
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->orig_er0 >= 0) { if (regs->orig_er0 >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
@ -501,8 +486,7 @@ statis void do_signal(struct pt_regs *regs)
} }
/* 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_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) restore_saved_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)

View File

@ -31,8 +31,6 @@
#include <asm/signal.h> #include <asm/signal.h>
#include <asm/vdso.h> #include <asm/vdso.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
struct rt_sigframe { struct rt_sigframe {
unsigned long tramp[2]; unsigned long tramp[2];
struct siginfo info; struct siginfo info;
@ -149,11 +147,9 @@ sigsegv:
/* /*
* Setup invocation of signal handler * Setup invocation of signal handler
*/ */
static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
int rc;
/* /*
* If we're handling a signal that aborted a system call, * If we're handling a signal that aborted a system call,
* set up the error return value before adding the signal * set up the error return value before adding the signal
@ -186,15 +182,12 @@ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
* Set up the stack frame; not doing the SA_SIGINFO thing. We * Set up the stack frame; not doing the SA_SIGINFO thing. We
* only set up the rt_frame flavor. * only set up the rt_frame flavor.
*/ */
rc = setup_rt_frame(sig, ka, info, oldset, regs);
/* If there was an error on setup, no signal was delivered. */ /* If there was an error on setup, no signal was delivered. */
if (rc) if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
return rc; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return 0;
} }
/* /*
@ -209,34 +202,13 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (try_to_freeze())
goto no_signal;
signo = get_signal_to_deliver(&info, &sigact, regs, NULL); signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
if (signo > 0) { if (signo > 0) {
sigset_t *oldset; handle_signal(signo, &info, &sigact, regs);
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
/*
* Successful delivery case. The saved sigmask is
* stored in the signal frame, and will be restored
* by sigreturn. We can clear the TIF flag.
*/
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signo, &info, &sigact, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }
no_signal:
/* /*
* If we came from a system call, handle the restart. * If we came from a system call, handle the restart.
*/ */
@ -259,10 +231,7 @@ no_signal:
no_restart: no_restart:
/* If there's no signal to deliver, put the saved sigmask back */ /* If there's no signal to deliver, put the saved sigmask back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
@ -301,7 +270,6 @@ asmlinkage int sys_rt_sigreturn(void)
if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked))) if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
goto badframe; goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
set_current_blocked(&blocked); set_current_blocked(&blocked);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))

View File

@ -141,7 +141,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, &ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -30,7 +30,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define STACK_ALIGN 16 /* minimal alignment for stack pointer */ #define STACK_ALIGN 16 /* minimal alignment for stack pointer */
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#if _NSIG_WORDS > 1 #if _NSIG_WORDS > 1
# define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t)) # define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t))
@ -200,7 +199,6 @@ ia64_rt_sigreturn (struct sigscratch *scr)
if (GET_SIGSET(&set, &sc->sc_mask)) if (GET_SIGSET(&set, &sc->sc_mask))
goto give_sigsegv; goto give_sigsegv;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(sc, scr)) if (restore_sigcontext(sc, scr))
@ -415,18 +413,13 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
} }
static long static long
handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
struct sigscratch *scr) struct sigscratch *scr)
{ {
if (!setup_frame(sig, ka, info, oldset, scr)) if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
return 0; return 0;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, &scr->pt,
/*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(sig, info, ka, &scr->pt,
test_thread_flag(TIF_SINGLESTEP)); test_thread_flag(TIF_SINGLESTEP));
return 1; return 1;
@ -440,7 +433,6 @@ void
ia64_do_signal (struct sigscratch *scr, long in_syscall) ia64_do_signal (struct sigscratch *scr, long in_syscall)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
long restart = in_syscall; long restart = in_syscall;
long errno = scr->pt.r8; long errno = scr->pt.r8;
@ -453,11 +445,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
if (!user_mode(&scr->pt)) if (!user_mode(&scr->pt))
return; return;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
/* /*
* This only loops in the rare cases of handle_signal() failing, in which case we * This only loops in the rare cases of handle_signal() failing, in which case we
* need to push through a forced SIGSEGV. * need to push through a forced SIGSEGV.
@ -507,16 +494,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to * Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV... * continue to iterate in this loop so we can deliver the SIGSEGV...
*/ */
if (handle_signal(signr, &ka, &info, oldset, scr)) { if (handle_signal(signr, &ka, &info, scr))
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
return; return;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
@ -538,8 +517,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }

View File

@ -28,8 +28,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage int asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long r2, unsigned long r3, unsigned long r4, unsigned long r2, unsigned long r3, unsigned long r4,
@ -111,7 +109,6 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
@ -267,9 +264,9 @@ static int prev_insn(struct pt_regs *regs)
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
/* Are we from a system call? */ /* Are we from a system call? */
if (regs->syscall_nr >= 0) { if (regs->syscall_nr >= 0) {
@ -294,11 +291,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
} }
/* Set up the stack frame */ /* Set up the stack frame */
if (setup_rt_frame(sig, ka, info, oldset, regs)) if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
return -EFAULT; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return 0;
} }
/* /*
@ -311,7 +307,6 @@ 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
@ -322,14 +317,6 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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) {
/* Re-enable any watchpoints before delivering the /* Re-enable any watchpoints before delivering the
@ -339,13 +326,11 @@ static void do_signal(struct pt_regs *regs)
*/ */
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) handle_signal(signr, &ka, &info, regs);
clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if (regs->syscall_nr >= 0) { if (regs->syscall_nr >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
@ -360,10 +345,7 @@ static void do_signal(struct pt_regs *regs)
prev_insn(regs); prev_insn(regs);
} }
} }
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*

View File

@ -51,8 +51,6 @@
#include <asm/traps.h> #include <asm/traps.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
/* /*
@ -795,7 +793,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, frame + 1)) if (restore_sigcontext(regs, &frame->sc, frame + 1))
@ -820,7 +817,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (rt_restore_ucontext(regs, sw, &frame->uc)) if (rt_restore_ucontext(regs, sw, &frame->uc))
@ -1123,8 +1119,9 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
*/ */
static void static 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 pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int err; int err;
/* are we from a system call? */ /* are we from a system call? */
if (regs->orig_d0 >= 0) if (regs->orig_d0 >= 0)
@ -1140,14 +1137,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
if (err) if (err)
return; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
if (test_thread_flag(TIF_DELAYED_TRACE)) { if (test_thread_flag(TIF_DELAYED_TRACE)) {
regs->sr &= ~0x8000; regs->sr &= ~0x8000;
send_sig(SIGTRAP, current, 1); send_sig(SIGTRAP, current, 1);
} }
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
/* /*
@ -1160,19 +1155,13 @@ static void do_signal(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
struct k_sigaction ka; struct k_sigaction ka;
int signr; int signr;
sigset_t *oldset;
current->thread.esp0 = (unsigned long) regs; current->thread.esp0 = (unsigned long) regs;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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, &ka, &info, oldset, regs); handle_signal(signr, &ka, &info, regs);
return; return;
} }
@ -1182,10 +1171,7 @@ static void do_signal(struct pt_regs *regs)
handle_restart(regs, NULL, 0); handle_restart(regs, NULL, 0);
/* 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)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
void do_notify_resume(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs)

View File

@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
#endif #endif

View File

@ -41,8 +41,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/syscalls.h> #include <asm/syscalls.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
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)
@ -106,7 +104,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
@ -310,10 +307,11 @@ do_restart:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
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, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Set up the stack frame */ /* Set up the stack frame */
@ -323,11 +321,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
ret = setup_rt_frame(sig, ka, NULL, oldset, regs); ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return 0;
} }
/* /*
@ -344,33 +340,18 @@ 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 %d\n", regs, 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
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
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. */
if (in_syscall) if (in_syscall)
handle_restart(regs, &ka, 1); handle_restart(regs, &ka, 1);
if (!handle_signal(signr, &ka, &info, oldset, regs)) { handle_signal(signr, &ka, &info, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &=
~TS_RESTORE_SIGMASK;
}
return; return;
} }
@ -381,10 +362,7 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
* If there's no signal to deliver, we just put the saved sigmask * If there's no signal to deliver, we just put the saved sigmask
* back. * back.
*/ */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
void do_notify_resume(struct pt_regs *regs, int in_syscall) void do_notify_resume(struct pt_regs *regs, int in_syscall)

View File

@ -19,8 +19,6 @@
# define DEBUGP(fmt, args...) # define DEBUGP(fmt, args...)
#endif #endif
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* Determine which stack to use.. * Determine which stack to use..
*/ */

View File

@ -339,7 +339,6 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked))) if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
goto badframe; goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
set_current_blocked(&blocked); set_current_blocked(&blocked);
sig = restore_sigcontext(&regs, &frame->sf_sc); sig = restore_sigcontext(&regs, &frame->sf_sc);
@ -375,7 +374,6 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext); sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
@ -514,9 +512,10 @@ struct mips_abi mips_abi = {
.restart = __NR_restart_syscall .restart = __NR_restart_syscall
}; };
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) struct k_sigaction *ka, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
struct mips_abi *abi = current->thread.abi; struct mips_abi *abi = current->thread.abi;
void *vdso = current->mm->context.vdso; void *vdso = current->mm->context.vdso;
@ -550,17 +549,14 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
ka, regs, sig, oldset); ka, regs, sig, oldset);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs, 0);
return ret;
} }
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
int signr; int signr;
@ -572,25 +568,10 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
@ -614,10 +595,7 @@ static void do_signal(struct pt_regs *regs)
* If there's no signal to deliver, we just put the saved sigmask * If there's no signal to deliver, we just put the saved sigmask
* back * back
*/ */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
@ -630,7 +608,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
local_irq_enable(); local_irq_enable();
/* 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) { if (thread_info_flags & _TIF_NOTIFY_RESUME) {

View File

@ -465,7 +465,6 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask)) if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
goto badframe; goto badframe;
sigdelsetmask(&blocked, ~_BLOCKABLE);
set_current_blocked(&blocked); set_current_blocked(&blocked);
sig = restore_sigcontext32(&regs, &frame->sf_sc); sig = restore_sigcontext32(&regs, &frame->sf_sc);
@ -503,7 +502,6 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext); sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);

View File

@ -109,7 +109,6 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask)) if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext); sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);

View File

@ -31,8 +31,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* atomically swap in the new signal mask, and wait for a signal. * atomically swap in the new signal mask, and wait for a signal.
*/ */
@ -163,7 +161,6 @@ asmlinkage long sys_sigreturn(void)
sizeof(frame->extramask))) sizeof(frame->extramask)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(current_frame(), &frame->sc, &d0)) if (restore_sigcontext(current_frame(), &frame->sc, &d0))
@ -191,7 +188,6 @@ asmlinkage long sys_rt_sigreturn(void)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0)) if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
@ -430,8 +426,9 @@ static inline void stepback(struct pt_regs *regs)
*/ */
static int handle_signal(int sig, static int handle_signal(int sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
@ -461,11 +458,11 @@ static int handle_signal(int sig,
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, oldset, regs);
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret)
return;
if (ret == 0) signal_delivered(sig, info, ka, regs,
block_sigmask(ka, sig); test_thread_flag(TIF_SINGLESTEP));
return ret;
} }
/* /*
@ -475,7 +472,6 @@ static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
siginfo_t info; siginfo_t info;
sigset_t *oldset;
int signr; int signr;
/* we want the common case to go fast, which is why we may in certain /* we want the common case to go fast, which is why we may in certain
@ -483,23 +479,9 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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) {
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { if (handle_signal(signr, &info, &ka, regs) == 0) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
return; return;
@ -525,10 +507,7 @@ static void do_signal(struct pt_regs *regs)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*
@ -548,7 +527,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, 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) { if (thread_info_flags & _TIF_NOTIFY_RESUME) {

View File

@ -33,8 +33,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
asmlinkage long asmlinkage long
_sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs) _sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
{ {
@ -101,7 +99,6 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@ -251,20 +248,19 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int static inline void
handle_signal(unsigned long sig, handle_signal(unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
sigset_t *oldset, struct pt_regs *regs) struct pt_regs *regs)
{ {
int ret; int ret;
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return 0;
} }
/* /*
@ -339,30 +335,10 @@ void do_signal(struct pt_regs *regs)
if (signr <= 0) { if (signr <= 0) {
/* no signal to deliver so we just put the saved sigmask /* no signal to deliver so we just put the saved sigmask
* back */ * back */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} else { /* signr > 0 */ } else { /* signr > 0 */
sigset_t *oldset;
if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (!handle_signal(signr, &info, &ka, oldset, regs)) { handle_signal(signr, &info, &ka, regs);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
return; return;

View File

@ -74,7 +74,7 @@ struct thread_info {
#define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) #define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP)
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
_TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK) _TIF_NEED_RESCHED)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */

View File

@ -924,7 +924,7 @@ intr_check_sig:
/* As above */ /* As above */
mfctl %cr30,%r1 mfctl %cr30,%r1
LDREG TI_FLAGS(%r1),%r19 LDREG TI_FLAGS(%r1),%r19
ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r20 ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r20
and,COND(<>) %r19, %r20, %r0 and,COND(<>) %r19, %r20, %r0
b,n intr_restore /* skip past if we've nothing to do */ b,n intr_restore /* skip past if we've nothing to do */
@ -2032,7 +2032,7 @@ syscall_check_resched:
.import do_signal,code .import do_signal,code
syscall_check_sig: syscall_check_sig:
LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19 LDREG TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
ldi (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r26 ldi (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r26
and,COND(<>) %r19, %r26, %r0 and,COND(<>) %r19, %r26, %r0
b,n syscall_restore /* skip past if we've nothing to do */ b,n syscall_restore /* skip past if we've nothing to do */

View File

@ -48,9 +48,6 @@
#define DBG(LEVEL, ...) #define DBG(LEVEL, ...)
#endif #endif
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* gcc will complain if a pointer is cast to an integer of different /* gcc will complain if a pointer is cast to an integer of different
* size. If you really need to do this (and we do for an ELF32 user * size. If you really need to do this (and we do for an ELF32 user
* application in an ELF64 kernel) then you have to do a cast to an * application in an ELF64 kernel) then you have to do a cast to an
@ -131,7 +128,6 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
goto give_sigsegv; goto give_sigsegv;
} }
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
/* Good thing we saved the old gr[30], eh? */ /* Good thing we saved the old gr[30], eh? */
@ -443,8 +439,9 @@ give_sigsegv:
static long static long
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, int in_syscall) struct pt_regs *regs, int in_syscall)
{ {
sigset_t *oldset = sigmask_to_save();
DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n", DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
sig, ka, info, oldset, regs); sig, ka, info, oldset, regs);
@ -452,12 +449,13 @@ 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;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP) || test_thread_flag(TIF_SINGLESTEP) ||
test_thread_flag(TIF_BLOCKSTEP)); test_thread_flag(TIF_BLOCKSTEP));
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
return 1; return 1;
} }
@ -568,28 +566,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
siginfo_t info; siginfo_t info;
struct k_sigaction ka; struct k_sigaction ka;
int signr; int signr;
sigset_t *oldset;
DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n", DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
oldset, regs, regs->sr[7], in_syscall); regs, regs->sr[7], in_syscall);
/* Everyone else checks to see if they are in kernel mode at /* Everyone else checks to see if they are in kernel mode at
this point and exits if that's the case. I'm not sure why this point and exits if that's the case. I'm not sure why
we would be called in that case, but for some reason we we would be called in that case, but for some reason we
are. */ are. */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
DBG(1,"do_signal: oldset %08lx / %08lx\n",
oldset->sig[0], oldset->sig[1]);
/* May need to force signal if handle_signal failed to deliver */ /* May need to force signal if handle_signal failed to deliver */
while (1) { while (1) {
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
@ -603,14 +590,8 @@ do_signal(struct pt_regs *regs, long in_syscall)
/* Whee! Actually deliver the signal. If the /* Whee! Actually deliver the signal. If the
delivery failed, we need to continue to iterate in delivery failed, we need to continue to iterate in
this loop so we can deliver the SIGSEGV... */ this loop so we can deliver the SIGSEGV... */
if (handle_signal(signr, &info, &ka, oldset, if (handle_signal(signr, &info, &ka, regs, in_syscall))
regs, in_syscall)) {
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
}
} }
/* end of while(1) looping forever if we can't force a signal */ /* end of while(1) looping forever if we can't force a signal */
@ -621,18 +602,12 @@ do_signal(struct pt_regs *regs, long in_syscall)
DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n",
regs->gr[28]); regs->gr[28]);
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return;
} }
void do_notify_resume(struct pt_regs *regs, long in_syscall) void do_notify_resume(struct pt_regs *regs, long in_syscall)
{ {
if (test_thread_flag(TIF_SIGPENDING) || if (test_thread_flag(TIF_SIGPENDING))
test_thread_flag(TIF_RESTORE_SIGMASK))
do_signal(regs, in_syscall); do_signal(regs, in_syscall);
if (test_thread_flag(TIF_NOTIFY_RESUME)) { if (test_thread_flag(TIF_NOTIFY_RESUME)) {

View File

@ -47,8 +47,6 @@
#define DBG(LEVEL, ...) #define DBG(LEVEL, ...)
#endif #endif
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
inline void inline void
sigset_32to64(sigset_t *s64, compat_sigset_t *s32) sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
{ {

View File

@ -140,7 +140,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->local_flags |= _TLF_RESTORE_SIGMASK; ti->local_flags |= _TLF_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, &ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->local_flags & _TLF_RESTORE_SIGMASK))
return false;
ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
return true;
} }
static inline bool test_thread_local_flags(unsigned int flags) static inline bool test_thread_local_flags(unsigned int flags)

View File

@ -51,16 +51,6 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
return (void __user *)newsp; return (void __user *)newsp;
} }
/*
* Restore the user process's signal mask
*/
void restore_sigmask(sigset_t *set)
{
sigdelsetmask(set, ~_BLOCKABLE);
set_current_blocked(set);
}
static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
int has_handler) int has_handler)
{ {
@ -114,30 +104,21 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
static int do_signal(struct pt_regs *regs) static int do_signal(struct pt_regs *regs)
{ {
sigset_t *oldset; sigset_t *oldset = sigmask_to_save();
siginfo_t info; siginfo_t info;
int signr; int signr;
struct k_sigaction ka; struct k_sigaction ka;
int ret; int ret;
int is32 = is_32bit_task(); int is32 = is_32bit_task();
if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* Is there any syscall restart business here ? */ /* Is there any syscall restart business here ? */
check_syscall_restart(regs, &ka, signr > 0); check_syscall_restart(regs, &ka, signr > 0);
if (signr <= 0) { if (signr <= 0) {
struct thread_info *ti = current_thread_info();
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
if (ti->local_flags & _TLF_RESTORE_SIGMASK) { restore_saved_sigmask();
ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
regs->trap = 0; regs->trap = 0;
return 0; /* no signals delivered */ return 0; /* no signals delivered */
} }
@ -167,18 +148,7 @@ static int do_signal(struct pt_regs *regs)
regs->trap = 0; regs->trap = 0;
if (ret) { if (ret) {
block_sigmask(&ka, signr); signal_delivered(signr, &info, &ka, regs,
/*
* A signal was successfully delivered; the saved sigmask is in
* its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
*/
current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
/*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP)); test_thread_flag(TIF_SINGLESTEP));
} }

View File

@ -10,13 +10,10 @@
#ifndef _POWERPC_ARCH_SIGNAL_H #ifndef _POWERPC_ARCH_SIGNAL_H
#define _POWERPC_ARCH_SIGNAL_H #define _POWERPC_ARCH_SIGNAL_H
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size, int is_32); size_t frame_size, int is_32);
extern void restore_sigmask(sigset_t *set);
extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, sigset_t *oldset,

View File

@ -919,7 +919,7 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp))) if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
return -EFAULT; return -EFAULT;
#endif #endif
restore_sigmask(&set); set_current_blocked(&set);
if (restore_user_regs(regs, mcp, sig)) if (restore_user_regs(regs, mcp, sig))
return -EFAULT; return -EFAULT;
@ -1273,7 +1273,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
set.sig[0] = sigctx.oldmask; set.sig[0] = sigctx.oldmask;
set.sig[1] = sigctx._unused[3]; set.sig[1] = sigctx._unused[3];
#endif #endif
restore_sigmask(&set); set_current_blocked(&set);
sr = (struct mcontext __user *)from_user_ptr(sigctx.regs); sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
addr = sr; addr = sr;

View File

@ -335,7 +335,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set)))
do_exit(SIGSEGV); do_exit(SIGSEGV);
restore_sigmask(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext)) if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext))
do_exit(SIGSEGV); do_exit(SIGSEGV);
@ -364,7 +364,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
restore_sigmask(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext)) if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext))
goto badframe; goto badframe;

View File

@ -32,8 +32,6 @@
#include "compat_ptrace.h" #include "compat_ptrace.h"
#include "entry.h" #include "entry.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
typedef struct typedef struct
{ {
__u8 callee_used_stack[__SIGNAL_FRAMESIZE32]; __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
@ -364,7 +362,6 @@ asmlinkage long sys32_sigreturn(void)
goto badframe; goto badframe;
if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigregs32(regs, &frame->sregs)) if (restore_sigregs32(regs, &frame->sregs))
goto badframe; goto badframe;
@ -390,7 +387,6 @@ asmlinkage long sys32_rt_sigreturn(void)
goto badframe; goto badframe;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigregs32(regs, &frame->uc.uc_mcontext)) if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
goto badframe; goto badframe;
@ -572,7 +568,7 @@ give_sigsegv:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
int handle_signal32(unsigned long sig, struct k_sigaction *ka, void handle_signal32(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; int ret;
@ -583,8 +579,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
else else
ret = setup_frame32(sig, ka, oldset, regs); ret = setup_frame32(sig, ka, oldset, regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
return 0; test_thread_flag(TIF_SINGLE_STEP));
} }

View File

@ -31,7 +31,7 @@ void do_per_trap(struct pt_regs *regs);
void syscall_trace(struct pt_regs *regs, int entryexit); void syscall_trace(struct pt_regs *regs, int entryexit);
void kernel_stack_overflow(struct pt_regs * regs); void kernel_stack_overflow(struct pt_regs * regs);
void do_signal(struct pt_regs *regs); void do_signal(struct pt_regs *regs);
int handle_signal32(unsigned long sig, struct k_sigaction *ka, void handle_signal32(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);
void do_notify_resume(struct pt_regs *regs); void do_notify_resume(struct pt_regs *regs);

View File

@ -33,9 +33,6 @@
#include <asm/switch_to.h> #include <asm/switch_to.h>
#include "entry.h" #include "entry.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
typedef struct typedef struct
{ {
__u8 callee_used_stack[__SIGNAL_FRAMESIZE]; __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
@ -169,7 +166,6 @@ SYSCALL_DEFINE0(sigreturn)
goto badframe; goto badframe;
if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE)) if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigregs(regs, &frame->sregs)) if (restore_sigregs(regs, &frame->sregs))
goto badframe; goto badframe;
@ -189,7 +185,6 @@ SYSCALL_DEFINE0(rt_sigreturn)
goto badframe; goto badframe;
if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigregs(regs, &frame->uc.uc_mcontext)) if (restore_sigregs(regs, &frame->uc.uc_mcontext))
goto badframe; goto badframe;
@ -367,7 +362,7 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
static int handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -379,9 +374,9 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
return 0; test_thread_flag(TIF_SINGLE_STEP));
} }
/* /*
@ -398,12 +393,7 @@ 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; sigset_t *oldset = sigmask_to_save();
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
/* /*
* Get signal to deliver. When running under ptrace, at this point * Get signal to deliver. When running under ptrace, at this point
@ -441,24 +431,10 @@ void do_signal(struct pt_regs *regs)
/* No longer in a system call */ /* No longer in a system call */
clear_thread_flag(TIF_SYSCALL); clear_thread_flag(TIF_SYSCALL);
if ((is_compat_task() ? if (is_compat_task())
handle_signal32(signr, &ka, &info, oldset, regs) : handle_signal32(signr, &ka, &info, oldset, regs);
handle_signal(signr, &ka, &info, oldset, regs)) == 0) { else
/* handle_signal(signr, &ka, &info, oldset, regs);
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
/*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLE_STEP));
}
return; return;
} }
@ -484,10 +460,7 @@ void do_signal(struct pt_regs *regs)
/* /*
* If there's no signal to deliver, we just put the saved sigmask back. * If there's no signal to deliver, we just put the saved sigmask back.
*/ */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
void do_notify_resume(struct pt_regs *regs) void do_notify_resume(struct pt_regs *regs)

View File

@ -34,8 +34,6 @@
#include <asm/syscalls.h> #include <asm/syscalls.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
struct rt_sigframe { struct rt_sigframe {
u32 rs_ass[4]; /* argument save space */ u32 rs_ass[4]; /* argument save space */
u32 rs_code[2]; /* signal trampoline */ u32 rs_code[2]; /* signal trampoline */
@ -162,7 +160,6 @@ score_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext); sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
@ -241,11 +238,9 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs) struct k_sigaction *ka, struct pt_regs *regs)
{ {
int ret;
if (regs->is_syscall) { if (regs->is_syscall) {
switch (regs->regs[4]) { switch (regs->regs[4]) {
case ERESTART_RESTARTBLOCK: case ERESTART_RESTARTBLOCK:
@ -269,18 +264,15 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
/* /*
* Set up the stack frame * Set up the stack frame
*/ */
ret = setup_rt_frame(ka, regs, sig, oldset, info); if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0)
return;
if (ret == 0) signal_delivered(sig, info, ka, regs, 0);
block_sigmask(ka, sig);
return ret;
} }
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
{ {
struct k_sigaction ka; struct k_sigaction ka;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
int signr; int signr;
@ -292,25 +284,10 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
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) {
/* Actually deliver the signal. */ /* Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
@ -337,10 +314,7 @@ static void do_signal(struct pt_regs *regs)
* If there's no signal to deliver, we just put the saved sigmask * If there's no signal to deliver, we just put the saved sigmask
* back * back
*/ */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
/* /*

View File

@ -169,7 +169,7 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
} }
#define TI_FLAG_FAULT_CODE_SHIFT 24 #define TI_FLAG_FAULT_CODE_SHIFT 24
@ -189,6 +189,23 @@ static inline unsigned int get_thread_fault_code(void)
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
return ti->flags >> TI_FLAG_FAULT_CODE_SHIFT; return ti->flags >> TI_FLAG_FAULT_CODE_SHIFT;
} }
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
}
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */

View File

@ -32,8 +32,6 @@
#include <asm/syscalls.h> #include <asm/syscalls.h>
#include <asm/fpu.h> #include <asm/fpu.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
struct fdpic_func_descriptor { struct fdpic_func_descriptor {
unsigned long text; unsigned long text;
unsigned long GOT; unsigned long GOT;
@ -226,7 +224,6 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, &r0)) if (restore_sigcontext(regs, &frame->sc, &r0))
@ -256,7 +253,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
@ -522,10 +518,11 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) struct pt_regs *regs, unsigned int save_r0)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Set up the stack frame */ /* Set up the stack frame */
@ -534,10 +531,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret)
block_sigmask(ka, sig); return;
signal_delivered(sig, info, ka, regs,
return ret; test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
@ -554,7 +551,6 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
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
@ -565,30 +561,12 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
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) {
handle_syscall_restart(save_r0, regs, &ka.sa); handle_syscall_restart(save_r0, regs, &ka.sa);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &ka, &info, oldset, handle_signal(signr, &ka, &info, regs, save_r0);
regs, save_r0) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }
@ -610,10 +588,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
* If there's no signal to deliver, we just put the saved sigmask * If there's no signal to deliver, we just put the saved sigmask
* back. * back.
*/ */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,

View File

@ -41,11 +41,9 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) static void
static int
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); struct pt_regs * regs);
static inline void static inline void
handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa) handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
@ -88,7 +86,6 @@ 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
@ -99,28 +96,13 @@ static void do_signal(struct pt_regs *regs)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, 0); signr = get_signal_to_deliver(&info, &ka, regs, 0);
if (signr > 0) { if (signr > 0) {
handle_syscall_restart(regs, &ka.sa); handle_syscall_restart(regs, &ka.sa);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/* return;
* If a signal was successfully delivered, the
* saved sigmask is in its frame, and we can
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
@ -143,12 +125,7 @@ static void do_signal(struct pt_regs *regs)
} }
/* No signal to deliver -- put the saved sigmask back */ /* No signal to deliver -- put the saved sigmask back */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return;
} }
/* /*
@ -351,7 +328,6 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, &ret)) if (restore_sigcontext(regs, &frame->sc, &ret))
@ -384,7 +360,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
@ -659,10 +634,11 @@ give_sigsegv:
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int 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) struct pt_regs * regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Set up the stack frame */ /* Set up the stack frame */
@ -671,10 +647,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret)
block_sigmask(ka, sig); return;
return ret; signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
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)

View File

@ -131,8 +131,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \ #define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \
_TIF_SIGPENDING | \ _TIF_SIGPENDING)
_TIF_RESTORE_SIGMASK)
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */

View File

@ -238,7 +238,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, &ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -32,8 +32,6 @@
#include "sigutil.h" #include "sigutil.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* This magic should be in g_upper[0] for all upper parts /* This magic should be in g_upper[0] for all upper parts
* to be valid. * to be valid.
*/ */
@ -274,7 +272,6 @@ void do_sigreturn32(struct pt_regs *regs)
case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);
case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
} }
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
return; return;
@ -376,7 +373,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32); case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32);
case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
} }
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
return; return;
segv: segv:
@ -775,7 +771,7 @@ sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
@ -787,12 +783,9 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
err = setup_frame32(ka, regs, signr, oldset); err = setup_frame32(ka, regs, signr, oldset);
if (err) if (err)
return err; return;
block_sigmask(ka, signr); signal_delivered(signr, info, ka, regs, 0);
tracehook_signal_handler(signr, info, ka, regs, 0);
return 0;
} }
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
@ -841,14 +834,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)
if (signr > 0) { if (signr > 0) {
if (restart_syscall) if (restart_syscall)
syscall_restart32(orig_i0, regs, &ka.sa); syscall_restart32(orig_i0, regs, &ka.sa);
if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { handle_signal32(signr, &ka, &info, oldset, regs);
/* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
return; return;
} }
if (restart_syscall && if (restart_syscall &&
@ -872,10 +858,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)
/* If there's no signal to deliver, we just put the saved sigmask /* If there's no signal to deliver, we just put the saved sigmask
* back * back
*/ */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
set_current_blocked(&current->saved_sigmask);
}
} }
struct sigstack32 { struct sigstack32 {

View File

@ -29,8 +29,6 @@
#include "sigutil.h" #include "sigutil.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern void fpsave(unsigned long *fpregs, unsigned long *fsr, extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
void *fpqueue, unsigned long *fpqdepth); void *fpqueue, unsigned long *fpqdepth);
extern void fpload(unsigned long *fpregs, unsigned long *fsr); extern void fpload(unsigned long *fpregs, unsigned long *fsr);
@ -130,7 +128,6 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
if (err) if (err)
goto segv_and_exit; goto segv_and_exit;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
return; return;
@ -197,7 +194,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
goto segv; goto segv;
} }
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
return; return;
segv: segv:
@ -449,10 +445,11 @@ sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int static inline void
handle_signal(unsigned long signr, struct k_sigaction *ka, handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) siginfo_t *info, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int err; int err;
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
@ -461,12 +458,9 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
err = setup_frame(ka, regs, signr, oldset); err = setup_frame(ka, regs, signr, oldset);
if (err) if (err)
return err; return;
block_sigmask(ka, signr); signal_delivered(signr, info, ka, regs, 0);
tracehook_signal_handler(signr, info, ka, regs, 0);
return 0;
} }
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@ -498,7 +492,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
{ {
struct k_sigaction ka; struct k_sigaction ka;
int restart_syscall; int restart_syscall;
sigset_t *oldset;
siginfo_t info; siginfo_t info;
int signr; int signr;
@ -523,11 +516,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
regs->u_regs[UREG_G6] = orig_i0; regs->u_regs[UREG_G6] = orig_i0;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* If the debugger messes with the program counter, it clears /* If the debugger messes with the program counter, it clears
@ -544,15 +532,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
if (signr > 0) { if (signr > 0) {
if (restart_syscall) if (restart_syscall)
syscall_restart(orig_i0, regs, &ka.sa); syscall_restart(orig_i0, regs, &ka.sa);
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { handle_signal(signr, &ka, &info, regs);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
if (restart_syscall && if (restart_syscall &&
@ -576,16 +556,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
/* if there's no signal to deliver, we just put the saved sigmask /* if there's no signal to deliver, we just put the saved sigmask
* back * back
*/ */
if (test_thread_flag(TIF_RESTORE_SIGMASK)) { restore_saved_sigmask();
clear_thread_flag(TIF_RESTORE_SIGMASK);
set_current_blocked(&current->saved_sigmask);
}
} }
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
unsigned long thread_info_flags) unsigned long thread_info_flags)
{ {
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(regs, orig_i0); do_signal(regs, orig_i0);
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);

View File

@ -38,8 +38,6 @@
#include "systbls.h" #include "systbls.h"
#include "sigutil.h" #include "sigutil.h"
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* {set, get}context() needed for 64-bit SparcLinux userland. */ /* {set, get}context() needed for 64-bit SparcLinux userland. */
asmlinkage void sparc64_set_context(struct pt_regs *regs) asmlinkage void sparc64_set_context(struct pt_regs *regs)
{ {
@ -71,7 +69,6 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t))) if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t)))
goto do_sigsegv; goto do_sigsegv;
} }
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
} }
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
@ -315,7 +312,6 @@ void do_rt_sigreturn(struct pt_regs *regs)
/* Prevent syscall restart. */ /* Prevent syscall restart. */
pt_regs_clear_syscall(regs); pt_regs_clear_syscall(regs);
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
return; return;
segv: segv:
@ -466,7 +462,7 @@ sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
@ -475,12 +471,9 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
err = setup_rt_frame(ka, regs, signr, oldset, err = setup_rt_frame(ka, regs, signr, oldset,
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
if (err) if (err)
return err; return;
block_sigmask(ka, signr); signal_delivered(signr, info, ka, regs, 0);
tracehook_signal_handler(signr, info, ka, regs, 0);
return 0;
} }
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@ -512,7 +505,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
{ {
struct k_sigaction ka; struct k_sigaction ka;
int restart_syscall; int restart_syscall;
sigset_t *oldset; sigset_t *oldset = sigmask_to_save();
siginfo_t info; siginfo_t info;
int signr; int signr;
@ -538,11 +531,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
regs->u_regs[UREG_G6] = orig_i0; regs->u_regs[UREG_G6] = orig_i0;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
if (test_thread_flag(TIF_32BIT)) { if (test_thread_flag(TIF_32BIT)) {
extern void do_signal32(sigset_t *, struct pt_regs *); extern void do_signal32(sigset_t *, struct pt_regs *);
@ -563,14 +551,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
if (signr > 0) { if (signr > 0) {
if (restart_syscall) if (restart_syscall)
syscall_restart(orig_i0, regs, &ka.sa); syscall_restart(orig_i0, regs, &ka.sa);
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { handle_signal(signr, &ka, &info, oldset, regs);
/* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
return; return;
} }
if (restart_syscall && if (restart_syscall &&
@ -594,10 +575,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
/* If there's no signal to deliver, we just put the saved sigmask /* If there's no signal to deliver, we just put the saved sigmask
* back * back
*/ */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
set_current_blocked(&current->saved_sigmask);
}
} }
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)

View File

@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, &ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
#endif /* !__ASSEMBLY__ */ #endif /* !__ASSEMBLY__ */

View File

@ -118,8 +118,6 @@ struct compat_rt_sigframe {
struct compat_ucontext uc; struct compat_ucontext uc;
}; };
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act, long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
struct compat_sigaction __user *oact, struct compat_sigaction __user *oact,
size_t sigsetsize) size_t sigsetsize)
@ -302,7 +300,6 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))

View File

@ -37,8 +37,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss, SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
stack_t __user *, uoss, struct pt_regs *, regs) stack_t __user *, uoss, struct pt_regs *, regs)
{ {
@ -96,7 +94,6 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@ -242,10 +239,11 @@ give_sigsegv:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, sigset_t *oldset, struct k_sigaction *ka,
struct pt_regs *regs) struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save();
int ret; int ret;
/* Are we from a system call? */ /* Are we from a system call? */
@ -278,15 +276,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
else else
#endif #endif
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, oldset, regs);
if (ret == 0) { if (ret)
/* This code is only called from system calls or from return;
* the work_pending path in the return-to-user code, and signal_delivered(sig, info, ka, regs, 0);
* either way we can re-enable interrupts unconditionally.
*/
block_sigmask(ka, sig);
}
return ret;
} }
/* /*
@ -299,7 +291,6 @@ 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;
/* /*
* i386 will check if we're coming from kernel mode and bail out * i386 will check if we're coming from kernel mode and bail out
@ -308,24 +299,10 @@ void do_signal(struct pt_regs *regs)
* helpful, we can reinstate the check on "!user_mode(regs)". * helpful, we can reinstate the check on "!user_mode(regs)".
*/ */
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
oldset = &current->saved_sigmask;
else
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. */
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
goto done; goto done;
} }
@ -350,10 +327,7 @@ void do_signal(struct pt_regs *regs)
} }
/* If there's no signal to deliver, just put the saved sigmask back. */ /* If there's no signal to deliver, just put the saved sigmask back. */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
done: done:
/* Avoid double syscall restart if there are nested signals. */ /* Avoid double syscall restart if there are nested signals. */

View File

@ -6,9 +6,6 @@
#ifndef __FRAME_KERN_H_ #ifndef __FRAME_KERN_H_
#define __FRAME_KERN_H_ #define __FRAME_KERN_H_
#define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
extern int setup_signal_stack_sc(unsigned long stack_top, int sig, extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
struct k_sigaction *ka, struct k_sigaction *ka,
struct pt_regs *regs, struct pt_regs *regs,

View File

@ -15,17 +15,13 @@
EXPORT_SYMBOL(block_signals); EXPORT_SYMBOL(block_signals);
EXPORT_SYMBOL(unblock_signals); EXPORT_SYMBOL(unblock_signals);
#define _S(nr) (1<<((nr)-1))
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(struct pt_regs *regs, unsigned long signr, static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka, siginfo_t *info)
sigset_t *oldset)
{ {
sigset_t *oldset = sigmask_to_save();
unsigned long sp; unsigned long sp;
int err; int err;
@ -65,9 +61,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
if (err) if (err)
force_sigsegv(signr, current); force_sigsegv(signr, current);
else else
block_sigmask(ka, signr); signal_delivered(signr, info, ka, regs, 0);
return err;
} }
static int kern_do_signal(struct pt_regs *regs) static int kern_do_signal(struct pt_regs *regs)
@ -77,24 +71,9 @@ static int kern_do_signal(struct pt_regs *regs)
int sig, handled_sig = 0; int sig, handled_sig = 0;
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
sigset_t *oldset;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
handled_sig = 1; handled_sig = 1;
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) { handle_signal(regs, sig, &ka_copy, &info);
/*
* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
break;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */
@ -130,10 +109,8 @@ static int kern_do_signal(struct pt_regs *regs)
* if there's no signal to deliver, we just put the saved sigmask * if there's no signal to deliver, we just put the saved sigmask
* back * back
*/ */
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { if (!handled_sig)
clear_thread_flag(TIF_RESTORE_SIGMASK); restore_saved_sigmask();
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
}
return handled_sig; return handled_sig;
} }

View File

@ -21,8 +21,6 @@
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/ucontext.h> #include <asm/ucontext.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
/* /*
* For UniCore syscalls, we encode the syscall number into the instruction. * For UniCore syscalls, we encode the syscall number into the instruction.
*/ */
@ -61,10 +59,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
int err; int err;
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
if (err == 0) { if (err == 0)
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
}
err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00); err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01); err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
@ -312,13 +308,12 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, struct pt_regs *regs, int syscall)
struct pt_regs *regs, int syscall)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
struct task_struct *tsk = current; struct task_struct *tsk = current;
sigset_t blocked; sigset_t *oldset = sigmask_to_save();
int usig = sig; int usig = sig;
int ret; int ret;
@ -364,15 +359,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
if (ret != 0) { if (ret != 0) {
force_sigsegv(sig, tsk); force_sigsegv(sig, tsk);
return ret; return;
} }
/* signal_delivered(sig, info, ka, regs, 0);
* Block the signal if we were successful.
*/
block_sigmask(ka, sig);
return 0;
} }
/* /*
@ -399,32 +389,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
if (!user_mode(regs)) if (!user_mode(regs))
return; return;
if (try_to_freeze())
goto no_signal;
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
sigset_t *oldset; handle_signal(signr, &ka, &info, regs, syscall);
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
if (handle_signal(signr, &ka, &info, oldset, regs, syscall)
== 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
no_signal:
/* /*
* No signal to deliver to the process - restart the syscall. * No signal to deliver to the process - restart the syscall.
*/ */
@ -451,8 +421,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
/* If there's no signal to deliver, we just put the saved /* If there's no signal to deliver, we just put the saved
* sigmask back. * sigmask back.
*/ */
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) restore_saved_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,

View File

@ -273,7 +273,6 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (ia32_restore_sigcontext(regs, &frame->sc, &ax)) if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
@ -299,7 +298,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))

View File

@ -7,8 +7,6 @@
#include <asm/processor-flags.h> #include <asm/processor-flags.h>
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
#define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \ #define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \ X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \ X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \

View File

@ -248,7 +248,23 @@ static inline void set_restore_sigmask(void)
{ {
struct thread_info *ti = current_thread_info(); struct thread_info *ti = current_thread_info();
ti->status |= TS_RESTORE_SIGMASK; ti->status |= TS_RESTORE_SIGMASK;
set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags); WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
}
static inline void clear_restore_sigmask(void)
{
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
static inline bool test_restore_sigmask(void)
{
return current_thread_info()->status & TS_RESTORE_SIGMASK;
}
static inline bool test_and_clear_restore_sigmask(void)
{
struct thread_info *ti = current_thread_info();
if (!(ti->status & TS_RESTORE_SIGMASK))
return false;
ti->status &= ~TS_RESTORE_SIGMASK;
return true;
} }
static inline bool is_ia32_task(void) static inline bool is_ia32_task(void)

View File

@ -316,7 +316,6 @@ ret_from_exception:
preempt_stop(CLBR_ANY) preempt_stop(CLBR_ANY)
ret_from_intr: ret_from_intr:
GET_THREAD_INFO(%ebp) GET_THREAD_INFO(%ebp)
resume_userspace_sig:
#ifdef CONFIG_VM86 #ifdef CONFIG_VM86
movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
movb PT_CS(%esp), %al movb PT_CS(%esp), %al
@ -615,9 +614,13 @@ work_notifysig: # deal with pending signals and
# vm86-space # vm86-space
TRACE_IRQS_ON TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE) ENABLE_INTERRUPTS(CLBR_NONE)
movb PT_CS(%esp), %bl
andb $SEGMENT_RPL_MASK, %bl
cmpb $USER_RPL, %bl
jb resume_kernel
xorl %edx, %edx xorl %edx, %edx
call do_notify_resume call do_notify_resume
jmp resume_userspace_sig jmp resume_userspace
ALIGN ALIGN
work_notifysig_v86: work_notifysig_v86:
@ -630,9 +633,13 @@ work_notifysig_v86:
#endif #endif
TRACE_IRQS_ON TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE) ENABLE_INTERRUPTS(CLBR_NONE)
movb PT_CS(%esp), %bl
andb $SEGMENT_RPL_MASK, %bl
cmpb $USER_RPL, %bl
jb resume_kernel
xorl %edx, %edx xorl %edx, %edx
call do_notify_resume call do_notify_resume
jmp resume_userspace_sig jmp resume_userspace
END(work_pending) END(work_pending)
# perform syscall exit tracing # perform syscall exit tracing

View File

@ -555,7 +555,6 @@ unsigned long sys_sigreturn(struct pt_regs *regs)
sizeof(frame->extramask)))) sizeof(frame->extramask))))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->sc, &ax)) if (restore_sigcontext(regs, &frame->sc, &ax))
@ -581,7 +580,6 @@ long sys_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
@ -647,42 +645,28 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
struct pt_regs *regs) struct pt_regs *regs)
{ {
int usig = signr_convert(sig); int usig = signr_convert(sig);
sigset_t *set = &current->blocked; sigset_t *set = sigmask_to_save();
int ret;
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
set = &current->saved_sigmask;
/* Set up the stack frame */ /* Set up the stack frame */
if (is_ia32) { if (is_ia32) {
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
ret = ia32_setup_rt_frame(usig, ka, info, set, regs); return ia32_setup_rt_frame(usig, ka, info, set, regs);
else else
ret = ia32_setup_frame(usig, ka, set, regs); return ia32_setup_frame(usig, ka, set, regs);
#ifdef CONFIG_X86_X32_ABI #ifdef CONFIG_X86_X32_ABI
} else if (is_x32) { } else if (is_x32) {
ret = x32_setup_rt_frame(usig, ka, info, return x32_setup_rt_frame(usig, ka, info,
(compat_sigset_t *)set, regs); (compat_sigset_t *)set, regs);
#endif #endif
} else { } else {
ret = __setup_rt_frame(sig, ka, info, set, regs); return __setup_rt_frame(sig, ka, info, set, regs);
} }
if (ret) {
force_sigsegv(sig, current);
return -EFAULT;
}
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
return ret;
} }
static int 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,
struct pt_regs *regs) struct pt_regs *regs)
{ {
int ret;
/* Are we from a system call? */ /* Are we from a system call? */
if (syscall_get_nr(current, regs) >= 0) { if (syscall_get_nr(current, regs) >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
@ -713,10 +697,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
likely(test_and_clear_thread_flag(TIF_FORCED_TF))) likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
regs->flags &= ~X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_TF;
ret = setup_rt_frame(sig, ka, info, regs); if (setup_rt_frame(sig, ka, info, regs) < 0) {
force_sigsegv(sig, current);
if (ret) return;
return ret; }
/* /*
* Clear the direction flag as per the ABI for function entry. * Clear the direction flag as per the ABI for function entry.
@ -731,12 +715,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
*/ */
regs->flags &= ~X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_TF;
block_sigmask(ka, sig); signal_delivered(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return 0;
} }
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
@ -757,16 +737,6 @@ static void do_signal(struct pt_regs *regs)
siginfo_t info; siginfo_t info;
int signr; int signr;
/*
* 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.
* X86_32: vm86 regs switched out by assembly code before reaching
* here, so testing against kernel CS suffices.
*/
if (!user_mode(regs))
return;
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. */
@ -796,10 +766,7 @@ static void do_signal(struct pt_regs *regs)
* If there's no signal to deliver, we just put the saved sigmask * If there's no signal to deliver, we just put the saved sigmask
* back. * back.
*/ */
if (current_thread_info()->status & TS_RESTORE_SIGMASK) { restore_saved_sigmask();
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
set_current_blocked(&current->saved_sigmask);
}
} }
/* /*
@ -934,7 +901,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax)) if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))

View File

@ -486,7 +486,6 @@ long sys_sigreturn(struct pt_regs *regs)
copy_from_user(&set.sig[1], extramask, sig_size)) copy_from_user(&set.sig[1], extramask, sig_size))
goto segfault; goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (copy_sc_from_user(&current->thread.regs, sc)) if (copy_sc_from_user(&current->thread.regs, sc))
@ -600,7 +599,6 @@ long sys_rt_sigreturn(struct pt_regs *regs)
if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set))) if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
goto segfault; goto segfault;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext)) if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))

View File

@ -30,8 +30,6 @@
#define DEBUG_SIG 0 #define DEBUG_SIG 0
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
extern struct task_struct *coproc_owners[]; extern struct task_struct *coproc_owners[];
struct rt_sigframe struct rt_sigframe
@ -261,7 +259,6 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto badframe; goto badframe;
sigdelsetmask(&set, ~_BLOCKABLE);
set_current_blocked(&set); set_current_blocked(&set);
if (restore_sigcontext(regs, frame)) if (restore_sigcontext(regs, frame))
@ -452,15 +449,6 @@ 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 (try_to_freeze())
goto no_signal;
if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;
else
oldset = &current->blocked;
task_pt_regs(current)->icountlevel = 0; task_pt_regs(current)->icountlevel = 0;
@ -501,19 +489,17 @@ static void do_signal(struct pt_regs *regs)
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_frame(signr, &ka, &info, oldset, regs); ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs);
if (ret) if (ret)
return; return;
clear_thread_flag(TIF_RESTORE_SIGMASK); signal_delivered(signr, info, ka, regs, 0);
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; return;
} }
no_signal:
/* Did we come from a system call? */ /* Did we come from a system call? */
if ((signed) regs->syscall >= 0) { if ((signed) regs->syscall >= 0) {
/* Restart the system call - no handlers present */ /* Restart the system call - no handlers present */
@ -532,8 +518,7 @@ no_signal:
} }
/* 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_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) restore_saved_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;

View File

@ -1542,7 +1542,6 @@ asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg)
compat_ptr(a.exp), compat_ptr(a.tvp)); compat_ptr(a.exp), compat_ptr(a.tvp));
} }
#ifdef HAVE_SET_RESTORE_SIGMASK
static long do_compat_pselect(int n, compat_ulong_t __user *inp, static long do_compat_pselect(int n, compat_ulong_t __user *inp,
compat_ulong_t __user *outp, compat_ulong_t __user *exp, compat_ulong_t __user *outp, compat_ulong_t __user *exp,
struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
@ -1665,11 +1664,9 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
return ret; return ret;
} }
#endif /* HAVE_SET_RESTORE_SIGMASK */
#ifdef CONFIG_EPOLL #ifdef CONFIG_EPOLL
#ifdef HAVE_SET_RESTORE_SIGMASK
asmlinkage long compat_sys_epoll_pwait(int epfd, asmlinkage long compat_sys_epoll_pwait(int epfd,
struct compat_epoll_event __user *events, struct compat_epoll_event __user *events,
int maxevents, int timeout, int maxevents, int timeout,
@ -1713,7 +1710,6 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
return err; return err;
} }
#endif /* HAVE_SET_RESTORE_SIGMASK */
#endif /* CONFIG_EPOLL */ #endif /* CONFIG_EPOLL */

View File

@ -1853,8 +1853,6 @@ error_return:
return error; return error;
} }
#ifdef HAVE_SET_RESTORE_SIGMASK
/* /*
* Implement the event wait interface for the eventpoll file. It is the kernel * Implement the event wait interface for the eventpoll file. It is the kernel
* part of the user space epoll_pwait(2). * part of the user space epoll_pwait(2).
@ -1899,8 +1897,6 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
return error; return error;
} }
#endif /* HAVE_SET_RESTORE_SIGMASK */
static int __init eventpoll_init(void) static int __init eventpoll_init(void)
{ {
struct sysinfo si; struct sysinfo si;

View File

@ -614,7 +614,6 @@ SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
return ret; return ret;
} }
#ifdef HAVE_SET_RESTORE_SIGMASK
static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
fd_set __user *exp, struct timespec __user *tsp, fd_set __user *exp, struct timespec __user *tsp,
const sigset_t __user *sigmask, size_t sigsetsize) const sigset_t __user *sigmask, size_t sigsetsize)
@ -686,7 +685,6 @@ SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize); return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize);
} }
#endif /* HAVE_SET_RESTORE_SIGMASK */
#ifdef __ARCH_WANT_SYS_OLD_SELECT #ifdef __ARCH_WANT_SYS_OLD_SELECT
struct sel_arg_struct { struct sel_arg_struct {
@ -941,7 +939,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
return ret; return ret;
} }
#ifdef HAVE_SET_RESTORE_SIGMASK
SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
struct timespec __user *, tsp, const sigset_t __user *, sigmask, struct timespec __user *, tsp, const sigset_t __user *, sigmask,
size_t, sigsetsize) size_t, sigsetsize)
@ -992,4 +989,3 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
return ret; return ret;
} }
#endif /* HAVE_SET_RESTORE_SIGMASK */

View File

@ -2207,6 +2207,20 @@ extern int send_sigqueue(struct sigqueue *, struct task_struct *, int group);
extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *); extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long); extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
static inline void restore_saved_sigmask(void)
{
if (test_and_clear_restore_sigmask())
__set_current_blocked(&current->saved_sigmask);
}
static inline sigset_t *sigmask_to_save(void)
{
sigset_t *res = &current->blocked;
if (unlikely(test_restore_sigmask()))
res = &current->saved_sigmask;
return res;
}
static inline int kill_cad_pid(int sig, int priv) static inline int kill_cad_pid(int sig, int priv)
{ {
return kill_pid(cad_pid, sig, priv); return kill_pid(cad_pid, sig, priv);

View File

@ -250,12 +250,13 @@ extern long do_sigpending(void __user *, unsigned long);
extern int do_sigtimedwait(const sigset_t *, siginfo_t *, extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
const struct timespec *); const struct timespec *);
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(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 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 signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping);
extern void exit_signals(struct task_struct *tsk); extern void exit_signals(struct task_struct *tsk);
extern struct kmem_cache *sighand_cachep; extern struct kmem_cache *sighand_cachep;

View File

@ -8,6 +8,7 @@
#define _LINUX_THREAD_INFO_H #define _LINUX_THREAD_INFO_H
#include <linux/types.h> #include <linux/types.h>
#include <linux/bug.h>
struct timespec; struct timespec;
struct compat_timespec; struct compat_timespec;
@ -125,10 +126,26 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
static inline void set_restore_sigmask(void) static inline void set_restore_sigmask(void)
{ {
set_thread_flag(TIF_RESTORE_SIGMASK); set_thread_flag(TIF_RESTORE_SIGMASK);
set_thread_flag(TIF_SIGPENDING); WARN_ON(!test_thread_flag(TIF_SIGPENDING));
}
static inline void clear_restore_sigmask(void)
{
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
static inline bool test_restore_sigmask(void)
{
return test_thread_flag(TIF_RESTORE_SIGMASK);
}
static inline bool test_and_clear_restore_sigmask(void)
{
return test_and_clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
#endif /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */ #endif /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */
#ifndef HAVE_SET_RESTORE_SIGMASK
#error "no set_restore_sigmask() provided and default one won't work"
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _LINUX_THREAD_INFO_H */ #endif /* _LINUX_THREAD_INFO_H */

View File

@ -2368,24 +2368,34 @@ relock:
} }
/** /**
* block_sigmask - add @ka's signal mask to current->blocked * signal_delivered -
* @ka: action for @signr * @sig: number of signal being delivered
* @signr: signal that has been successfully delivered * @info: siginfo_t of signal being delivered
* @ka: sigaction setting that chose the handler
* @regs: user register state
* @stepping: nonzero if debugger single-step or block-step in use
* *
* This function should be called when a signal has succesfully been * This function should be called when a signal has succesfully been
* delivered. It adds the mask of signals for @ka to current->blocked * delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask
* so that they are blocked during the execution of the signal * is always blocked, and the signal itself is blocked unless %SA_NODEFER
* handler. In addition, @signr will be blocked unless %SA_NODEFER is * is set in @ka->sa.sa_flags. Tracing is notified.
* set in @ka->sa.sa_flags.
*/ */
void block_sigmask(struct k_sigaction *ka, int signr) void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs, int stepping)
{ {
sigset_t blocked; sigset_t blocked;
/* 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_restore_sigmask();
sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask); sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER)) if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&blocked, signr); sigaddset(&blocked, sig);
set_current_blocked(&blocked); set_current_blocked(&blocked);
tracehook_signal_handler(sig, info, ka, regs, stepping);
} }
/* /*
@ -2518,7 +2528,16 @@ static void __set_task_blocked(struct task_struct *tsk, const sigset_t *newset)
* It is wrong to change ->blocked directly, this helper should be used * It is wrong to change ->blocked directly, this helper should be used
* to ensure the process can't miss a shared signal we are going to block. * to ensure the process can't miss a shared signal we are going to block.
*/ */
void set_current_blocked(const sigset_t *newset) void set_current_blocked(sigset_t *newset)
{
struct task_struct *tsk = current;
sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP));
spin_lock_irq(&tsk->sighand->siglock);
__set_task_blocked(tsk, newset);
spin_unlock_irq(&tsk->sighand->siglock);
}
void __set_current_blocked(const sigset_t *newset)
{ {
struct task_struct *tsk = current; struct task_struct *tsk = current;
@ -2558,7 +2577,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
return -EINVAL; return -EINVAL;
} }
set_current_blocked(&newset); __set_current_blocked(&newset);
return 0; return 0;
} }
@ -3132,7 +3151,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
return -EINVAL; return -EINVAL;
} }
set_current_blocked(&new_blocked); __set_current_blocked(&new_blocked);
} }
if (oset) { if (oset) {
@ -3196,7 +3215,6 @@ SYSCALL_DEFINE1(ssetmask, int, newmask)
int old = current->blocked.sig[0]; int old = current->blocked.sig[0];
sigset_t newset; sigset_t newset;
siginitset(&newset, newmask & ~(sigmask(SIGKILL) | sigmask(SIGSTOP)));
set_current_blocked(&newset); set_current_blocked(&newset);
return old; return old;
@ -3235,11 +3253,8 @@ SYSCALL_DEFINE0(pause)
#endif #endif
#ifdef HAVE_SET_RESTORE_SIGMASK
int sigsuspend(sigset_t *set) int sigsuspend(sigset_t *set)
{ {
sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP));
current->saved_sigmask = current->blocked; current->saved_sigmask = current->blocked;
set_current_blocked(set); set_current_blocked(set);
@ -3248,7 +3263,6 @@ int sigsuspend(sigset_t *set)
set_restore_sigmask(); set_restore_sigmask();
return -ERESTARTNOHAND; return -ERESTARTNOHAND;
} }
#endif
#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
/** /**