pull clearing RESTORE_SIGMASK into block_sigmask()

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Al Viro 2012-05-21 23:42:15 -04:00
parent 5754f412a3
commit a610d6e672
34 changed files with 130 additions and 387 deletions

View File

@ -481,11 +481,6 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
return; return;
} }
block_sigmask(ka, sig); block_sigmask(ka, sig);
/* A signal was successfully delivered, and the
saved sigmask was stored on the signal frame,
and will be restored by sigreturn. So we can
simply clear the restore sigmask flag. */
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
static inline void static inline void

View File

@ -528,7 +528,7 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, struct pt_regs *regs) siginfo_t *info, struct pt_regs *regs)
{ {
@ -559,17 +559,14 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
if (ret != 0) { if (ret != 0) {
force_sigsegv(sig, tsk); force_sigsegv(sig, tsk);
return ret; return;
} }
/* /*
* Block the signal if we were successful. * Block the signal if we were successful.
*/ */
block_sigmask(ka, sig); block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, regs, 0); tracehook_signal_handler(sig, info, ka, regs, 0);
return 0;
} }
/* /*
@ -633,16 +630,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
clear_thread_flag(TIF_SYSCALL_RESTARTSYS); clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
} }
if (handle_signal(signr, &ka, &info, regs) == 0) { handle_signal(signr, &ka, &info, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }

View File

@ -238,16 +238,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
*/ */
ret |= !valid_user_regs(regs); ret |= !valid_user_regs(regs);
if (ret != 0) {
force_sigsegv(sig, current);
return;
}
/* /*
* Block the signal if we were successful. * Block the signal if we were successful.
*/ */
block_sigmask(ka, sig); if (ret != 0)
clear_thread_flag(TIF_RESTORE_SIGMASK); force_sigsegv(sig, current);
else
block_sigmask(ka, sig);
} }
/* /*

View File

@ -247,7 +247,7 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -260,11 +260,12 @@ handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
/* set up the stack frame */ /* set up the stack frame */
ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
if (ret)
return;
if (ret == 0) block_sigmask(ka, sig);
block_sigmask(ka, sig); tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return ret;
} }
/* /*
@ -290,18 +291,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }

View File

@ -248,7 +248,7 @@ do_restart:
/* /*
* handle the actual delivery of a signal to userspace * handle the actual delivery of a signal to userspace
*/ */
static int handle_signal(int sig, static void handle_signal(int sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs, int syscall) struct pt_regs *regs, int syscall)
{ {
@ -277,11 +277,10 @@ static int handle_signal(int sig,
} }
/* Set up the stack frame */ /* Set up the stack frame */
ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
if (ret == 0) return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, regs, 0);
return ret;
} }
/* /*
@ -300,17 +299,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &info, &ka, regs, syscall) == 0) { handle_signal(signr, &info, &ka, regs, syscall);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs, 0);
}
return; return;
} }

View File

@ -415,7 +415,7 @@ give_sigsegv:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static inline int handle_signal(int canrestart, unsigned long sig, static inline void handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -458,8 +458,6 @@ static inline int handle_signal(int canrestart, unsigned long sig,
if (ret == 0) if (ret == 0)
block_sigmask(ka, sig); block_sigmask(ka, sig);
return ret;
} }
/* /*
@ -492,15 +490,7 @@ void do_signal(int canrestart, struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(canrestart, signr, &info, &ka, handle_signal(canrestart, signr, &info, &ka, regs);
regs)) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }

View File

@ -434,7 +434,7 @@ give_sigsegv:
} }
/* Invoke a signal handler to, well, handle the signal. */ /* Invoke a signal handler to, well, handle the signal. */
static inline int static inline void
handle_signal(int canrestart, unsigned long sig, handle_signal(int canrestart, unsigned long sig,
siginfo_t *info, struct k_sigaction *ka, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs * regs) struct pt_regs * regs)
@ -491,8 +491,6 @@ handle_signal(int canrestart, unsigned long sig,
if (ret == 0) if (ret == 0)
block_sigmask(ka, sig); block_sigmask(ka, sig);
return ret;
} }
/* /*
@ -525,16 +523,7 @@ do_signal(int canrestart, struct pt_regs *regs)
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(canrestart, signr, &info, &ka, handle_signal(canrestart, signr, &info, &ka, regs);
regs)) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }

View File

@ -426,7 +426,7 @@ give_sigsegv:
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka) struct k_sigaction *ka)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
@ -461,11 +461,12 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
else else
ret = setup_frame(sig, ka, oldset); ret = setup_frame(sig, ka, oldset);
if (ret == 0) if (ret)
block_sigmask(ka, sig); return;
return ret;
block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, __frame,
test_thread_flag(TIF_SINGLESTEP));
} /* end handle_signal() */ } /* end handle_signal() */
/*****************************************************************************/ /*****************************************************************************/
@ -495,18 +496,7 @@ static void do_signal(void)
signr = get_signal_to_deliver(&info, &ka, __frame, NULL); signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &info, &ka) == 0) { handle_signal(signr, &info, &ka);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, __frame,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }

