1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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;
}
|