diff options
Diffstat (limited to 'system/xen/xsa/xsa260-4.patch')
-rw-r--r-- | system/xen/xsa/xsa260-4.patch | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/system/xen/xsa/xsa260-4.patch b/system/xen/xsa/xsa260-4.patch new file mode 100644 index 0000000000..c2fa02d6e1 --- /dev/null +++ b/system/xen/xsa/xsa260-4.patch @@ -0,0 +1,72 @@ +From: Andrew Cooper <andrew.cooper3@citrix.com> +Subject: x86/traps: Fix handling of #DB exceptions in hypervisor context + +The WARN_ON() can be triggered by guest activities, and emits a full stack +trace without rate limiting. Swap it out for a ratelimited printk with just +enough information to work out what is going on. + +Not all #DB exceptions are traps, so blindly continuing is not a safe action +to take. We don't let PV guests select these settings in the real %dr7 to +begin with, but for added safety against unexpected situations, detect the +fault cases and crash in an obvious manner. + +This is part of XSA-260 / CVE-2018-8897. + +Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> +Reviewed-by: Jan Beulich <jbeulich@suse.com> + +--- a/xen/arch/x86/traps.c ++++ b/xen/arch/x86/traps.c +@@ -1809,16 +1809,44 @@ void do_debug(struct cpu_user_regs *regs + regs->eflags &= ~X86_EFLAGS_TF; + } + } +- else ++ ++ /* ++ * Check for fault conditions. General Detect, and instruction ++ * breakpoints are faults rather than traps, at which point attempting ++ * to ignore and continue will result in a livelock. ++ */ ++ if ( dr6 & DR_GENERAL_DETECT ) ++ { ++ printk(XENLOG_ERR "Hit General Detect in Xen context\n"); ++ fatal_trap(regs, 0); ++ } ++ ++ if ( dr6 & (DR_TRAP3 | DR_TRAP2 | DR_TRAP1 | DR_TRAP0) ) + { +- /* +- * We ignore watchpoints when they trigger within Xen. This may +- * happen when a buffer is passed to us which previously had a +- * watchpoint set on it. No need to bump EIP; the only faulting +- * trap is an instruction breakpoint, which can't happen to us. +- */ +- WARN_ON(!search_exception_table(regs)); ++ unsigned int bp, dr7 = read_debugreg(7) >> DR_CONTROL_SHIFT; ++ ++ for ( bp = 0; bp < 4; ++bp ) ++ { ++ if ( (dr6 & (1u << bp)) && /* Breakpoint triggered? */ ++ ((dr7 & (3u << (bp * DR_CONTROL_SIZE))) == 0) /* Insn? */ ) ++ { ++ printk(XENLOG_ERR ++ "Hit instruction breakpoint in Xen context\n"); ++ fatal_trap(regs, 0); ++ } ++ } + } ++ ++ /* ++ * Whatever caused this #DB should be a trap. Note it and continue. ++ * Guests can trigger this in certain corner cases, so ensure the ++ * message is ratelimited. ++ */ ++ gprintk(XENLOG_WARNING, ++ "Hit #DB in Xen context: %04x:%p [%ps], stk %04x:%p, dr6 %lx\n", ++ regs->cs, _p(regs->rip), _p(regs->rip), ++ regs->ss, _p(regs->rsp), dr6); ++ + goto out; + } + |