View File

@ -442,10 +442,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (!ret) { if (!ret)
block_sigmask(ka, sig); block_sigmask(ka, sig);
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
} }
/* /*

View File

@ -149,11 +149,9 @@ sigsegv:
/* /*
* Setup invocation of signal handler * Setup invocation of signal handler
*/ */
static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka, static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs) struct pt_regs *regs)
{ {
int rc;
/* /*
* If we're handling a signal that aborted a system call, * If we're handling a signal that aborted a system call,
* set up the error return value before adding the signal * set up the error return value before adding the signal
@ -186,15 +184,13 @@ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
* Set up the stack frame; not doing the SA_SIGINFO thing. We * Set up the stack frame; not doing the SA_SIGINFO thing. We
* only set up the rt_frame flavor. * only set up the rt_frame flavor.
*/ */
rc = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
/* If there was an error on setup, no signal was delivered. */ /* If there was an error on setup, no signal was delivered. */
if (rc) if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
return rc; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, regs,
return 0; test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
@ -215,17 +211,7 @@ static void do_signal(struct pt_regs *regs)
signo = get_signal_to_deliver(&info, &sigact, regs, NULL); signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
if (signo > 0) { if (signo > 0) {
if (handle_signal(signo, &info, &sigact, regs) == 0) { handle_signal(signo, &info, &sigact, regs);
/*
* Successful delivery case. The saved sigmask is
* stored in the signal frame, and will be restored
* by sigreturn. We can clear the TIF flag.
*/
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signo, &info, &sigact, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }

View File

@ -501,16 +501,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
* Whee! Actually deliver the signal. If the delivery failed, we need to * Whee! Actually deliver the signal. If the delivery failed, we need to
* continue to iterate in this loop so we can deliver the SIGSEGV... * continue to iterate in this loop so we can deliver the SIGSEGV...
*/ */
if (handle_signal(signr, &ka, &info, scr)) { if (handle_signal(signr, &ka, &info, scr))
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
return; return;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */

View File

@ -267,7 +267,7 @@ static int prev_insn(struct pt_regs *regs)
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -295,10 +295,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up the stack frame */ /* Set up the stack frame */
if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs)) if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
return -EFAULT; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
return 0;
} }
/* /*
@ -333,8 +332,7 @@ static void do_signal(struct pt_regs *regs)
*/ */
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &ka, &info, regs) == 0) handle_signal(signr, &ka, &info, regs);
clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
} }

View File

