Commit e933c70d authored by Matt Fleming's avatar Matt Fleming Committed by Jonas Bonn
Browse files

OpenRISC: Don't mask signals if we fail to setup signal stack



setup_rt_frame() needs to return an indication of whether it succeeded
or failed in setting up the signal stack frame. If setup_rt_frame()
fails then we must not modify current->blocked.

Acked-by: default avatarOleg Nesterov <oleg@redhat.com>
Cc: Jonas Bonn <jonas@southpole.se>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: linux@lists.openrisc.net
Signed-off-by: default avatarMatt Fleming <matt.fleming@intel.com>
Signed-off-by: default avatarJonas Bonn <jonas@southpole.se>
parent b675eeb7
Loading
Loading
Loading
Loading
+18 −11
Original line number Original line Diff line number Diff line
@@ -189,7 +189,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
 * trampoline which performs the syscall sigreturn, or a provided
 * trampoline which performs the syscall sigreturn, or a provided
 * user-mode trampoline.
 * user-mode trampoline.
 */
 */
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
			  sigset_t *set, struct pt_regs *regs)
			  sigset_t *set, struct pt_regs *regs)
{
{
	struct rt_sigframe *frame;
	struct rt_sigframe *frame;
@@ -247,18 +247,23 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
	/* actually move the usp to reflect the stacked frame */
	/* actually move the usp to reflect the stacked frame */
	regs->sp = (unsigned long)frame;
	regs->sp = (unsigned long)frame;


	return;
	return 0;


give_sigsegv:
give_sigsegv:
	force_sigsegv(sig, current);
	force_sigsegv(sig, current);
	return -EFAULT;
}
}


static inline void
static inline int
handle_signal(unsigned long sig,
handle_signal(unsigned long sig,
	      siginfo_t *info, struct k_sigaction *ka,
	      siginfo_t *info, struct k_sigaction *ka,
	      sigset_t *oldset, struct pt_regs *regs)
	      sigset_t *oldset, struct pt_regs *regs)
{
{
	setup_rt_frame(sig, ka, info, oldset, regs);
	int ret;

	ret = setup_rt_frame(sig, ka, info, oldset, regs);
	if (ret)
		return ret;


	spin_lock_irq(&current->sighand->siglock);
	spin_lock_irq(&current->sighand->siglock);
	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
	sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
@@ -267,6 +272,8 @@ handle_signal(unsigned long sig,
	recalc_sigpending();
	recalc_sigpending();


	spin_unlock_irq(&current->sighand->siglock);
	spin_unlock_irq(&current->sighand->siglock);

	return 0;
}
}


/*
/*
@@ -355,13 +362,13 @@ void do_signal(struct pt_regs *regs)
			oldset = &current->blocked;
			oldset = &current->blocked;


		/* Whee!  Actually deliver the signal.  */
		/* Whee!  Actually deliver the signal.  */
		handle_signal(signr, &info, &ka, oldset, regs);
		if (!handle_signal(signr, &info, &ka, oldset, regs)) {
			/* a signal was successfully delivered; the saved
			/* a signal was successfully delivered; the saved
			 * sigmask will have been stored in the signal frame,
			 * sigmask will have been stored in the signal frame,
			 * and will be restored by sigreturn, so we can simply
			 * and will be restored by sigreturn, so we can simply
			 * clear the TIF_RESTORE_SIGMASK flag */
			 * clear the TIF_RESTORE_SIGMASK flag */
		if (test_thread_flag(TIF_RESTORE_SIGMASK))
			clear_thread_flag(TIF_RESTORE_SIGMASK);
			clear_thread_flag(TIF_RESTORE_SIGMASK);
		}


		tracehook_signal_handler(signr, &info, &ka, regs,
		tracehook_signal_handler(signr, &info, &ka, regs,
					 test_thread_flag(TIF_SINGLESTEP));
					 test_thread_flag(TIF_SINGLESTEP));