Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751434AbcCFUHe (ORCPT ); Sun, 6 Mar 2016 15:07:34 -0500 Received: from mail-oi0-f45.google.com ([209.85.218.45]:35141 "EHLO mail-oi0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750798AbcCFUHZ (ORCPT ); Sun, 6 Mar 2016 15:07:25 -0500 MIME-Version: 1.0 In-Reply-To: <1456781345-8243-2-git-send-email-stsp@list.ru> References: <1456781345-8243-1-git-send-email-stsp@list.ru> <1456781345-8243-2-git-send-email-stsp@list.ru> From: Andy Lutomirski Date: Sun, 6 Mar 2016 12:07:04 -0800 Message-ID: Subject: Re: [PATCH 1/2] sigaltstack: implement SS_AUTODISARM flag To: Stas Sergeev Cc: Ingo Molnar , Peter Zijlstra , Richard Weinberger , Andrew Morton , Oleg Nesterov , Tejun Heo , Heinrich Schuchardt , Jason Low , Andrea Arcangeli , Frederic Weisbecker , Konstantin Khlebnikov , Josh Triplett , "Eric W. Biederman" , Aleksa Sarai , "Amanieu d'Antras" , Paul Moore , Sasha Levin , Palmer Dabbelt , Vladimir Davydov , "linux-kernel@vger.kernel.org" , Linux API , Stas Sergeev Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4880 Lines: 127 On Mon, Feb 29, 2016 at 1:29 PM, Stas Sergeev 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 > CC: Peter Zijlstra > CC: Richard Weinberger > CC: Andrew Morton > CC: Oleg Nesterov > CC: Tejun Heo > CC: Heinrich Schuchardt > CC: Jason Low > CC: Andrea Arcangeli > CC: Frederic Weisbecker > CC: Konstantin Khlebnikov > CC: Josh Triplett > CC: "Eric W. Biederman" > CC: Aleksa Sarai > CC: "Amanieu d'Antras" > CC: Paul Moore > CC: Sasha Levin > CC: Palmer Dabbelt > CC: Vladimir Davydov > CC: linux-kernel@vger.kernel.org > CC: linux-api@vger.kernel.org > CC: Andy Lutomirski > > Signed-off-by: Stas Sergeev > --- > 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