Message ID | 20201119190237.626-3-chang.seok.bae@intel.com |
---|---|
State | New |
Headers | show |
Series | x86: Improve Minimum Alternate Stack Size | expand |
On Thu, Nov 19, 2020 at 11:02:35AM -0800, Chang S. Bae wrote: > Historically, signal.h defines MINSIGSTKSZ (2KB) and SIGSTKSZ (8KB), for > use by all architectures with sigaltstack(2). Over time, the hardware state > size grew, but these constants did not evolve. Today, literal use of these > constants on several architectures may result in signal stack overflow, and > thus user data corruption. > > A few years ago, the ARM team addressed this issue by establishing > getauxval(AT_MINSIGSTKSZ), such that the kernel can supply at runtime value > that is an appropriate replacement on the current and future hardware. > > Add getauxval(AT_MINSIGSTKSZ) support to x86, analogous to the support > added for ARM in commit 94b07c1f8c39 ("arm64: signal: Report signal frame > size to userspace via auxv"). I don't see it documented here: https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man3/getauxval.3 Dunno, now that two architectures will have it, maybe that is good enough reason to document it. Adding Michael.
Hey Dave Marin, On 11/26/20 6:44 PM, Borislav Petkov wrote: > On Thu, Nov 19, 2020 at 11:02:35AM -0800, Chang S. Bae wrote: >> Historically, signal.h defines MINSIGSTKSZ (2KB) and SIGSTKSZ (8KB), for >> use by all architectures with sigaltstack(2). Over time, the hardware state >> size grew, but these constants did not evolve. Today, literal use of these >> constants on several architectures may result in signal stack overflow, and >> thus user data corruption. >> >> A few years ago, the ARM team addressed this issue by establishing >> getauxval(AT_MINSIGSTKSZ), such that the kernel can supply at runtime value >> that is an appropriate replacement on the current and future hardware. >> >> Add getauxval(AT_MINSIGSTKSZ) support to x86, analogous to the support >> added for ARM in commit 94b07c1f8c39 ("arm64: signal: Report signal frame >> size to userspace via auxv"). > > I don't see it documented here: > > https://git.kernel.org/pub/scm/docs/man-pages/man-pages.git/tree/man3/getauxval.3 > > Dunno, now that two architectures will have it, maybe that is good > enough reason to document it. > > Adding Michael. Commit 94b07c1f8c39 was your, Dave. Might I convince you to write a patch for getauxval(3)? Thanks, Michael
diff --git a/arch/x86/include/asm/elf.h b/arch/x86/include/asm/elf.h index b9a5d488f1a5..044b024abea1 100644 --- a/arch/x86/include/asm/elf.h +++ b/arch/x86/include/asm/elf.h @@ -311,6 +311,7 @@ do { \ NEW_AUX_ENT(AT_SYSINFO, VDSO_ENTRY); \ NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_CURRENT_BASE); \ } \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \ } while (0) /* @@ -327,6 +328,7 @@ extern unsigned long task_size_32bit(void); extern unsigned long task_size_64bit(int full_addr_space); extern unsigned long get_mmap_base(int is_legacy); extern bool mmap_address_hint_valid(unsigned long addr, unsigned long len); +extern unsigned long get_sigframe_size(void); #ifdef CONFIG_X86_32 @@ -348,6 +350,7 @@ do { \ if (vdso64_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, \ (unsigned long __force)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \ } while (0) /* As a historical oddity, the x32 and x86_64 vDSOs are controlled together. */ @@ -356,6 +359,7 @@ do { \ if (vdso64_enabled) \ NEW_AUX_ENT(AT_SYSINFO_EHDR, \ (unsigned long __force)current->mm->context.vdso); \ + NEW_AUX_ENT(AT_MINSIGSTKSZ, get_sigframe_size()); \ } while (0) #define AT_SYSINFO 32 diff --git a/arch/x86/include/uapi/asm/auxvec.h b/arch/x86/include/uapi/asm/auxvec.h index 580e3c567046..edd7808060e6 100644 --- a/arch/x86/include/uapi/asm/auxvec.h +++ b/arch/x86/include/uapi/asm/auxvec.h @@ -10,11 +10,13 @@ #endif #define AT_SYSINFO_EHDR 33 +#define AT_MINSIGSTKSZ 51 + /* entries in ARCH_DLINFO: */ #if defined(CONFIG_IA32_EMULATION) || !defined(CONFIG_X86_64) -# define AT_VECTOR_SIZE_ARCH 2 +# define AT_VECTOR_SIZE_ARCH 3 #else /* else it's non-compat x86-64 */ -# define AT_VECTOR_SIZE_ARCH 1 +# define AT_VECTOR_SIZE_ARCH 2 #endif #endif /* _ASM_X86_AUXVEC_H */ diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index bae35ff6e744..ee6f1ceaa7a2 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -720,6 +720,11 @@ void __init init_sigframe_size(void) max_frame_size = round_up(max_frame_size, FRAME_ALIGNMENT); } +unsigned long get_sigframe_size(void) +{ + return max_frame_size; +} + static inline int is_ia32_compat_frame(struct ksignal *ksig) { return IS_ENABLED(CONFIG_IA32_EMULATION) &&