On Tue, Jun 23, 2020 at 03:59:16PM +0200, Peter Zijlstra wrote: > So basically when your exception frame points to your own IST, you die. > That sounds like something we should have in generic IST code. Something like this... #DF already dies and NMI is 'magic' --- arch/x86/entry/common.c | 7 +++++++ arch/x86/include/asm/idtentry.h | 12 +++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index af0d57ed5e69..e38e4f34c90c 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -742,6 +742,13 @@ noinstr void idtentry_exit_nmi(struct pt_regs *regs, bool restore) __nmi_exit(); } +noinstr void idtentry_validate_ist(struct pt_regs *regs) +{ + if ((regs->sp & ~(EXCEPTION_STKSZ-1)) == + (_RET_IP_ & ~(EXCEPTION_STKSZ-1))) + die("IST stack recursion", regs, 0); +} + #ifdef CONFIG_XEN_PV #ifndef CONFIG_PREEMPTION /* diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h index 4e399f120ff8..974c1a4eacbb 100644 --- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -19,6 +19,8 @@ void idtentry_exit_cond_rcu(struct pt_regs *regs, bool rcu_exit); bool idtentry_enter_nmi(struct pt_regs *regs); void idtentry_exit_nmi(struct pt_regs *regs, bool irq_state); +void idtentry_validate_ist(struct pt_regs *regs); + /** * DECLARE_IDTENTRY - Declare functions for simple IDT entry points * No error code pushed by hardware @@ -322,7 +324,15 @@ static __always_inline void __##func(struct pt_regs *regs) * Maps to DEFINE_IDTENTRY_RAW */ #define DEFINE_IDTENTRY_IST(func) \ - DEFINE_IDTENTRY_RAW(func) +static __always_inline void __##func(struct pt_regs *regs); \ + \ +__visible noinstr void func(struct pt_regs *regs) \ +{ \ + idtentry_validate_ist(regs); \ + __##func(regs); \ +} \ + \ +static __always_inline void __##func(struct pt_regs *regs) /** * DEFINE_IDTENTRY_NOIST - Emit code for NOIST entry points which