On Mon, Feb 29, 2016 at 1:29 PM, Stas Sergeev <s...@list.ru> wrote: > This patch implements the SS_AUTODISARM flag that can be ORed with > SS_ONSTACK when forming ss_flags. > When this flag is set, sigaltstack will be disabled when entering > the signal handler; more precisely, after saving sas to uc_stack. > When leaving the signal handler, the sigaltstack is restored by > uc_stack. > When this flag is used, it is safe to switch from sighandler with > swapcontext(). Without this flag, the subsequent signal will corrupt > the state of the switched-away sighandler. > > CC: Ingo Molnar <mi...@redhat.com> > CC: Peter Zijlstra <pet...@infradead.org> > CC: Richard Weinberger <rich...@nod.at> > CC: Andrew Morton <a...@linux-foundation.org> > CC: Oleg Nesterov <o...@redhat.com> > CC: Tejun Heo <t...@kernel.org> > CC: Heinrich Schuchardt <xypron.g...@gmx.de> > CC: Jason Low <jason.l...@hp.com> > CC: Andrea Arcangeli <aarca...@redhat.com> > CC: Frederic Weisbecker <fweis...@gmail.com> > CC: Konstantin Khlebnikov <khlebni...@yandex-team.ru> > CC: Josh Triplett <j...@joshtriplett.org> > CC: "Eric W. Biederman" <ebied...@xmission.com> > CC: Aleksa Sarai <cyp...@cyphar.com> > CC: "Amanieu d'Antras" <aman...@gmail.com> > CC: Paul Moore <pmo...@redhat.com> > CC: Sasha Levin <sasha.le...@oracle.com> > CC: Palmer Dabbelt <pal...@dabbelt.com> > CC: Vladimir Davydov <vdavy...@parallels.com> > CC: linux-kernel@vger.kernel.org > CC: linux-...@vger.kernel.org > CC: Andy Lutomirski <l...@amacapital.net> > > Signed-off-by: Stas Sergeev <s...@users.sourceforge.net> > --- > include/linux/sched.h | 8 ++++++++ > include/linux/signal.h | 4 +++- > include/uapi/linux/signal.h | 3 +++ > kernel/fork.c | 2 +- > kernel/signal.c | 23 ++++++++++++----------- > 5 files changed, 27 insertions(+), 13 deletions(-) > > diff --git a/include/linux/sched.h b/include/linux/sched.h > index a10494a..26201cd 100644 > --- a/include/linux/sched.h > +++ b/include/linux/sched.h > @@ -1587,6 +1587,7 @@ struct task_struct { > > unsigned long sas_ss_sp; > size_t sas_ss_size; > + unsigned sas_ss_flags; > > struct callback_head *task_works; > > @@ -2573,6 +2574,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)) > diff --git a/include/linux/signal.h b/include/linux/signal.h > index 92557bb..3fbe814 100644 > --- a/include/linux/signal.h > +++ b/include/linux/signal.h > @@ -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 > diff --git a/include/uapi/linux/signal.h b/include/uapi/linux/signal.h > index e1bd50c2..4691bc5 100644 > --- a/include/uapi/linux/signal.h > +++ b/include/uapi/linux/signal.h > @@ -6,5 +6,8 @@ > > #define SS_ONSTACK 1 > #define SS_DISABLE 2 > +#define SS_VALMASK 0xf
SS_MODE_MASK, perhaps? > diff --git a/kernel/signal.c b/kernel/signal.c > index 0508544..fab6bea 100644 > --- a/kernel/signal.c > +++ b/kernel/signal.c > @@ -3100,13 +3100,14 @@ do_sigaltstack (const stack_t __user *uss, stack_t > __user *uoss, unsigned long s > if (uss) { > void __user *ss_sp; > size_t ss_size; > - int ss_flags; > + unsigned ss_flags; > + unsigned ss_xflags; > > error = -EFAULT; > if (!access_ok(VERIFY_READ, uss, sizeof(*uss))) > goto out; > error = __get_user(ss_sp, &uss->ss_sp) | > - __get_user(ss_flags, &uss->ss_flags) | > + __get_user(ss_xflags, &uss->ss_flags) | > __get_user(ss_size, &uss->ss_size); > if (error) > goto out; > @@ -3115,14 +3116,8 @@ do_sigaltstack (const stack_t __user *uss, stack_t > __user *uoss, unsigned long s > if (on_sig_stack(sp)) > goto out; > > + ss_flags = ss_xflags & SS_VALMASK; This is poorly named. How about "ss_mode = ss_flags & SS_MODE_MASK"; --Andy