summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-05-16 21:25:25 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2016-05-16 21:25:25 +0200
commit230e51f21101e49c8d73018d414adbd0d57459a1 (patch)
tree95dbb338a2ae90c0f8a060836bf93d858425e00a /arch
parentMerge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kerne... (diff)
parentsignals/sigaltstack: Change SS_AUTODISARM to (1U << 31) (diff)
downloadlinux-230e51f21101e49c8d73018d414adbd0d57459a1.tar.xz
linux-230e51f21101e49c8d73018d414adbd0d57459a1.zip
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
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kernel/signal.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 548ddf7d6fd2..3e84ef16f657 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -248,18 +248,17 @@ 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)
- sp = current->sas_ss_sp + current->sas_ss_size;
- } else if (config_enabled(CONFIG_X86_32) &&
- (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;
- }
+ /* This is the X/Open sanctioned signal stack switching. */
+ if (ka->sa.sa_flags & SA_ONSTACK) {
+ 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) {