Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/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
  • Loading branch information
torvalds committed Jun 1, 2012
2 parents 1193755 + 44fbbb3 commit 86c47b7
Show file tree
Hide file tree
Showing 68 changed files with 482 additions and 1,091 deletions.
18 changes: 3 additions & 15 deletions arch/alpha/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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 = &current->blocked;
sigset_t *oldset = sigmask_to_save();
int ret;

if (test_thread_flag(TIF_RESTORE_SIGMASK))
oldset = &current->saved_sigmask;

if (ka->sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
else
Expand All @@ -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
Expand Down Expand Up @@ -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(&current->saved_sigmask);

restore_saved_sigmask();
if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */
}
Expand Down
47 changes: 8 additions & 39 deletions arch/arm/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@

#include "signal.h"

#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))

/*
* For ARM syscalls, we encode the syscall number into the instruction.
*/
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand All @@ -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);
}

/*
Expand Down Expand Up @@ -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
Expand All @@ -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 = &current->saved_sigmask;
else
oldset = &current->blocked;
if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
/*
* A signal was successfully delivered; the saved
* sigmask will have been stored in the signal frame,
* and will be restored by sigreturn, so we can simply
* clear the TIF_RESTORE_SIGMASK flag.
*/
if (test_thread_flag(TIF_RESTORE_SIGMASK))
clear_thread_flag(TIF_RESTORE_SIGMASK);
}
handle_signal(signr, &ka, &info, regs);
return;
}

Expand All @@ -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(&current->saved_sigmask);
restore_saved_sigmask();
}

asmlinkage void
Expand Down
4 changes: 2 additions & 2 deletions arch/avr32/kernel/entry-avr32b.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
41 changes: 13 additions & 28 deletions arch/avr32/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -224,38 +221,35 @@ 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);
}

/*
* Note that 'init' is a special process: it doesn't get signals it
* 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;
Expand All @@ -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 = &current->saved_sigmask;
else if (!oldset)
oldset = &current->blocked;
return;

signr = get_signal_to_deliver(&info, &ka, regs, NULL);
if (syscall) {
Expand All @@ -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, &current->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)
Expand All @@ -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, &current->blocked, syscall);
if (ti->flags & _TIF_SIGPENDING))
do_signal(regs, syscall);

if (ti->flags & _TIF_NOTIFY_RESUME) {
clear_thread_flag(TIF_NOTIFY_RESUME);
Expand Down
2 changes: 0 additions & 2 deletions arch/blackfin/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down
Loading

0 comments on commit 86c47b7

Please sign in to comment.