@ -1147,8 +1147,6 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
regs->sr &= ~0x8000; regs->sr &= ~0x8000;
send_sig(SIGTRAP, current, 1); send_sig(SIGTRAP, current, 1);
} }
clear_thread_flag(TIF_RESTORE_SIGMASK);
} }
/* /*

View File

@ -310,7 +310,7 @@ do_restart:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, struct pt_regs *regs) siginfo_t *info, struct pt_regs *regs)
{ {
@ -324,11 +324,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
ret = setup_rt_frame(sig, ka, NULL, oldset, regs); ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
return 0;
} }
/* /*
@ -356,16 +354,7 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (in_syscall) if (in_syscall)
handle_restart(regs, &ka, 1); handle_restart(regs, &ka, 1);
if (!handle_signal(signr, &ka, &info, oldset, regs)) { handle_signal(signr, &ka, &info, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &=
~TS_RESTORE_SIGMASK;
}
return; return;
} }

View File

@ -514,7 +514,7 @@ struct mips_abi mips_abi = {
.restart = __NR_restart_syscall .restart = __NR_restart_syscall
}; };
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, struct pt_regs *regs) struct k_sigaction *ka, struct pt_regs *regs)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
@ -551,11 +551,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
ka, regs, sig, oldset); ka, regs, sig, oldset);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
return ret;
} }
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
@ -575,17 +573,7 @@ static void do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }

View File

@ -462,11 +462,12 @@ static int handle_signal(int sig,
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, oldset, regs);
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret)
return;
if (ret == 0) block_sigmask(ka, sig);
block_sigmask(ka, sig); tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
return ret;
} }
/* /*
@ -486,15 +487,6 @@ static void do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &info, &ka, regs) == 0) { if (handle_signal(signr, &info, &ka, regs) == 0) {
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag */
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
return; return;

View File

@ -263,8 +263,6 @@ handle_signal(unsigned long sig,
return; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
clear_thread_flag(TIF_RESTORE_SIGMASK);
tracehook_signal_handler(sig, info, ka, regs, tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP)); test_thread_flag(TIF_SINGLESTEP));
} }

View File

@ -459,6 +459,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
test_thread_flag(TIF_SINGLESTEP) || test_thread_flag(TIF_SINGLESTEP) ||
test_thread_flag(TIF_BLOCKSTEP)); test_thread_flag(TIF_BLOCKSTEP));
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
return 1; return 1;
} }
@ -593,13 +596,8 @@ do_signal(struct pt_regs *regs, long in_syscall)
/* Whee! Actually deliver the signal. If the /* Whee! Actually deliver the signal. If the
delivery failed, we need to continue to iterate in delivery failed, we need to continue to iterate in
this loop so we can deliver the SIGSEGV... */ this loop so we can deliver the SIGSEGV... */
if (handle_signal(signr, &info, &ka, regs, in_syscall)) { if (handle_signal(signr, &info, &ka, regs, in_syscall))
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
regs->gr[28]);
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
return; return;
}
} }
/* end of while(1) looping forever if we can't force a signal */ /* end of while(1) looping forever if we can't force a signal */

View File

