Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 86c47b70 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents 1193755a 44fbbb3d
Loading
Loading
Loading
Loading
+3 −15
Original line number Diff line number Diff line
@@ -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 = &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
@@ -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(&current->saved_sigmask);

	restore_saved_sigmask();
	if (single_stepping)
		ptrace_set_bpt(current);	/* re-set breakpoint */
}
+8 −39
Original line number Diff line number Diff line
@@ -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 = &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;
	}

@@ -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
+2 −2
Original line number Diff line number Diff line
@@ -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
+13 −28
Original line number Diff line number Diff line
@@ -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 = &current->saved_sigmask;
	else if (!oldset)
		oldset = &current->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, &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)
@@ -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);
+0 −2
Original line number Diff line number Diff line
@@ -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)
Loading