mirror of
https://github.com/torvalds/linux.git
synced 2024-11-25 21:51:40 +00:00
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:
commit
86c47b70f6
@ -226,7 +226,6 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
|
||||
if (__get_user(set.sig[0], &sc->sc_mask))
|
||||
goto give_sigsegv;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto give_sigsegv;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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,
|
||||
struct pt_regs * regs, struct switch_stack *sw)
|
||||
{
|
||||
sigset_t *oldset = ¤t->blocked;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
|
||||
if (ka->sa.sa_flags & SA_SIGINFO)
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
|
||||
else
|
||||
@ -483,12 +478,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
force_sigsegv(sig, current);
|
||||
return;
|
||||
}
|
||||
block_sigmask(ka, sig);
|
||||
/* A signal was successfully delivered, and the
|
||||
saved sigmask was stored on the signal frame,
|
||||
and will be restored by sigreturn. So we can
|
||||
simply clear the restore sigmask flag. */
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
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 (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
|
||||
restore_saved_sigmask();
|
||||
if (single_stepping)
|
||||
ptrace_set_bpt(current); /* re-set breakpoint */
|
||||
}
|
||||
|
@ -22,8 +22,6 @@
|
||||
|
||||
#include "signal.h"
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
|
||||
if (err == 0) {
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
if (err == 0)
|
||||
set_current_blocked(&set);
|
||||
}
|
||||
|
||||
__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);
|
||||
@ -528,13 +524,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
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)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
struct task_struct *tsk = current;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int usig = sig;
|
||||
int ret;
|
||||
|
||||
@ -559,17 +555,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
|
||||
if (ret != 0) {
|
||||
force_sigsegv(sig, tsk);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Block the signal if we were successful.
|
||||
*/
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
tracehook_signal_handler(sig, info, ka, regs, 0);
|
||||
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -617,8 +605,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
*/
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* Depending on the signal settings we may need to revert the
|
||||
* 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);
|
||||
}
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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);
|
||||
}
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -663,11 +636,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
set_thread_flag(TIF_SYSCALL_RESTARTSYS);
|
||||
}
|
||||
|
||||
/* If there's no signal to deliver, we just put the saved sigmask
|
||||
* back.
|
||||
*/
|
||||
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
asmlinkage void
|
||||
|
@ -281,7 +281,7 @@ syscall_exit_work:
|
||||
ld.w r1, r0[TI_flags]
|
||||
rjmp 1b
|
||||
|
||||
2: mov r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
|
||||
2: mov r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
|
||||
tst r1, r2
|
||||
breq 3f
|
||||
unmask_interrupts
|
||||
@ -587,7 +587,7 @@ fault_exit_work:
|
||||
ld.w r1, r0[TI_flags]
|
||||
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
|
||||
breq 2f
|
||||
unmask_interrupts
|
||||
|
@ -22,8 +22,6 @@
|
||||
#include <asm/ucontext.h>
|
||||
#include <asm/syscalls.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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
|
||||
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;
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
ret |= !valid_user_regs(regs);
|
||||
|
||||
if (ret != 0) {
|
||||
force_sigsegv(sig, current);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Block the signal if we were successful.
|
||||
*/
|
||||
block_sigmask(ka, sig);
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
if (ret != 0)
|
||||
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
|
||||
* 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;
|
||||
int signr;
|
||||
@ -267,12 +261,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
|
||||
* without doing anything if so.
|
||||
*/
|
||||
if (!user_mode(regs))
|
||||
return 0;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else if (!oldset)
|
||||
oldset = ¤t->blocked;
|
||||
return;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (syscall) {
|
||||
@ -297,15 +286,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
|
||||
|
||||
if (signr == 0) {
|
||||
/* No signal to deliver -- put the saved sigmask back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
return 0;
|
||||
restore_saved_sigmask();
|
||||
return;
|
||||
}
|
||||
|
||||
handle_signal(signr, &ka, &info, oldset, regs, syscall);
|
||||
return 1;
|
||||
handle_signal(signr, &ka, &info, regs, syscall);
|
||||
}
|
||||
|
||||
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)
|
||||
syscall = 1;
|
||||
|
||||
if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
do_signal(regs, ¤t->blocked, syscall);
|
||||
if (ti->flags & _TIF_SIGPENDING))
|
||||
do_signal(regs, syscall);
|
||||
|
||||
if (ti->flags & _TIF_NOTIFY_RESUME) {
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
|
@ -100,7 +100,6 @@ static inline struct thread_info *current_thread_info(void)
|
||||
TIF_NEED_RESCHED */
|
||||
#define TIF_MEMDIE 4 /* is terminating due to OOM killer */
|
||||
#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_NOTIFY_RESUME 8 /* callback before returning to user */
|
||||
#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_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
|
||||
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
|
||||
#define _TIF_FREEZE (1<<TIF_FREEZE)
|
||||
#define _TIF_IRQ_SYNC (1<<TIF_IRQ_SYNC)
|
||||
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
|
||||
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include <asm/fixed_code.h>
|
||||
#include <asm/syscall.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/* Location of the trace bit in SYSCFG. */
|
||||
#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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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));
|
||||
|
||||
if (err)
|
||||
goto give_sigsegv;
|
||||
return -EFAULT;
|
||||
|
||||
/* Set up registers for signal handler */
|
||||
wrusp((unsigned long)frame);
|
||||
if (current->personality & FDPIC_FUNCPTRS) {
|
||||
struct fdpic_func_descriptor __user *funcptr =
|
||||
(struct fdpic_func_descriptor *) ka->sa.sa_handler;
|
||||
__get_user(regs->pc, &funcptr->text);
|
||||
__get_user(regs->p3, &funcptr->GOT);
|
||||
u32 pc, p3;
|
||||
err |= __get_user(pc, &funcptr->text);
|
||||
err |= __get_user(p3, &funcptr->GOT);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
regs->pc = pc;
|
||||
regs->p3 = p3;
|
||||
} else
|
||||
regs->pc = (unsigned long)ka->sa.sa_handler;
|
||||
wrusp((unsigned long)frame);
|
||||
regs->rets = SIGRETURN_STUB;
|
||||
|
||||
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);
|
||||
|
||||
return 0;
|
||||
|
||||
give_sigsegv:
|
||||
force_sigsegv(sig, current);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
static int
|
||||
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 ret;
|
||||
|
||||
/* are we from a system call? to see pt_regs->orig_p0 */
|
||||
if (regs->orig_p0 >= 0)
|
||||
/* If so, check system call restarting.. */
|
||||
handle_restart(regs, ka, 1);
|
||||
|
||||
/* set up the stack frame */
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
|
||||
force_sigsegv(sig, current);
|
||||
else
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -281,37 +276,16 @@ asmlinkage void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
current->thread.esp0 = (unsigned long)regs;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &info, &ka, 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);
|
||||
|
||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (regs->orig_p0 >= 0)
|
||||
/* 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
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -330,7 +301,7 @@ asmlinkage void do_signal(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);
|
||||
|
||||
if (test_thread_flag(TIF_NOTIFY_RESUME)) {
|
||||
|
@ -711,8 +711,6 @@ ENTRY(_system_call)
|
||||
jump .Lresume_userspace_1;
|
||||
|
||||
.Lsyscall_sigpending:
|
||||
cc = BITTST(r7, TIF_RESTORE_SIGMASK);
|
||||
if cc jump .Lsyscall_do_signals;
|
||||
cc = BITTST(r7, TIF_SIGPENDING);
|
||||
if cc jump .Lsyscall_do_signals;
|
||||
cc = BITTST(r7, TIF_NOTIFY_RESUME);
|
||||
|
@ -20,8 +20,6 @@
|
||||
#include <asm/cacheflush.h>
|
||||
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* 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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
@ -248,10 +245,9 @@ do_restart:
|
||||
/*
|
||||
* 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,
|
||||
sigset_t *oldset, struct pt_regs *regs,
|
||||
int syscall)
|
||||
struct pt_regs *regs, int syscall)
|
||||
{
|
||||
int ret;
|
||||
|
||||
@ -278,11 +274,9 @@ static int handle_signal(int sig,
|
||||
}
|
||||
|
||||
/* Set up the stack frame */
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -292,7 +286,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
sigset_t *oldset;
|
||||
int signr;
|
||||
|
||||
/* 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))
|
||||
return;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (handle_signal(signr, &info, &ka, 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);
|
||||
|
||||
tracehook_signal_handler(signr, &info, &ka, regs, 0);
|
||||
}
|
||||
|
||||
handle_signal(signr, &info, &ka, regs, syscall);
|
||||
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
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -357,8 +331,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
|
||||
int syscall)
|
||||
{
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & ((1 << TIF_SIGPENDING) |
|
||||
(1 << TIF_RESTORE_SIGMASK)))
|
||||
if (thread_info_flags & (1 << TIF_SIGPENDING))
|
||||
do_signal(regs, syscall);
|
||||
|
||||
if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) {
|
||||
|
@ -31,8 +31,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/* 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 */
|
||||
|
||||
@ -176,7 +174,6 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
|
||||
sizeof(frame->extramask))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
@ -415,10 +411,11 @@ give_sigsegv:
|
||||
* 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,
|
||||
sigset_t *oldset, struct pt_regs *regs)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
/* 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);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -478,7 +473,6 @@ void do_signal(int canrestart, struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -489,23 +483,10 @@ void do_signal(int canrestart, struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(canrestart, signr, &info, &ka,
|
||||
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);
|
||||
}
|
||||
handle_signal(canrestart, signr, &info, &ka, regs);
|
||||
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
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
@ -24,9 +24,6 @@
|
||||
|
||||
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
|
||||
* 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))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
@ -434,11 +429,12 @@ give_sigsegv:
|
||||
}
|
||||
|
||||
/* Invoke a signal handler to, well, handle the signal. */
|
||||
static inline int
|
||||
static inline void
|
||||
handle_signal(int canrestart, 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;
|
||||
|
||||
/* 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);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -511,7 +505,6 @@ do_signal(int canrestart, struct pt_regs *regs)
|
||||
int signr;
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* 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))
|
||||
return;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(canrestart, signr, &info, &ka,
|
||||
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);
|
||||
}
|
||||
|
||||
handle_signal(canrestart, signr, &info, &ka, regs);
|
||||
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
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
asmlinkage void
|
||||
|
@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15");
|
||||
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
|
||||
#define TIF_SINGLESTEP 4 /* restore singlestep on return to user mode */
|
||||
#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_MEMDIE 17 /* is terminating due to OOM killer */
|
||||
#define TIF_POLLING_NRFLAG 6 /* true if poll_idle() is polling TIF_NEED_RESCHED */
|
||||
#define TIF_MEMDIE 7 /* is terminating due to OOM killer */
|
||||
|
||||
#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
|
||||
#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_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
|
||||
|
||||
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
|
||||
#define _TIF_ALLWORK_MASK 0x0000FFFF /* work to do on any return to u-space */
|
||||
/* work to do on interrupt/exception return */
|
||||
#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.
|
||||
|
@ -905,18 +905,19 @@ __syscall_call:
|
||||
__syscall_exit:
|
||||
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
|
||||
ldi @(gr28,#REG_PSR),gr22
|
||||
srli gr22,#1,gr5
|
||||
andi.p gr22,#~PSR_PS,gr22
|
||||
andi gr5,#PSR_PS,gr5
|
||||
or gr5,gr22,gr22
|
||||
ori gr22,#PSR_S,gr22
|
||||
|
||||
# keep current PSR in GR23
|
||||
movsg psr,gr23
|
||||
ori.p gr22,#PSR_S,gr22
|
||||
|
||||
# make sure we don't miss an interrupt setting need_resched or sigpending between
|
||||
# sampling and the RETT
|
||||
@ -924,9 +925,7 @@ __syscall_exit:
|
||||
movgs gr23,psr
|
||||
|
||||
ldi @(gr15,#TI_FLAGS),gr4
|
||||
sethi.p %hi(_TIF_ALLWORK_MASK),gr5
|
||||
setlo %lo(_TIF_ALLWORK_MASK),gr5
|
||||
andcc gr4,gr5,gr0,icc0
|
||||
andicc gr4,#_TIF_ALLWORK_MASK,gr0,icc0
|
||||
bne icc0,#0,__syscall_exit_work
|
||||
|
||||
# restore all registers and return
|
||||
@ -1111,9 +1110,7 @@ __entry_resume_userspace:
|
||||
__entry_return_from_user_interrupt:
|
||||
LEDS 0x6402
|
||||
ldi @(gr15,#TI_FLAGS),gr4
|
||||
sethi.p %hi(_TIF_WORK_MASK),gr5
|
||||
setlo %lo(_TIF_WORK_MASK),gr5
|
||||
andcc gr4,gr5,gr0,icc0
|
||||
andicc gr4,#_TIF_WORK_MASK,gr0,icc0
|
||||
beq icc0,#1,__entry_return_direct
|
||||
|
||||
__entry_work_pending:
|
||||
@ -1133,9 +1130,7 @@ __entry_work_resched:
|
||||
|
||||
LEDS 0x6401
|
||||
ldi @(gr15,#TI_FLAGS),gr4
|
||||
sethi.p %hi(_TIF_WORK_MASK),gr5
|
||||
setlo %lo(_TIF_WORK_MASK),gr5
|
||||
andcc gr4,gr5,gr0,icc0
|
||||
andicc gr4,#_TIF_WORK_MASK,gr0,icc0
|
||||
beq icc0,#1,__entry_return_direct
|
||||
andicc gr4,#_TIF_NEED_RESCHED,gr0,icc0
|
||||
bne icc0,#1,__entry_work_resched
|
||||
@ -1163,7 +1158,9 @@ __syscall_trace_entry:
|
||||
# perform syscall exit tracing
|
||||
__syscall_exit_work:
|
||||
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
|
||||
|
||||
movsg psr,gr23
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
struct fdpic_func_descriptor {
|
||||
unsigned long text;
|
||||
unsigned long GOT;
|
||||
@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void)
|
||||
__copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
|
||||
@ -426,9 +422,10 @@ give_sigsegv:
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset)
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
@ -460,11 +457,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, __frame,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
} /* end handle_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -477,44 +474,14 @@ static void do_signal(void)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
sigset_t *oldset;
|
||||
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 = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
|
||||
if (signr > 0) {
|
||||
if (handle_signal(signr, &info, &ka, oldset) == 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, __frame,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
handle_signal(signr, &info, &ka);
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (__frame->syscallno != -1) {
|
||||
/* 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
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
restore_saved_sigmask();
|
||||
} /* end do_signal() */
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
|
||||
clear_thread_flag(TIF_SINGLESTEP);
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
if (thread_info_flags & _TIF_SIGPENDING))
|
||||
do_signal();
|
||||
|
||||
/* deal with notification on about to resume userspace execution */
|
||||
|
@ -47,8 +47,6 @@
|
||||
#include <asm/traps.h>
|
||||
#include <asm/ucontext.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* 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))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
|
||||
@ -412,8 +408,9 @@ give_sigsegv:
|
||||
*/
|
||||
static void
|
||||
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;
|
||||
/* are we from a system call? */
|
||||
if (regs->orig_er0 >= 0) {
|
||||
@ -441,10 +438,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (!ret) {
|
||||
block_sigmask(ka, sig);
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
if (!ret)
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -457,7 +452,6 @@ statis void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -468,23 +462,14 @@ statis void do_signal(struct pt_regs *regs)
|
||||
if ((regs->ccr & 0x10))
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
current->thread.esp0 = (unsigned long) regs;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &info, &ka, oldset, regs);
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
return;
|
||||
}
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (regs->orig_er0 >= 0) {
|
||||
/* 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 (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
|
||||
|
@ -31,8 +31,6 @@
|
||||
#include <asm/signal.h>
|
||||
#include <asm/vdso.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
struct rt_sigframe {
|
||||
unsigned long tramp[2];
|
||||
struct siginfo info;
|
||||
@ -149,11 +147,9 @@ sigsegv:
|
||||
/*
|
||||
* Setup invocation of signal handler
|
||||
*/
|
||||
static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
sigset_t *oldset, struct pt_regs *regs)
|
||||
static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* If we're handling a signal that aborted a system call,
|
||||
* 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
|
||||
* 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 (rc)
|
||||
return rc;
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
|
||||
return;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -209,34 +202,13 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
|
||||
|
||||
if (signo > 0) {
|
||||
sigset_t *oldset;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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));
|
||||
}
|
||||
handle_signal(signo, &info, &sigact, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/*
|
||||
* If we came from a system call, handle the restart.
|
||||
*/
|
||||
@ -259,10 +231,7 @@ no_signal:
|
||||
|
||||
no_restart:
|
||||
/* If there's no signal to deliver, put the saved sigmask back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&blocked, ~_BLOCKABLE);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
|
@ -141,7 +141,23 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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__ */
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
#define STACK_ALIGN 16 /* minimal alignment for stack pointer */
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
#if _NSIG_WORDS > 1
|
||||
# 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))
|
||||
goto give_sigsegv;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
if (!setup_frame(sig, ka, info, oldset, scr))
|
||||
if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
|
||||
return 0;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
/*
|
||||
* Let tracing know that we've done the handler setup.
|
||||
*/
|
||||
tracehook_signal_handler(sig, info, ka, &scr->pt,
|
||||
signal_delivered(sig, info, ka, &scr->pt,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
|
||||
return 1;
|
||||
@ -440,7 +433,6 @@ void
|
||||
ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
siginfo_t info;
|
||||
long restart = in_syscall;
|
||||
long errno = scr->pt.r8;
|
||||
@ -453,11 +445,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
|
||||
if (!user_mode(&scr->pt))
|
||||
return;
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
/*
|
||||
* This only loops in the rare cases of handle_signal() failing, in which case we
|
||||
* 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
|
||||
* continue to iterate in this loop so we can deliver the SIGSEGV...
|
||||
*/
|
||||
if (handle_signal(signr, &ka, &info, oldset, 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;
|
||||
if (handle_signal(signr, &ka, &info, scr))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
* back */
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
@ -28,8 +28,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
asmlinkage int
|
||||
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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
|
||||
*/
|
||||
|
||||
static int
|
||||
static void
|
||||
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? */
|
||||
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 */
|
||||
if (setup_rt_frame(sig, ka, info, oldset, regs))
|
||||
return -EFAULT;
|
||||
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
|
||||
return;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -311,7 +307,6 @@ static void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* We want the common case to go fast, which
|
||||
@ -322,14 +317,6 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Re-enable any watchpoints before delivering the
|
||||
@ -339,13 +326,11 @@ static void do_signal(struct pt_regs *regs)
|
||||
*/
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if (regs->syscall_nr >= 0) {
|
||||
/* Restart the system call - no handlers present */
|
||||
@ -360,10 +345,7 @@ static void do_signal(struct pt_regs *regs)
|
||||
prev_insn(regs);
|
||||
}
|
||||
}
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -51,8 +51,6 @@
|
||||
#include <asm/traps.h>
|
||||
#include <asm/ucontext.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
|
||||
/*
|
||||
@ -795,7 +793,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
|
||||
sizeof(frame->extramask))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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
|
||||
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;
|
||||
/* are we from a system call? */
|
||||
if (regs->orig_d0 >= 0)
|
||||
@ -1140,14 +1137,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
if (err)
|
||||
return;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
|
||||
if (test_thread_flag(TIF_DELAYED_TRACE)) {
|
||||
regs->sr &= ~0x8000;
|
||||
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;
|
||||
struct k_sigaction ka;
|
||||
int signr;
|
||||
sigset_t *oldset;
|
||||
|
||||
current->thread.esp0 = (unsigned long) regs;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
handle_signal(signr, &ka, &info, oldset, regs);
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1182,10 +1171,7 @@ static void do_signal(struct pt_regs *regs)
|
||||
handle_restart(regs, NULL, 0);
|
||||
|
||||
/* If there's no signal to deliver, we just restore the saved mask. */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs)
|
||||
|
@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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
|
||||
|
||||
|
@ -41,8 +41,6 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/syscalls.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
asmlinkage long
|
||||
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
|
||||
@ -310,10 +307,11 @@ do_restart:
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
|
||||
static int
|
||||
static void
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
return;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -344,33 +340,18 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
#ifdef DEBUG_SIG
|
||||
printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall);
|
||||
printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
|
||||
regs->r12, current_thread_info()->flags);
|
||||
#endif
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (in_syscall)
|
||||
handle_restart(regs, &ka, 1);
|
||||
if (!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;
|
||||
}
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
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
|
||||
* back.
|
||||
*/
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, int in_syscall)
|
||||
|
@ -19,8 +19,6 @@
|
||||
# define DEBUGP(fmt, args...)
|
||||
#endif
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* Determine which stack to use..
|
||||
*/
|
||||
|
@ -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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&blocked, ~_BLOCKABLE);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
sig = restore_sigcontext(®s, &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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext);
|
||||
@ -514,9 +512,10 @@ struct mips_abi mips_abi = {
|
||||
.restart = __NR_restart_syscall
|
||||
};
|
||||
|
||||
static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
struct mips_abi *abi = current->thread.abi;
|
||||
void *vdso = current->mm->context.vdso;
|
||||
@ -550,17 +549,14 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
ka, regs, sig, oldset);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
return;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
|
||||
@ -572,25 +568,10 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &info, &ka, 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);
|
||||
}
|
||||
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
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
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -630,7 +608,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
|
||||
local_irq_enable();
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(regs);
|
||||
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||
|
@ -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))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&blocked, ~_BLOCKABLE);
|
||||
set_current_blocked(&blocked);
|
||||
|
||||
sig = restore_sigcontext32(®s, &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))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
sig = restore_sigcontext32(®s, &frame->rs_uc.uc_mcontext);
|
||||
|
@ -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))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
sig = restore_sigcontext(®s, &frame->rs_uc.uc_mcontext);
|
||||
|
@ -31,8 +31,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
@ -163,7 +161,6 @@ asmlinkage long sys_sigreturn(void)
|
||||
sizeof(frame->extramask)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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,
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -475,7 +472,6 @@ static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
siginfo_t info;
|
||||
sigset_t *oldset;
|
||||
int signr;
|
||||
|
||||
/* 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))
|
||||
return;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
if (handle_signal(signr, &info, &ka, 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);
|
||||
|
||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
if (handle_signal(signr, &info, &ka, regs) == 0) {
|
||||
}
|
||||
|
||||
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
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -548,7 +527,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
|
||||
}
|
||||
|
||||
/* deal with pending signal delivery */
|
||||
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
|
||||
if (thread_info_flags & _TIF_SIGPENDING)
|
||||
do_signal(regs);
|
||||
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||
|
@ -33,8 +33,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
asmlinkage long
|
||||
_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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
@ -251,20 +248,19 @@ give_sigsegv:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline void
|
||||
handle_signal(unsigned long sig,
|
||||
siginfo_t *info, struct k_sigaction *ka,
|
||||
sigset_t *oldset, struct pt_regs *regs)
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
|
||||
if (ret)
|
||||
return ret;
|
||||
return;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -339,30 +335,10 @@ void do_signal(struct pt_regs *regs)
|
||||
if (signr <= 0) {
|
||||
/* no signal to deliver so we just put the saved sigmask
|
||||
* back */
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
restore_saved_sigmask();
|
||||
} else { /* signr > 0 */
|
||||
sigset_t *oldset;
|
||||
|
||||
if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (!handle_signal(signr, &info, &ka, 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 */
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
}
|
||||
|
||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -74,7 +74,7 @@ struct thread_info {
|
||||
#define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP)
|
||||
|
||||
#define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
|
||||
_TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
|
||||
_TIF_NEED_RESCHED)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
@ -924,7 +924,7 @@ intr_check_sig:
|
||||
/* As above */
|
||||
mfctl %cr30,%r1
|
||||
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
|
||||
b,n intr_restore /* skip past if we've nothing to do */
|
||||
|
||||
@ -2032,7 +2032,7 @@ syscall_check_resched:
|
||||
.import do_signal,code
|
||||
syscall_check_sig:
|
||||
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
|
||||
b,n syscall_restore /* skip past if we've nothing to do */
|
||||
|
||||
|
@ -48,9 +48,6 @@
|
||||
#define DBG(LEVEL, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/* 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
|
||||
* 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;
|
||||
}
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
/* Good thing we saved the old gr[30], eh? */
|
||||
@ -443,8 +439,9 @@ give_sigsegv:
|
||||
|
||||
static long
|
||||
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",
|
||||
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))
|
||||
return 0;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
tracehook_signal_handler(sig, info, ka, regs,
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP) ||
|
||||
test_thread_flag(TIF_BLOCKSTEP));
|
||||
|
||||
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
|
||||
regs->gr[28]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -568,28 +566,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
|
||||
siginfo_t info;
|
||||
struct k_sigaction ka;
|
||||
int signr;
|
||||
sigset_t *oldset;
|
||||
|
||||
DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
|
||||
oldset, regs, regs->sr[7], in_syscall);
|
||||
DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
|
||||
regs, regs->sr[7], in_syscall);
|
||||
|
||||
/* 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
|
||||
we would be called in that case, but for some reason we
|
||||
are. */
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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 */
|
||||
while (1) {
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
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
|
||||
delivery failed, we need to continue to iterate in
|
||||
this loop so we can deliver the SIGSEGV... */
|
||||
if (handle_signal(signr, &info, &ka, oldset,
|
||||
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);
|
||||
if (handle_signal(signr, &info, &ka, regs, in_syscall))
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* 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",
|
||||
regs->gr[28]);
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, long in_syscall)
|
||||
{
|
||||
if (test_thread_flag(TIF_SIGPENDING) ||
|
||||
test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
if (test_thread_flag(TIF_SIGPENDING))
|
||||
do_signal(regs, in_syscall);
|
||||
|
||||
if (test_thread_flag(TIF_NOTIFY_RESUME)) {
|
||||
|
@ -47,8 +47,6 @@
|
||||
#define DBG(LEVEL, ...)
|
||||
#endif
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
inline void
|
||||
sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
|
||||
{
|
||||
|
@ -140,7 +140,23 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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)
|
||||
|
@ -51,16 +51,6 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
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,
|
||||
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)
|
||||
{
|
||||
sigset_t *oldset;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
int ret;
|
||||
int is32 = is_32bit_task();
|
||||
|
||||
if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
/* Is there any syscall restart business here ? */
|
||||
check_syscall_restart(regs, &ka, signr > 0);
|
||||
|
||||
if (signr <= 0) {
|
||||
struct thread_info *ti = current_thread_info();
|
||||
/* No signal to deliver -- put the saved sigmask back */
|
||||
if (ti->local_flags & _TLF_RESTORE_SIGMASK) {
|
||||
ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
regs->trap = 0;
|
||||
return 0; /* no signals delivered */
|
||||
}
|
||||
@ -167,18 +148,7 @@ static int do_signal(struct pt_regs *regs)
|
||||
|
||||
regs->trap = 0;
|
||||
if (ret) {
|
||||
block_sigmask(&ka, signr);
|
||||
|
||||
/*
|
||||
* 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,
|
||||
signal_delivered(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
|
@ -10,13 +10,10 @@
|
||||
#ifndef _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 __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
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,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
|
@ -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)))
|
||||
return -EFAULT;
|
||||
#endif
|
||||
restore_sigmask(&set);
|
||||
set_current_blocked(&set);
|
||||
if (restore_user_regs(regs, mcp, sig))
|
||||
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[1] = sigctx._unused[3];
|
||||
#endif
|
||||
restore_sigmask(&set);
|
||||
set_current_blocked(&set);
|
||||
|
||||
sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
|
||||
addr = sr;
|
||||
|
@ -335,7 +335,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
|
||||
|
||||
if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set)))
|
||||
do_exit(SIGSEGV);
|
||||
restore_sigmask(&set);
|
||||
set_current_blocked(&set);
|
||||
if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext))
|
||||
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)))
|
||||
goto badframe;
|
||||
restore_sigmask(&set);
|
||||
set_current_blocked(&set);
|
||||
if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext))
|
||||
goto badframe;
|
||||
|
||||
|
@ -32,8 +32,6 @@
|
||||
#include "compat_ptrace.h"
|
||||
#include "entry.h"
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
|
||||
@ -364,7 +362,6 @@ asmlinkage long sys32_sigreturn(void)
|
||||
goto badframe;
|
||||
if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
|
||||
goto badframe;
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
if (restore_sigregs32(regs, &frame->sregs))
|
||||
goto badframe;
|
||||
@ -390,7 +387,6 @@ asmlinkage long sys32_rt_sigreturn(void)
|
||||
goto badframe;
|
||||
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
|
||||
goto badframe;
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
|
||||
goto badframe;
|
||||
@ -572,7 +568,7 @@ give_sigsegv:
|
||||
* 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)
|
||||
{
|
||||
int ret;
|
||||
@ -583,8 +579,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
|
||||
else
|
||||
ret = setup_frame32(sig, ka, oldset, regs);
|
||||
if (ret)
|
||||
return ret;
|
||||
block_sigmask(ka, sig);
|
||||
return 0;
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ void do_per_trap(struct pt_regs *regs);
|
||||
void syscall_trace(struct pt_regs *regs, int entryexit);
|
||||
void kernel_stack_overflow(struct pt_regs * regs);
|
||||
void do_signal(struct pt_regs *regs);
|
||||
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);
|
||||
void do_notify_resume(struct pt_regs *regs);
|
||||
|
||||
|
@ -33,9 +33,6 @@
|
||||
#include <asm/switch_to.h>
|
||||
#include "entry.h"
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
__u8 callee_used_stack[__SIGNAL_FRAMESIZE];
|
||||
@ -169,7 +166,6 @@ SYSCALL_DEFINE0(sigreturn)
|
||||
goto badframe;
|
||||
if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
|
||||
goto badframe;
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
if (restore_sigregs(regs, &frame->sregs))
|
||||
goto badframe;
|
||||
@ -189,7 +185,6 @@ SYSCALL_DEFINE0(rt_sigreturn)
|
||||
goto badframe;
|
||||
if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
|
||||
goto badframe;
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
if (restore_sigregs(regs, &frame->uc.uc_mcontext))
|
||||
goto badframe;
|
||||
@ -367,7 +362,7 @@ give_sigsegv:
|
||||
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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
@ -379,9 +374,9 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
if (ret)
|
||||
return ret;
|
||||
block_sigmask(ka, sig);
|
||||
return 0;
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -398,12 +393,7 @@ void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
|
||||
/*
|
||||
* 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 */
|
||||
clear_thread_flag(TIF_SYSCALL);
|
||||
|
||||
if ((is_compat_task() ?
|
||||
handle_signal32(signr, &ka, &info, oldset, regs) :
|
||||
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);
|
||||
|
||||
/*
|
||||
* Let tracing know that we've done the handler setup.
|
||||
*/
|
||||
tracehook_signal_handler(signr, &info, &ka, regs,
|
||||
test_thread_flag(TIF_SINGLE_STEP));
|
||||
}
|
||||
if (is_compat_task())
|
||||
handle_signal32(signr, &ka, &info, oldset, regs);
|
||||
else
|
||||
handle_signal(signr, &ka, &info, oldset, regs);
|
||||
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 (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs)
|
||||
|
@ -34,8 +34,6 @@
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/ucontext.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
struct rt_sigframe {
|
||||
u32 rs_ass[4]; /* argument save space */
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
|
||||
@ -241,11 +238,9 @@ give_sigsegv:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (regs->is_syscall) {
|
||||
switch (regs->regs[4]) {
|
||||
case ERESTART_RESTARTBLOCK:
|
||||
@ -269,18 +264,15 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
/*
|
||||
* 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)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
static void do_signal(struct pt_regs *regs)
|
||||
{
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
|
||||
@ -292,25 +284,10 @@ static void do_signal(struct pt_regs *regs)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Actually deliver the signal. */
|
||||
if (handle_signal(signr, &info, &ka, 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);
|
||||
}
|
||||
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
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
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -169,7 +169,7 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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
|
||||
@ -189,6 +189,23 @@ static inline unsigned int get_thread_fault_code(void)
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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 /* __KERNEL__ */
|
||||
|
@ -32,8 +32,6 @@
|
||||
#include <asm/syscalls.h>
|
||||
#include <asm/fpu.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
struct fdpic_func_descriptor {
|
||||
unsigned long text;
|
||||
unsigned long GOT;
|
||||
@ -226,7 +224,6 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
|
||||
sizeof(frame->extramask))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
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;
|
||||
|
||||
/* Set up the stack frame */
|
||||
@ -534,10 +531,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return ret;
|
||||
if (ret)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -554,7 +551,6 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* 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))
|
||||
return;
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
handle_syscall_restart(save_r0, regs, &ka.sa);
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &ka, &info, oldset,
|
||||
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));
|
||||
}
|
||||
|
||||
handle_signal(signr, &ka, &info, regs, save_r0);
|
||||
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
|
||||
* back.
|
||||
*/
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
|
||||
|
@ -41,11 +41,9 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
static int
|
||||
static void
|
||||
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
|
||||
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;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* 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))
|
||||
return;
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, 0);
|
||||
if (signr > 0) {
|
||||
handle_syscall_restart(regs, &ka.sa);
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
return;
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
|
||||
return;
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
/*
|
||||
@ -351,7 +328,6 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
|
||||
sizeof(frame->extramask))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
|
||||
@ -659,10 +634,11 @@ give_sigsegv:
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static int
|
||||
static void
|
||||
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;
|
||||
|
||||
/* Set up the stack frame */
|
||||
@ -671,10 +647,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
else
|
||||
ret = setup_frame(sig, ka, oldset, regs);
|
||||
|
||||
if (ret == 0)
|
||||
block_sigmask(ka, sig);
|
||||
if (ret)
|
||||
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)
|
||||
|
@ -131,8 +131,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
|
||||
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
|
||||
|
||||
#define _TIF_DO_NOTIFY_RESUME_MASK (_TIF_NOTIFY_RESUME | \
|
||||
_TIF_SIGPENDING | \
|
||||
_TIF_RESTORE_SIGMASK)
|
||||
_TIF_SIGPENDING)
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
@ -238,7 +238,23 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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__ */
|
||||
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
#include "sigutil.h"
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/* This magic should be in g_upper[0] for all upper parts
|
||||
* 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 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
|
||||
}
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
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 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
|
||||
}
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
return;
|
||||
segv:
|
||||
@ -775,7 +771,7 @@ sigsegv:
|
||||
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,
|
||||
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);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
return;
|
||||
|
||||
block_sigmask(ka, signr);
|
||||
tracehook_signal_handler(signr, info, ka, regs, 0);
|
||||
|
||||
return 0;
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
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 (restart_syscall)
|
||||
syscall_restart32(orig_i0, regs, &ka.sa);
|
||||
if (handle_signal32(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 TS_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
}
|
||||
handle_signal32(signr, &ka, &info, oldset, regs);
|
||||
return;
|
||||
}
|
||||
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
|
||||
* back
|
||||
*/
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
struct sigstack32 {
|
||||
|
@ -29,8 +29,6 @@
|
||||
|
||||
#include "sigutil.h"
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
|
||||
void *fpqueue, unsigned long *fpqdepth);
|
||||
extern void fpload(unsigned long *fpregs, unsigned long *fsr);
|
||||
@ -130,7 +128,6 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
|
||||
if (err)
|
||||
goto segv_and_exit;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
return;
|
||||
|
||||
@ -197,7 +194,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
|
||||
goto segv;
|
||||
}
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
return;
|
||||
segv:
|
||||
@ -449,10 +445,11 @@ sigsegv:
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
static inline int
|
||||
static inline void
|
||||
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;
|
||||
|
||||
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);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
return;
|
||||
|
||||
block_sigmask(ka, signr);
|
||||
tracehook_signal_handler(signr, info, ka, regs, 0);
|
||||
|
||||
return 0;
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
int restart_syscall;
|
||||
sigset_t *oldset;
|
||||
siginfo_t info;
|
||||
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))
|
||||
regs->u_regs[UREG_G6] = orig_i0;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
|
||||
/* If 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 (restart_syscall)
|
||||
syscall_restart(orig_i0, regs, &ka.sa);
|
||||
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);
|
||||
}
|
||||
handle_signal(signr, &ka, &info, regs);
|
||||
return;
|
||||
}
|
||||
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
|
||||
* back
|
||||
*/
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
|
||||
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);
|
||||
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
|
||||
clear_thread_flag(TIF_NOTIFY_RESUME);
|
||||
|
@ -38,8 +38,6 @@
|
||||
#include "systbls.h"
|
||||
#include "sigutil.h"
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/* {set, get}context() needed for 64-bit SparcLinux userland. */
|
||||
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)))
|
||||
goto do_sigsegv;
|
||||
}
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
}
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
@ -315,7 +312,6 @@ void do_rt_sigreturn(struct pt_regs *regs)
|
||||
/* Prevent syscall restart. */
|
||||
pt_regs_clear_syscall(regs);
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
return;
|
||||
segv:
|
||||
@ -466,7 +462,7 @@ sigsegv:
|
||||
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,
|
||||
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,
|
||||
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
|
||||
if (err)
|
||||
return err;
|
||||
return;
|
||||
|
||||
block_sigmask(ka, signr);
|
||||
tracehook_signal_handler(signr, info, ka, regs, 0);
|
||||
|
||||
return 0;
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
int restart_syscall;
|
||||
sigset_t *oldset;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
siginfo_t info;
|
||||
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->u_regs[UREG_G6] = orig_i0;
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
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 (restart_syscall)
|
||||
syscall_restart(orig_i0, regs, &ka.sa);
|
||||
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 TS_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
}
|
||||
handle_signal(signr, &ka, &info, oldset, regs);
|
||||
return;
|
||||
}
|
||||
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
|
||||
* back
|
||||
*/
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
|
||||
|
@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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__ */
|
||||
|
||||
|
@ -118,8 +118,6 @@ struct compat_rt_sigframe {
|
||||
struct compat_ucontext uc;
|
||||
};
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
|
||||
struct compat_sigaction __user *oact,
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
|
@ -37,8 +37,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
|
||||
@ -242,10 +239,11 @@ give_sigsegv:
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
|
||||
static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka, sigset_t *oldset,
|
||||
static void handle_signal(unsigned long sig, siginfo_t *info,
|
||||
struct k_sigaction *ka,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
@ -278,15 +276,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
|
||||
else
|
||||
#endif
|
||||
ret = setup_rt_frame(sig, ka, info, oldset, regs);
|
||||
if (ret == 0) {
|
||||
/* This code is only called from system calls or from
|
||||
* the work_pending path in the return-to-user code, and
|
||||
* either way we can re-enable interrupts unconditionally.
|
||||
*/
|
||||
block_sigmask(ka, sig);
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (ret)
|
||||
return;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -299,7 +291,6 @@ void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t *oldset;
|
||||
|
||||
/*
|
||||
* 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)".
|
||||
*/
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (handle_signal(signr, &info, &ka, 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 TS_RESTORE_SIGMASK flag.
|
||||
*/
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
}
|
||||
|
||||
handle_signal(signr, &info, &ka, regs);
|
||||
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 (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
restore_saved_sigmask();
|
||||
|
||||
done:
|
||||
/* Avoid double syscall restart if there are nested signals. */
|
||||
|
@ -6,9 +6,6 @@
|
||||
#ifndef __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,
|
||||
struct k_sigaction *ka,
|
||||
struct pt_regs *regs,
|
||||
|
@ -15,17 +15,13 @@
|
||||
EXPORT_SYMBOL(block_signals);
|
||||
EXPORT_SYMBOL(unblock_signals);
|
||||
|
||||
#define _S(nr) (1<<((nr)-1))
|
||||
|
||||
#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static int handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
struct k_sigaction *ka, siginfo_t *info,
|
||||
sigset_t *oldset)
|
||||
static void handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
struct k_sigaction *ka, siginfo_t *info)
|
||||
{
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
unsigned long sp;
|
||||
int err;
|
||||
|
||||
@ -65,9 +61,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
|
||||
if (err)
|
||||
force_sigsegv(signr, current);
|
||||
else
|
||||
block_sigmask(ka, signr);
|
||||
|
||||
return err;
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
|
||||
sigset_t *oldset;
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
handled_sig = 1;
|
||||
/* Whee! Actually deliver the signal. */
|
||||
if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
handle_signal(regs, sig, &ka_copy, &info);
|
||||
}
|
||||
|
||||
/* 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
|
||||
* back
|
||||
*/
|
||||
if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL);
|
||||
}
|
||||
if (!handled_sig)
|
||||
restore_saved_sigmask();
|
||||
return handled_sig;
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,6 @@
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/ucontext.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
|
||||
if (err == 0) {
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
if (err == 0)
|
||||
set_current_blocked(&set);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -312,13 +308,12 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
|
||||
/*
|
||||
* OK, we're invoking a handler
|
||||
*/
|
||||
static int handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, sigset_t *oldset,
|
||||
struct pt_regs *regs, int syscall)
|
||||
static void handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
siginfo_t *info, struct pt_regs *regs, int syscall)
|
||||
{
|
||||
struct thread_info *thread = current_thread_info();
|
||||
struct task_struct *tsk = current;
|
||||
sigset_t blocked;
|
||||
sigset_t *oldset = sigmask_to_save();
|
||||
int usig = sig;
|
||||
int ret;
|
||||
|
||||
@ -364,15 +359,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
|
||||
|
||||
if (ret != 0) {
|
||||
force_sigsegv(sig, tsk);
|
||||
return ret;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Block the signal if we were successful.
|
||||
*/
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -399,32 +389,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
|
||||
if (!user_mode(regs))
|
||||
return;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
if (signr > 0) {
|
||||
sigset_t *oldset;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->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);
|
||||
}
|
||||
handle_signal(signr, &ka, &info, regs, syscall);
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/*
|
||||
* 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
|
||||
* sigmask back.
|
||||
*/
|
||||
if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
restore_saved_sigmask();
|
||||
}
|
||||
|
||||
asmlinkage void do_notify_resume(struct pt_regs *regs,
|
||||
|
@ -273,7 +273,6 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
|
||||
sizeof(frame->extramask))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
||||
|
@ -7,8 +7,6 @@
|
||||
|
||||
#include <asm/processor-flags.h>
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
#define __FIX_EFLAGS (X86_EFLAGS_AC | X86_EFLAGS_OF | \
|
||||
X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
|
||||
X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
|
||||
|
@ -248,7 +248,23 @@ static inline void set_restore_sigmask(void)
|
||||
{
|
||||
struct thread_info *ti = current_thread_info();
|
||||
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)
|
||||
|
@ -316,7 +316,6 @@ ret_from_exception:
|
||||
preempt_stop(CLBR_ANY)
|
||||
ret_from_intr:
|
||||
GET_THREAD_INFO(%ebp)
|
||||
resume_userspace_sig:
|
||||
#ifdef CONFIG_VM86
|
||||
movl PT_EFLAGS(%esp), %eax # mix EFLAGS and CS
|
||||
movb PT_CS(%esp), %al
|
||||
@ -615,9 +614,13 @@ work_notifysig: # deal with pending signals and
|
||||
# vm86-space
|
||||
TRACE_IRQS_ON
|
||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||
movb PT_CS(%esp), %bl
|
||||
andb $SEGMENT_RPL_MASK, %bl
|
||||
cmpb $USER_RPL, %bl
|
||||
jb resume_kernel
|
||||
xorl %edx, %edx
|
||||
call do_notify_resume
|
||||
jmp resume_userspace_sig
|
||||
jmp resume_userspace
|
||||
|
||||
ALIGN
|
||||
work_notifysig_v86:
|
||||
@ -630,9 +633,13 @@ work_notifysig_v86:
|
||||
#endif
|
||||
TRACE_IRQS_ON
|
||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||
movb PT_CS(%esp), %bl
|
||||
andb $SEGMENT_RPL_MASK, %bl
|
||||
cmpb $USER_RPL, %bl
|
||||
jb resume_kernel
|
||||
xorl %edx, %edx
|
||||
call do_notify_resume
|
||||
jmp resume_userspace_sig
|
||||
jmp resume_userspace
|
||||
END(work_pending)
|
||||
|
||||
# perform syscall exit tracing
|
||||
|
@ -555,7 +555,6 @@ unsigned long sys_sigreturn(struct pt_regs *regs)
|
||||
sizeof(frame->extramask))))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
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)
|
||||
{
|
||||
int usig = signr_convert(sig);
|
||||
sigset_t *set = ¤t->blocked;
|
||||
int ret;
|
||||
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
|
||||
set = ¤t->saved_sigmask;
|
||||
sigset_t *set = sigmask_to_save();
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (is_ia32) {
|
||||
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
|
||||
ret = ia32_setup_frame(usig, ka, set, regs);
|
||||
return ia32_setup_frame(usig, ka, set, regs);
|
||||
#ifdef CONFIG_X86_X32_ABI
|
||||
} 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);
|
||||
#endif
|
||||
} 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,
|
||||
struct pt_regs *regs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Are we from a system call? */
|
||||
if (syscall_get_nr(current, regs) >= 0) {
|
||||
/* 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)))
|
||||
regs->flags &= ~X86_EFLAGS_TF;
|
||||
|
||||
ret = setup_rt_frame(sig, ka, info, regs);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
if (setup_rt_frame(sig, ka, info, regs) < 0) {
|
||||
force_sigsegv(sig, current);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
block_sigmask(ka, sig);
|
||||
|
||||
tracehook_signal_handler(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
|
||||
return 0;
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP));
|
||||
}
|
||||
|
||||
#ifdef CONFIG_X86_32
|
||||
@ -757,16 +737,6 @@ static void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
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);
|
||||
if (signr > 0) {
|
||||
/* 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
|
||||
* back.
|
||||
*/
|
||||
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
|
||||
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
}
|
||||
restore_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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
|
||||
|
@ -486,7 +486,6 @@ long sys_sigreturn(struct pt_regs *regs)
|
||||
copy_from_user(&set.sig[1], extramask, sig_size))
|
||||
goto segfault;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (copy_sc_from_user(¤t->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)))
|
||||
goto segfault;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (copy_sc_from_user(¤t->thread.regs, &uc->uc_mcontext))
|
||||
|
@ -30,8 +30,6 @@
|
||||
|
||||
#define DEBUG_SIG 0
|
||||
|
||||
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
|
||||
|
||||
extern struct task_struct *coproc_owners[];
|
||||
|
||||
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)))
|
||||
goto badframe;
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
set_current_blocked(&set);
|
||||
|
||||
if (restore_sigcontext(regs, frame))
|
||||
@ -452,15 +449,6 @@ static void do_signal(struct pt_regs *regs)
|
||||
siginfo_t info;
|
||||
int signr;
|
||||
struct k_sigaction ka;
|
||||
sigset_t oldset;
|
||||
|
||||
if (try_to_freeze())
|
||||
goto no_signal;
|
||||
|
||||
if (test_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
oldset = ¤t->saved_sigmask;
|
||||
else
|
||||
oldset = ¤t->blocked;
|
||||
|
||||
task_pt_regs(current)->icountlevel = 0;
|
||||
|
||||
@ -501,19 +489,17 @@ static void do_signal(struct pt_regs *regs)
|
||||
|
||||
/* Whee! Actually deliver the signal. */
|
||||
/* 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)
|
||||
return;
|
||||
|
||||
clear_thread_flag(TIF_RESTORE_SIGMASK);
|
||||
block_sigmask(&ka, signr);
|
||||
signal_delivered(signr, info, ka, regs, 0);
|
||||
if (current->ptrace & PT_SINGLESTEP)
|
||||
task_pt_regs(current)->icountlevel = 1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
no_signal:
|
||||
/* Did we come from a system call? */
|
||||
if ((signed) regs->syscall >= 0) {
|
||||
/* 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 (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
|
||||
set_current_blocked(¤t->saved_sigmask);
|
||||
restore_saved_sigmask();
|
||||
|
||||
if (current->ptrace & PT_SINGLESTEP)
|
||||
task_pt_regs(current)->icountlevel = 1;
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||
static long do_compat_pselect(int n, compat_ulong_t __user *inp,
|
||||
compat_ulong_t __user *outp, compat_ulong_t __user *exp,
|
||||
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;
|
||||
}
|
||||
#endif /* HAVE_SET_RESTORE_SIGMASK */
|
||||
|
||||
#ifdef CONFIG_EPOLL
|
||||
|
||||
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||
asmlinkage long compat_sys_epoll_pwait(int epfd,
|
||||
struct compat_epoll_event __user *events,
|
||||
int maxevents, int timeout,
|
||||
@ -1713,7 +1710,6 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif /* HAVE_SET_RESTORE_SIGMASK */
|
||||
|
||||
#endif /* CONFIG_EPOLL */
|
||||
|
||||
|
@ -1853,8 +1853,6 @@ error_return:
|
||||
return error;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||
|
||||
/*
|
||||
* Implement the event wait interface for the eventpoll file. It is the kernel
|
||||
* 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;
|
||||
}
|
||||
|
||||
#endif /* HAVE_SET_RESTORE_SIGMASK */
|
||||
|
||||
static int __init eventpoll_init(void)
|
||||
{
|
||||
struct sysinfo si;
|
||||
|
@ -614,7 +614,6 @@ SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||
static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
|
||||
fd_set __user *exp, struct timespec __user *tsp,
|
||||
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);
|
||||
}
|
||||
#endif /* HAVE_SET_RESTORE_SIGMASK */
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_OLD_SELECT
|
||||
struct sel_arg_struct {
|
||||
@ -941,7 +939,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||
SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
|
||||
struct timespec __user *, tsp, const sigset_t __user *, sigmask,
|
||||
size_t, sigsetsize)
|
||||
@ -992,4 +989,3 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_SET_RESTORE_SIGMASK */
|
||||
|
@ -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_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(¤t->saved_sigmask);
|
||||
}
|
||||
|
||||
static inline sigset_t *sigmask_to_save(void)
|
||||
{
|
||||
sigset_t *res = ¤t->blocked;
|
||||
if (unlikely(test_restore_sigmask()))
|
||||
res = ¤t->saved_sigmask;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int kill_cad_pid(int sig, int priv)
|
||||
{
|
||||
return kill_pid(cad_pid, sig, priv);
|
||||
|
@ -250,12 +250,13 @@ extern long do_sigpending(void __user *, unsigned long);
|
||||
extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
|
||||
const struct timespec *);
|
||||
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 sigsuspend(sigset_t *);
|
||||
|
||||
extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
|
||||
extern void block_sigmask(struct k_sigaction *ka, int signr);
|
||||
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 struct kmem_cache *sighand_cachep;
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define _LINUX_THREAD_INFO_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/bug.h>
|
||||
|
||||
struct 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)
|
||||
{
|
||||
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 */
|
||||
|
||||
#ifndef HAVE_SET_RESTORE_SIGMASK
|
||||
#error "no set_restore_sigmask() provided and default one won't work"
|
||||
#endif
|
||||
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _LINUX_THREAD_INFO_H */
|
||||
|
@ -2368,24 +2368,34 @@ relock:
|
||||
}
|
||||
|
||||
/**
|
||||
* block_sigmask - add @ka's signal mask to current->blocked
|
||||
* @ka: action for @signr
|
||||
* @signr: signal that has been successfully delivered
|
||||
* signal_delivered -
|
||||
* @sig: number of signal being delivered
|
||||
* @info: siginfo_t of signal being delivered
|
||||
* @ka: sigaction setting that chose the handler
|
||||
* @regs: user register state
|
||||
* @stepping: nonzero if debugger single-step or block-step in use
|
||||
*
|
||||
* This function should be called when a signal has succesfully been
|
||||
* delivered. It adds the mask of signals for @ka to current->blocked
|
||||
* so that they are blocked during the execution of the signal
|
||||
* handler. In addition, @signr will be blocked unless %SA_NODEFER is
|
||||
* set in @ka->sa.sa_flags.
|
||||
* delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask
|
||||
* is always blocked, and the signal itself is blocked unless %SA_NODEFER
|
||||
* is set in @ka->sa.sa_flags. Tracing is notified.
|
||||
*/
|
||||
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;
|
||||
|
||||
/* 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, ¤t->blocked, &ka->sa.sa_mask);
|
||||
if (!(ka->sa.sa_flags & SA_NODEFER))
|
||||
sigaddset(&blocked, signr);
|
||||
sigaddset(&blocked, sig);
|
||||
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
|
||||
* 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;
|
||||
|
||||
@ -2558,7 +2577,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set_current_blocked(&newset);
|
||||
__set_current_blocked(&newset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3132,7 +3151,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
set_current_blocked(&new_blocked);
|
||||
__set_current_blocked(&new_blocked);
|
||||
}
|
||||
|
||||
if (oset) {
|
||||
@ -3196,7 +3215,6 @@ SYSCALL_DEFINE1(ssetmask, int, newmask)
|
||||
int old = current->blocked.sig[0];
|
||||
sigset_t newset;
|
||||
|
||||
siginitset(&newset, newmask & ~(sigmask(SIGKILL) | sigmask(SIGSTOP)));
|
||||
set_current_blocked(&newset);
|
||||
|
||||
return old;
|
||||
@ -3235,11 +3253,8 @@ SYSCALL_DEFINE0(pause)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SET_RESTORE_SIGMASK
|
||||
int sigsuspend(sigset_t *set)
|
||||
{
|
||||
sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
||||
|
||||
current->saved_sigmask = current->blocked;
|
||||
set_current_blocked(set);
|
||||
|
||||
@ -3248,7 +3263,6 @@ int sigsuspend(sigset_t *set)
|
||||
set_restore_sigmask();
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user