From 2a74213838104a41588d86fd5e8d344972891ace Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Thu, 14 Apr 2016 23:20:04 +0300 Subject: 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 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux/sched.h') diff --git a/include/linux/sched.h b/include/linux/sched.h index 52c4847b05e2..2950c5cd3005 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)) -- cgit