From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932566AbcECHwR (ORCPT ); Tue, 3 May 2016 03:52:17 -0400 Received: from terminus.zytor.com ([198.137.202.10]:37434 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750846AbcECHwO (ORCPT ); Tue, 3 May 2016 03:52:14 -0400 Date: Tue, 3 May 2016 00:50:30 -0700 From: tip-bot for Stas Sergeev Message-ID: Cc: amanieu@gmail.com, oleg@redhat.com, torvalds@linux-foundation.org, luto@amacapital.net, xypron.glpk@gmx.de, akpm@linux-foundation.org, jason.low2@hp.com, cyphar@cyphar.com, aarcange@redhat.com, ebiederm@xmission.com, viro@zeniv.linux.org.uk, josh@joshtriplett.org, tj@kernel.org, hpa@zytor.com, linux-kernel@vger.kernel.org, vdavydov@parallels.com, stsp@list.ru, mingo@kernel.org, tglx@linutronix.de, peterz@infradead.org, bp@alien8.de, pmoore@redhat.com, fweisbec@gmail.com, khlebnikov@yandex-team.ru, sasha.levin@oracle.com, shuahkh@osg.samsung.com, palmer@dabbelt.com, brgerst@gmail.com, richard@nod.at, xemul@parallels.com, dvlasenk@redhat.com Reply-To: josh@joshtriplett.org, viro@zeniv.linux.org.uk, stsp@list.ru, vdavydov@parallels.com, linux-kernel@vger.kernel.org, hpa@zytor.com, tj@kernel.org, cyphar@cyphar.com, akpm@linux-foundation.org, jason.low2@hp.com, xypron.glpk@gmx.de, luto@amacapital.net, oleg@redhat.com, amanieu@gmail.com, torvalds@linux-foundation.org, ebiederm@xmission.com, aarcange@redhat.com, palmer@dabbelt.com, sasha.levin@oracle.com, shuahkh@osg.samsung.com, dvlasenk@redhat.com, xemul@parallels.com, richard@nod.at, brgerst@gmail.com, peterz@infradead.org, mingo@kernel.org, tglx@linutronix.de, khlebnikov@yandex-team.ru, fweisbec@gmail.com, pmoore@redhat.com, bp@alien8.de In-Reply-To: <1460665206-13646-4-git-send-email-stsp@list.ru> References: <1460665206-13646-4-git-send-email-stsp@list.ru> To: linux-tip-commits@vger.kernel.org Subject: [tip:core/signals] signals/sigaltstack: Implement SS_AUTODISARM flag Git-Commit-ID: 2a74213838104a41588d86fd5e8d344972891ace X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 2a74213838104a41588d86fd5e8d344972891ace Gitweb: http://git.kernel.org/tip/2a74213838104a41588d86fd5e8d344972891ace Author: Stas Sergeev AuthorDate: Thu, 14 Apr 2016 23:20:04 +0300 Committer: Ingo Molnar CommitDate: Tue, 3 May 2016 08:37:59 +0200 signals/sigaltstack: Implement SS_AUTODISARM flag This patch implements the SS_AUTODISARM flag that can be OR-ed 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. To detect the support of this functionality, one can do: err = sigaltstack(SS_DISABLE | SS_AUTODISARM); if (err && errno == EINVAL) unsupported(); Signed-off-by: Stas Sergeev Cc: Al Viro Cc: Aleksa Sarai Cc: Amanieu d'Antras Cc: Andrea Arcangeli Cc: Andrew Morton Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Brian Gerst Cc: Denys Vlasenko Cc: Eric W. Biederman Cc: Frederic Weisbecker Cc: H. Peter Anvin Cc: Heinrich Schuchardt Cc: Jason Low Cc: Josh Triplett Cc: Konstantin Khlebnikov Cc: Linus Torvalds Cc: Oleg Nesterov Cc: Palmer Dabbelt Cc: Paul Moore Cc: Pavel Emelyanov Cc: Peter Zijlstra Cc: Richard Weinberger Cc: Sasha Levin Cc: Shuah Khan Cc: Tejun Heo Cc: Thomas Gleixner Cc: Vladimir Davydov Cc: linux-api@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/1460665206-13646-4-git-send-email-stsp@list.ru Signed-off-by: Ingo Molnar --- include/linux/sched.h | 8 ++++++++ include/linux/signal.h | 4 +++- include/uapi/linux/signal.h | 4 +++- kernel/fork.c | 2 +- kernel/signal.c | 10 ++++++++-- 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/linux/sched.h b/include/linux/sched.h index 52c4847..2950c5c 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1596,6 +1596,7 @@ struct task_struct { unsigned long sas_ss_sp; size_t sas_ss_size; + unsigned sas_ss_flags; struct callback_head *task_works; @@ -2592,6 +2593,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 7c73165..7388260 100644 --- a/include/uapi/linux/signal.h +++ b/include/uapi/linux/signal.h @@ -7,7 +7,9 @@ #define SS_ONSTACK 1 #define SS_DISABLE 2 +/* bit-flags */ +#define SS_AUTODISARM (1 << 4) /* disable sas during sighandling */ /* mask for all SS_xxx flags */ -#define SS_FLAG_BITS 0 +#define SS_FLAG_BITS SS_AUTODISARM #endif /* _UAPI_LINUX_SIGNAL_H */ diff --git a/kernel/fork.c b/kernel/fork.c index d277e83..3e84515 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -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 diff --git a/kernel/signal.c b/kernel/signal.c index b1c6eb4..bf97ea5 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3137,6 +3137,7 @@ do_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, unsigned long s current->sas_ss_sp = (unsigned long) ss_sp; current->sas_ss_size = ss_size; + current->sas_ss_flags = ss_flags; } error = 0; @@ -3167,9 +3168,14 @@ int restore_altstack(const stack_t __user *uss) int __save_altstack(stack_t __user *uss, unsigned long sp) { struct task_struct *t = current; - return __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) | - __put_user(sas_ss_flags(sp), &uss->ss_flags) | + int err = __put_user((void __user *)t->sas_ss_sp, &uss->ss_sp) | + __put_user(t->sas_ss_flags, &uss->ss_flags) | __put_user(t->sas_ss_size, &uss->ss_size); + if (err) + return err; + if (t->sas_ss_flags & SS_AUTODISARM) + sas_ss_reset(t); + return 0; } #ifdef CONFIG_COMPAT