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

Commit 230e51f2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'core-signals-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull core signal updates from Ingo Molnar:
 "These updates from Stas Sergeev and Andy Lutomirski, improve the
  sigaltstack interface by extending its ABI with the SS_AUTODISARM
  feature, which makes it possible to use swapcontext() in a sighandler
  that works on sigaltstack.  Without this flag, the subsequent signal
  will corrupt the state of the switched-away sighandler.

  The inspiration is more robust dosemu signal handling"

* 'core-signals-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  signals/sigaltstack: Change SS_AUTODISARM to (1U << 31)
  signals/sigaltstack: Report current flag bits in sigaltstack()
  selftests/sigaltstack: Fix the sigaltstack test on old kernels
  signals/sigaltstack: If SS_AUTODISARM, bypass on_sig_stack()
  selftests/sigaltstack: Add new testcase for sigaltstack(SS_ONSTACK|SS_AUTODISARM)
  signals/sigaltstack: Implement SS_AUTODISARM flag
  signals/sigaltstack: Prepare to add new SS_xxx flags
  signals/sigaltstack, x86/signals: Unify the x86 sigaltstack check with other architectures
parents a3871bd4 91c61805
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -248,19 +248,18 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
	if (config_enabled(CONFIG_X86_64))
		sp -= 128;

	if (!onsigstack) {
	/* This is the X/Open sanctioned signal stack switching.  */
	if (ka->sa.sa_flags & SA_ONSTACK) {
			if (current->sas_ss_size)
		if (sas_ss_flags(sp) == 0)
			sp = current->sas_ss_sp + current->sas_ss_size;
	} else if (config_enabled(CONFIG_X86_32) &&
		   !onsigstack &&
		   (regs->ss & 0xffff) != __USER_DS &&
		   !(ka->sa.sa_flags & SA_RESTORER) &&
		   ka->sa.sa_restorer) {
		/* This is the legacy signal stack switching. */
		sp = (unsigned long) ka->sa.sa_restorer;
	}
	}

	if (fpu->fpstate_active) {
		sp = fpu__alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
+20 −0
Original line number Diff line number Diff line
@@ -1595,6 +1595,7 @@ struct task_struct {

	unsigned long sas_ss_sp;
	size_t sas_ss_size;
	unsigned sas_ss_flags;

	struct callback_head *task_works;

@@ -2574,6 +2575,18 @@ static inline int kill_cad_pid(int sig, int priv)
 */
static inline int on_sig_stack(unsigned long sp)
{
	/*
	 * If the signal stack is SS_AUTODISARM then, by construction, we
	 * can't be on the signal stack unless user code deliberately set
	 * SS_AUTODISARM when we were already on it.
	 *
	 * This improves reliability: if user state gets corrupted such that
	 * the stack pointer points very close to the end of the signal stack,
	 * then this check will enable the signal to be handled anyway.
	 */
	if (current->sas_ss_flags & SS_AUTODISARM)
		return 0;

#ifdef CONFIG_STACK_GROWSUP
	return sp >= current->sas_ss_sp &&
		sp - current->sas_ss_sp < current->sas_ss_size;
@@ -2591,6 +2604,13 @@ static inline int sas_ss_flags(unsigned long sp)
	return on_sig_stack(sp) ? SS_ONSTACK : 0;
}

static inline void sas_ss_reset(struct task_struct *p)
{
	p->sas_ss_sp = 0;
	p->sas_ss_size = 0;
	p->sas_ss_flags = SS_DISABLE;
}

static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig)
{
	if (unlikely((ksig->ka.sa.sa_flags & SA_ONSTACK)) && ! sas_ss_flags(sp))
+3 −1
Original line number Diff line number Diff line
@@ -432,8 +432,10 @@ int __save_altstack(stack_t __user *, unsigned long);
	stack_t __user *__uss = uss; \
	struct task_struct *t = current; \
	put_user_ex((void __user *)t->sas_ss_sp, &__uss->ss_sp); \
	put_user_ex(sas_ss_flags(sp), &__uss->ss_flags); \
	put_user_ex(t->sas_ss_flags, &__uss->ss_flags); \
	put_user_ex(t->sas_ss_size, &__uss->ss_size); \
	if (t->sas_ss_flags & SS_AUTODISARM) \
		sas_ss_reset(t); \
} while (0);

#ifdef CONFIG_PROC_FS
+5 −0
Original line number Diff line number Diff line
@@ -7,4 +7,9 @@
#define SS_ONSTACK	1
#define SS_DISABLE	2

/* bit-flags */
#define SS_AUTODISARM	(1U << 31)	/* disable sas during sighandling */
/* mask for all SS_xxx flags */
#define SS_FLAG_BITS	SS_AUTODISARM

#endif /* _UAPI_LINUX_SIGNAL_H */
+1 −1
Original line number Diff line number Diff line
@@ -1494,7 +1494,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
	 * sigaltstack should be cleared when sharing the same VM
	 */
	if ((clone_flags & (CLONE_VM|CLONE_VFORK)) == CLONE_VM)
		p->sas_ss_sp = p->sas_ss_size = 0;
		sas_ss_reset(p);

	/*
	 * Syscall tracing and stepping should be turned off in the
Loading