@ -159,13 +159,6 @@ static int do_signal(struct pt_regs *regs)
regs->trap = 0; regs->trap = 0;
if (ret) { if (ret) {
block_sigmask(&ka, signr); 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. * Let tracing know that we've done the handler setup.
*/ */

View File

@ -572,7 +572,7 @@ give_sigsegv:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
int handle_signal32(unsigned long sig, struct k_sigaction *ka, void handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
{ {
int ret; int ret;
@ -583,8 +583,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
else else
ret = setup_frame32(sig, ka, oldset, regs); ret = setup_frame32(sig, ka, oldset, regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
return 0; /*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLE_STEP));
} }

View File

@ -31,7 +31,7 @@ void do_per_trap(struct pt_regs *regs);
void syscall_trace(struct pt_regs *regs, int entryexit); void syscall_trace(struct pt_regs *regs, int entryexit);
void kernel_stack_overflow(struct pt_regs * regs); void kernel_stack_overflow(struct pt_regs * regs);
void do_signal(struct pt_regs *regs); void do_signal(struct pt_regs *regs);
int handle_signal32(unsigned long sig, struct k_sigaction *ka, void handle_signal32(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs); siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
void do_notify_resume(struct pt_regs *regs); void do_notify_resume(struct pt_regs *regs);

View File

@ -367,7 +367,7 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
static int handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, sigset_t *oldset, siginfo_t *info, sigset_t *oldset,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -379,9 +379,13 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret) if (ret)
return ret; return;
block_sigmask(ka, sig); block_sigmask(ka, sig);
return 0; /*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLE_STEP));
} }
/* /*
@ -436,24 +440,10 @@ void do_signal(struct pt_regs *regs)
/* No longer in a system call */ /* No longer in a system call */
clear_thread_flag(TIF_SYSCALL); clear_thread_flag(TIF_SYSCALL);
if ((is_compat_task() ? if (is_compat_task())
handle_signal32(signr, &ka, &info, oldset, regs) : handle_signal32(signr, &ka, &info, oldset, regs);
handle_signal(signr, &ka, &info, oldset, regs)) == 0) { else
/* handle_signal(signr, &ka, &info, oldset, regs);
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
/*
* Let tracing know that we've done the handler setup.
*/
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLE_STEP));
}
return; return;
} }

View File

@ -241,11 +241,9 @@ give_sigsegv:
return -EFAULT; return -EFAULT;
} }
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, struct pt_regs *regs) struct k_sigaction *ka, struct pt_regs *regs)
{ {
int ret;
if (regs->is_syscall) { if (regs->is_syscall) {
switch (regs->regs[4]) { switch (regs->regs[4]) {
case ERESTART_RESTARTBLOCK: case ERESTART_RESTARTBLOCK:
@ -269,12 +267,10 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
/* /*
* Set up the stack frame * Set up the stack frame
*/ */
ret = setup_rt_frame(ka, regs, sig, sigmask_to_save(), info); if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0)
return;
if (ret == 0) block_sigmask(ka, sig);
block_sigmask(ka, sig);
return ret;
} }
static void do_signal(struct pt_regs *regs) static void do_signal(struct pt_regs *regs)
@ -294,17 +290,7 @@ static void do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Actually deliver the signal. */ /* Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }

View File

@ -522,7 +522,7 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
struct pt_regs *regs, unsigned int save_r0) struct pt_regs *regs, unsigned int save_r0)
{ {
@ -535,10 +535,11 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret)
block_sigmask(ka, sig); return;
block_sigmask(ka, sig);
return ret; tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
/* /*
@ -570,20 +571,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
handle_syscall_restart(save_r0, regs, &ka.sa); handle_syscall_restart(save_r0, regs, &ka.sa);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &ka, &info, handle_signal(signr, &ka, &info, regs, save_r0);
regs, save_r0) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
tracehook_signal_handler(signr, &info, &ka, regs,
test_thread_flag(TIF_SINGLESTEP));
}
return; return;
} }

View File

@ -43,7 +43,7 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
static int static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs * regs); struct pt_regs * regs);
@ -103,17 +103,7 @@ static void do_signal(struct pt_regs *regs)
handle_syscall_restart(regs, &ka.sa); handle_syscall_restart(regs, &ka.sa);
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* 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; return;
} }
@ -648,7 +638,7 @@ give_sigsegv:
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs * regs) struct pt_regs * regs)
{ {
@ -661,10 +651,12 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
else else
ret = setup_frame(sig, ka, oldset, regs); ret = setup_frame(sig, ka, oldset, regs);
if (ret == 0) if (ret)
block_sigmask(ka, sig); return;
return ret; block_sigmask(ka, sig);
tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP));
} }
asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)

View File

@ -775,7 +775,7 @@ sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
@ -787,12 +787,10 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
err = setup_frame32(ka, regs, signr, oldset); err = setup_frame32(ka, regs, signr, oldset);
if (err) if (err)
return err; return;
block_sigmask(ka, signr); block_sigmask(ka, signr);
tracehook_signal_handler(signr, info, ka, regs, 0); tracehook_signal_handler(signr, info, ka, regs, 0);
return 0;
} }
static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
@ -841,14 +839,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)
if (signr > 0) { if (signr > 0) {
if (restart_syscall) if (restart_syscall)
syscall_restart32(orig_i0, regs, &ka.sa); syscall_restart32(orig_i0, regs, &ka.sa);
if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { handle_signal32(signr, &ka, &info, oldset, regs);
/* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
return; return;
} }
if (restart_syscall && if (restart_syscall &&

View File

@ -449,7 +449,7 @@ sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int static inline void
handle_signal(unsigned long signr, struct k_sigaction *ka, handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, struct pt_regs *regs) siginfo_t *info, struct pt_regs *regs)
{ {
@ -462,12 +462,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
err = setup_frame(ka, regs, signr, oldset); err = setup_frame(ka, regs, signr, oldset);
if (err) if (err)
return err; return;
block_sigmask(ka, signr); block_sigmask(ka, signr);
tracehook_signal_handler(signr, info, ka, regs, 0); tracehook_signal_handler(signr, info, ka, regs, 0);
return 0;
} }
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@ -539,15 +537,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
if (signr > 0) { if (signr > 0) {
if (restart_syscall) if (restart_syscall)
syscall_restart(orig_i0, regs, &ka.sa); syscall_restart(orig_i0, regs, &ka.sa);
if (handle_signal(signr, &ka, &info, regs) == 0) { handle_signal(signr, &ka, &info, regs);
/* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }
if (restart_syscall && if (restart_syscall &&

View File

@ -466,7 +466,7 @@ sigsegv:
return -EFAULT; return -EFAULT;
} }
static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t *info, siginfo_t *info,
sigset_t *oldset, struct pt_regs *regs) sigset_t *oldset, struct pt_regs *regs)
{ {
@ -475,12 +475,10 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
err = setup_rt_frame(ka, regs, signr, oldset, err = setup_rt_frame(ka, regs, signr, oldset,
(ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
if (err) if (err)
return err; return;
block_sigmask(ka, signr); block_sigmask(ka, signr);
tracehook_signal_handler(signr, info, ka, regs, 0); tracehook_signal_handler(signr, info, ka, regs, 0);
return 0;
} }
static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@ -558,14 +556,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
if (signr > 0) { if (signr > 0) {
if (restart_syscall) if (restart_syscall)
syscall_restart(orig_i0, regs, &ka.sa); syscall_restart(orig_i0, regs, &ka.sa);
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { handle_signal(signr, &ka, &info, oldset, regs);
/* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
return; return;
} }
if (restart_syscall && if (restart_syscall &&

View File

@ -242,7 +242,7 @@ give_sigsegv:
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, siginfo_t *info, static void handle_signal(unsigned long sig, siginfo_t *info,
struct k_sigaction *ka, struct k_sigaction *ka,
struct pt_regs *regs) struct pt_regs *regs)
{ {
@ -279,15 +279,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
else else
#endif #endif
ret = setup_rt_frame(sig, ka, info, oldset, regs); ret = setup_rt_frame(sig, ka, info, oldset, regs);
if (ret == 0) { if (ret)
/* This code is only called from system calls or from return;
* the work_pending path in the return-to-user code, and block_sigmask(ka, sig);
* either way we can re-enable interrupts unconditionally.
*/
block_sigmask(ka, sig);
}
return ret;
} }
/* /*
@ -311,16 +305,7 @@ void do_signal(struct pt_regs *regs)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (handle_signal(signr, &info, &ka, regs) == 0) { handle_signal(signr, &info, &ka, regs);
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TS_RESTORE_SIGMASK flag.
*/
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
}
goto done; goto done;
} }

