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