mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
x86/pv: Correct the auditing of guest breakpoint addresses
The use of access_ok() is buggy, because it permits access to the compat translation area. 64bit PV guests don't use the XLAT area, but on AMD hardware, the DBEXT feature allows a breakpoint to match up to a 4G aligned region, allowing the breakpoint to reach outside of the XLAT area. Prior to c/scda16c1bb2("x86: mirror compat argument translation area for 32-bit PV"), the live GDT was within 4G of the XLAT area. All together, this allowed a malicious 64bit PV guest on AMD hardware to place a breakpoint over the live GDT, and trigger a #DB livelock (CVE-2015-8104). Introduce breakpoint_addr_ok() and explain why __addr_ok() happens to be an appropriate check in this case. For Xen 4.14 and later, this is a latent bug because the XLAT area has moved to be on its own with nothing interesting adjacent. For Xen 4.13 and older on AMD hardware, this fixes a PV-trigger-able DoS. This is part of XSA-444 / CVE-2023-34328. Fixes:65e3554908("x86/PV: support data breakpoint extension registers") Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Roger Pau Monné <roger.pau@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> (cherry picked from commitdc9d9aa62d)
This commit is contained in:
1 parent
1f0d217f05
commit
4a4daf6bdd
2 files changed
+21
-1
No files matched your search
@@ -68,7 +68,7 @@ long set_debugreg(struct vcpu *v, unsigned int reg, unsigned long value)
|
||||
switch ( reg )
|
||||
{
|
||||
case 0 ... 3:
|
||||
if ( !access_ok(value, sizeof(long)) )
|
||||
if ( !breakpoint_addr_ok(value) )
|
||||
return -EPERM;
|
||||
|
||||
v->arch.dr[reg] = value;
|
||||
|
||||
@@ -77,6 +77,26 @@
|
||||
asm volatile ( "mov %%db" #reg ",%0" : "=r" (__val) ); \
|
||||
__val; \
|
||||
})
|
||||
|
||||
/*
|
||||
* Architecturally, %dr{0..3} can have any arbitrary value. However, Xen
|
||||
* can't allow the guest to breakpoint the Xen address range, so we limit the
|
||||
* guest to the lower canonical half, or above the Xen range in the higher
|
||||
* canonical half.
|
||||
*
|
||||
* Breakpoint lengths are specified to mask the low order address bits,
|
||||
* meaning all breakpoints are naturally aligned. With %dr7, the widest
|
||||
* breakpoint is 8 bytes. With DBEXT, the widest breakpoint is 4G. Both of
|
||||
* the Xen boundaries have >4G alignment.
|
||||
*
|
||||
* In principle we should account for HYPERVISOR_COMPAT_VIRT_START(d), but
|
||||
* 64bit Xen has never enforced this for compat guests, and there's no problem
|
||||
* (to Xen) if the guest breakpoints it's alias of the M2P. Skipping this
|
||||
* aspect simplifies the logic, and causes us not to reject a migrating guest
|
||||
* which operated fine on prior versions of Xen.
|
||||
*/
|
||||
#define breakpoint_addr_ok(a) __addr_ok(a)
|
||||
|
||||
long set_debugreg(struct vcpu *, unsigned int reg, unsigned long value);
|
||||
void activate_debugregs(const struct vcpu *);
|
||||
|
||||
|
||||