View File

@ -22,7 +22,7 @@ EXPORT_SYMBOL(unblock_signals);
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(struct pt_regs *regs, unsigned long signr, static void handle_signal(struct pt_regs *regs, unsigned long signr,
struct k_sigaction *ka, siginfo_t *info) struct k_sigaction *ka, siginfo_t *info)
{ {
sigset_t *oldset = sigmask_to_save(); sigset_t *oldset = sigmask_to_save();
@ -66,8 +66,6 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
force_sigsegv(signr, current); force_sigsegv(signr, current);
else else
block_sigmask(ka, signr); block_sigmask(ka, signr);
return err;
} }
static int kern_do_signal(struct pt_regs *regs) static int kern_do_signal(struct pt_regs *regs)
@ -79,17 +77,7 @@ static int kern_do_signal(struct pt_regs *regs)
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) { while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
handled_sig = 1; handled_sig = 1;
/* Whee! Actually deliver the signal. */ /* Whee! Actually deliver the signal. */
if (!handle_signal(regs, sig, &ka_copy, &info)) { handle_signal(regs, sig, &ka_copy, &info);
/*
* a signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
break;
}
} }
/* Did we come from a system call? */ /* Did we come from a system call? */

View File

@ -312,7 +312,7 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static int handle_signal(unsigned long sig, struct k_sigaction *ka, static void handle_signal(unsigned long sig, struct k_sigaction *ka,
siginfo_t *info, struct pt_regs *regs, int syscall) siginfo_t *info, struct pt_regs *regs, int syscall)
{ {
struct thread_info *thread = current_thread_info(); struct thread_info *thread = current_thread_info();
@ -363,15 +363,13 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
if (ret != 0) { if (ret != 0) {
force_sigsegv(sig, tsk); force_sigsegv(sig, tsk);
return ret; return;
} }
/* /*
* Block the signal if we were successful. * Block the signal if we were successful.
*/ */
block_sigmask(ka, sig); block_sigmask(ka, sig);
return 0;
} }
/* /*
@ -403,17 +401,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
signr = get_signal_to_deliver(&info, &ka, regs, NULL); signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (signr > 0) { if (signr > 0) {
if (handle_signal(signr, &ka, &info, regs, syscall) handle_signal(signr, &ka, &info, regs, syscall);
== 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
return; return;
} }

View File

@ -648,38 +648,27 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
{ {
int usig = signr_convert(sig); int usig = signr_convert(sig);
sigset_t *set = sigmask_to_save(); sigset_t *set = sigmask_to_save();
int ret;
/* Set up the stack frame */ /* Set up the stack frame */
if (is_ia32) { if (is_ia32) {
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
ret = ia32_setup_rt_frame(usig, ka, info, set, regs); return ia32_setup_rt_frame(usig, ka, info, set, regs);
else else
ret = ia32_setup_frame(usig, ka, set, regs); return ia32_setup_frame(usig, ka, set, regs);
#ifdef CONFIG_X86_X32_ABI #ifdef CONFIG_X86_X32_ABI
} else if (is_x32) { } else if (is_x32) {
ret = x32_setup_rt_frame(usig, ka, info, return x32_setup_rt_frame(usig, ka, info,
(compat_sigset_t *)set, regs); (compat_sigset_t *)set, regs);
#endif #endif
} else { } else {
ret = __setup_rt_frame(sig, ka, info, set, regs); return __setup_rt_frame(sig, ka, info, set, regs);
} }
if (ret) {
force_sigsegv(sig, current);
return -EFAULT;
}
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
return ret;
} }
static int static void
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
struct pt_regs *regs) struct pt_regs *regs)
{ {
int ret;
/* Are we from a system call? */ /* Are we from a system call? */
if (syscall_get_nr(current, regs) >= 0) { if (syscall_get_nr(current, regs) >= 0) {
/* If so, check system call restarting.. */ /* If so, check system call restarting.. */
@ -710,10 +699,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
likely(test_and_clear_thread_flag(TIF_FORCED_TF))) likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
regs->flags &= ~X86_EFLAGS_TF; regs->flags &= ~X86_EFLAGS_TF;
ret = setup_rt_frame(sig, ka, info, regs); if (setup_rt_frame(sig, ka, info, regs) < 0) {
force_sigsegv(sig, current);
if (ret) return;
return ret; }
/* /*
* Clear the direction flag as per the ABI for function entry. * Clear the direction flag as per the ABI for function entry.
@ -732,8 +721,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
tracehook_signal_handler(sig, info, ka, regs, tracehook_signal_handler(sig, info, ka, regs,
test_thread_flag(TIF_SINGLESTEP)); test_thread_flag(TIF_SINGLESTEP));
return 0;
} }
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32

View File

@ -499,7 +499,6 @@ static void do_signal(struct pt_regs *regs)
if (ret) if (ret)
return; return;
clear_thread_flag(TIF_RESTORE_SIGMASK);
block_sigmask(&ka, signr); block_sigmask(&ka, signr);
if (current->ptrace & PT_SINGLESTEP) if (current->ptrace & PT_SINGLESTEP)
task_pt_regs(current)->icountlevel = 1; task_pt_regs(current)->icountlevel = 1;

View File

@ -2382,6 +2382,12 @@ void block_sigmask(struct k_sigaction *ka, int signr)
{ {
sigset_t blocked; sigset_t blocked;
/* A signal was successfully delivered, and the
saved sigmask was stored on the signal frame,
and will be restored by sigreturn. So we can
simply clear the restore sigmask flag. */
clear_restore_sigmask();
sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask); sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
if (!(ka->sa.sa_flags & SA_NODEFER)) if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(&blocked, signr); sigaddset(&blocked, signr);