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

Commit 68fa383f authored by Martin Michlmayr's avatar Martin Michlmayr Committed by Ralf Baechle
Browse files

[MIPS] Add support for TIF_RESTORE_SIGMASK for signal32


    
Following the recent implementation of TIF_RESTORE_SIGMASK in
arch/mips/kernel/signal.c, 64-bit kernels with 32-bit user-land
compatibility oops when starting init.  signal32.c needs to be
converted to use TIF_RESTORE_SIGMASK too.
    
Signed-off-by: default avatarMartin Michlmayr <tbm@cyrius.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 8ecbbcaf
Loading
Loading
Loading
Loading
+41 −27
Original line number Original line Diff line number Diff line
@@ -106,8 +106,6 @@ typedef struct compat_siginfo {


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


extern int do_signal32(sigset_t *oldset, struct pt_regs *regs);

/* 32-bit compatibility types */
/* 32-bit compatibility types */


#define _NSIG_BPW32	32
#define _NSIG_BPW32	32
@@ -198,7 +196,7 @@ __attribute_used__ noinline static int
_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
_sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
{
	compat_sigset_t *uset;
	compat_sigset_t *uset;
	sigset_t newset, saveset;
	sigset_t newset;


	uset = (compat_sigset_t *) regs.regs[4];
	uset = (compat_sigset_t *) regs.regs[4];
	if (get_sigset(&newset, uset))
	if (get_sigset(&newset, uset))
@@ -206,19 +204,15 @@ _sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
	sigdelsetmask(&newset, ~_BLOCKABLE);
	sigdelsetmask(&newset, ~_BLOCKABLE);


	spin_lock_irq(&current->sighand->siglock);
	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	current->saved_sigmask = current->blocked;
	current->blocked = newset;
	current->blocked = newset;
	recalc_sigpending();
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
	spin_unlock_irq(&current->sighand->siglock);


	regs.regs[2] = EINTR;
	regs.regs[7] = 1;
	while (1) {
	current->state = TASK_INTERRUPTIBLE;
	current->state = TASK_INTERRUPTIBLE;
	schedule();
	schedule();
		if (do_signal32(&saveset, &regs))
	set_thread_flag(TIF_RESTORE_SIGMASK);
			return -EINTR;
	return -ERESTARTNOHAND;
	}
}
}


save_static_function(sys32_rt_sigsuspend);
save_static_function(sys32_rt_sigsuspend);
@@ -226,7 +220,7 @@ __attribute_used__ noinline static int
_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
_sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
{
{
	compat_sigset_t *uset;
	compat_sigset_t *uset;
	sigset_t newset, saveset;
	sigset_t newset;
        size_t sigsetsize;
        size_t sigsetsize;


	/* XXX Don't preclude handling different sized sigset_t's.  */
	/* XXX Don't preclude handling different sized sigset_t's.  */
@@ -240,19 +234,15 @@ _sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
	sigdelsetmask(&newset, ~_BLOCKABLE);
	sigdelsetmask(&newset, ~_BLOCKABLE);


	spin_lock_irq(&current->sighand->siglock);
	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	current->saved_sigmask = current->blocked;
	current->blocked = newset;
	current->blocked = newset;
        recalc_sigpending();
        recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
	spin_unlock_irq(&current->sighand->siglock);


	regs.regs[2] = EINTR;
	regs.regs[7] = 1;
	while (1) {
	current->state = TASK_INTERRUPTIBLE;
	current->state = TASK_INTERRUPTIBLE;
	schedule();
	schedule();
		if (do_signal32(&saveset, &regs))
	set_thread_flag(TIF_RESTORE_SIGMASK);
			return -EINTR;
	return -ERESTARTNOHAND;
	}
}
}


asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
asmlinkage int sys32_sigaction(int sig, const struct sigaction32 *act,
@@ -810,9 +800,10 @@ static inline int handle_signal(unsigned long sig, siginfo_t *info,
	return ret;
	return ret;
}
}


int do_signal32(sigset_t *oldset, struct pt_regs *regs)
int do_signal32(struct pt_regs *regs)
{
{
	struct k_sigaction ka;
	struct k_sigaction ka;
	sigset_t *oldset;
	siginfo_t info;
	siginfo_t info;
	int signr;
	int signr;


@@ -827,12 +818,25 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
	if (try_to_freeze())
	if (try_to_freeze())
		goto no_signal;
		goto no_signal;


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


	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
	if (signr > 0)
	if (signr > 0) {
		return handle_signal(signr, &info, &ka, oldset, regs);
		/* 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);
		}
	}


no_signal:
no_signal:
	/*
	/*
@@ -853,6 +857,16 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
			regs->cp0_epc -= 4;
			regs->cp0_epc -= 4;
		}
		}
	}
	}

	/*
	* 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, &current->saved_sigmask, NULL);
	}

	return 0;
	return 0;
}
}