Joerg Roedel
2021-Oct-21 08:08 UTC
[PATCH 0/2] x86/sev: Two fixes for SEV-ES VC stack handling
From: Joerg Roedel <jroedel at suse.de> Hi, here are two fixes for recently discovered issues in the handling of VC handler stack. Please review. Thanks, Joerg Joerg Roedel (2): x86/sev: Fix stack type check in vc_switch_off_ist() x86/sev: Allow #VC exceptions on the VC2 stack arch/x86/kernel/sev.c | 21 +++++++++++++++++---- arch/x86/kernel/traps.c | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) base-commit: 519d81956ee277b4419c723adfb154603c2565ba -- 2.33.1
Joerg Roedel
2021-Oct-21 08:08 UTC
[PATCH 1/2] x86/sev: Fix stack type check in vc_switch_off_ist()
From: Joerg Roedel <jroedel at suse.de> The value of STACK_TYPE_EXCEPTION_LAST points to the last _valid_ exception stack. Reflect that in the check done in the vc_switch_off_ist() function. Reported-by: Tom Lendacky <thomas.lendacky at amd.com> Fixes: a13644f3a53de ("x86/entry/64: Add entry code for #VC handler") Signed-off-by: Joerg Roedel <jroedel at suse.de> --- arch/x86/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index a58800973aed..f516f2b4797e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -709,7 +709,7 @@ asmlinkage __visible noinstr struct pt_regs *vc_switch_off_ist(struct pt_regs *r stack = (unsigned long *)sp; if (!get_stack_info_noinstr(stack, current, &info) || info.type == STACK_TYPE_ENTRY || - info.type >= STACK_TYPE_EXCEPTION_LAST) + info.type > STACK_TYPE_EXCEPTION_LAST) sp = __this_cpu_ist_top_va(VC2); sync: -- 2.33.1
Joerg Roedel
2021-Oct-21 08:08 UTC
[PATCH 2/2] x86/sev: Allow #VC exceptions on the VC2 stack
From: Joerg Roedel <jroedel at suse.de> When code running on the VC2 stack causes a nested VC exception, the handler will not handle it as expected but goes again into the error path. The result is that the panic() call happening when the VC exception was raised in an invalid context is called recursively. Fix this by checking the interrupted stack too and only call panic if it is not the VC2 stack. Reported-by: Xinyang Ge <xing at microsoft.com> Fixes: 0786138c78e79 ("x86/sev-es: Add a Runtime #VC Exception Handler") Signed-off-by: Joerg Roedel <jroedel at suse.de> --- arch/x86/kernel/sev.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c index a6895e440bc3..f39165b5fa34 100644 --- a/arch/x86/kernel/sev.c +++ b/arch/x86/kernel/sev.c @@ -1319,13 +1319,26 @@ static __always_inline void vc_forward_exception(struct es_em_ctxt *ctxt) } } -static __always_inline bool on_vc_fallback_stack(struct pt_regs *regs) +static __always_inline bool is_vc2_stack(unsigned long sp) { - unsigned long sp = (unsigned long)regs; - return (sp >= __this_cpu_ist_bottom_va(VC2) && sp < __this_cpu_ist_top_va(VC2)); } +static __always_inline bool vc_from_invalid_context(struct pt_regs *regs) +{ + unsigned long sp, prev_sp; + + sp = (unsigned long)regs; + prev_sp = regs->sp; + + /* + * If the code was already executing on the VC2 stack when the #VC + * happened, let it proceed to the normal handling routine. This way the + * code executing on the VC2 stack can cause get #VC exceptions handled. + */ + return is_vc2_stack(sp) && !is_vc2_stack(prev_sp); +} + static bool vc_raw_handle_exception(struct pt_regs *regs, unsigned long error_code) { struct ghcb_state state; @@ -1406,7 +1419,7 @@ DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication) * But keep this here in case the noinstr annotations are violated due * to bug elsewhere. */ - if (unlikely(on_vc_fallback_stack(regs))) { + if (unlikely(vc_from_invalid_context(regs))) { instrumentation_begin(); panic("Can't handle #VC exception from unsupported context\n"); instrumentation_end(); -- 2.33.1