Message ID | 20201223015312.4882-4-chang.seok.bae@intel.com |
---|---|
State | New |
Headers | show |
Series | x86: Improve Minimum Alternate Stack Size | expand |
On Wed, Dec 23, 2020 at 2:57 AM Chang S. Bae <chang.seok.bae@intel.com> wrote: > The kernel pushes data on the userspace stack when entering a signal. If > using a sigaltstack(), the kernel precisely knows the user stack size. > > When the kernel knows that the user stack is too small, avoid the overflow > and do an immediate SIGSEGV instead. > > This overflow is known to occur on systems with large XSAVE state. The > effort to increase the size typically used for altstacks reduces the > frequency of these overflows, but this approach is still useful for legacy > binaries. > > Suggested-by: Jann Horn <jannh@google.com> > Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com> > Reviewed-by: Len Brown <len.brown@intel.com> > Cc: Jann Horn <jannh@google.com> > Cc: x86@kernel.org > Cc: linux-kernel@vger.kernel.org Reviewed-by: Jann Horn <jannh@google.com>
On Tue, Dec 22, 2020 at 05:53:11PM -0800, Chang S. Bae wrote: > The kernel pushes data on the userspace stack when entering a signal. If > using a sigaltstack(), the kernel precisely knows the user stack size. ^^^^^^^^^^^^^^^^^^^^^^^ Formulate properly. > > When the kernel knows that the user stack is too small, avoid the overflow > and do an immediate SIGSEGV instead. ^^^^^^^^^^^^^^^^^^^^^^^ Ditto. > This overflow is known to occur on systems with large XSAVE state. The > effort to increase the size typically used for altstacks reduces the ^^^^^^^^^^ "alternate signal stacks"
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index 761d856f8ef7..91056a940271 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -242,7 +242,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, unsigned long math_size = 0; unsigned long sp = regs->sp; unsigned long buf_fx = 0; - int onsigstack = on_sig_stack(sp); + bool onsigstack = on_sig_stack(sp); int ret; /* redzone */ @@ -251,8 +251,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (sas_ss_flags(sp) == 0) + if (sas_ss_flags(sp) == 0) { sp = current->sas_ss_sp + current->sas_ss_size; + /* On the alternate signal stack */ + onsigstack = true; + } } else if (IS_ENABLED(CONFIG_X86_32) && !onsigstack && regs->ss != __USER_DS &&