[PATCH] KVM: x86: fix #GP check in em_dr_write()

From: Carlos López

Date: Mon Jun 01 2026 - 09:36:40 EST


When emulating a MOV to a debug register, em_dr_write() calls
@ctxt->ops->set_dr(), which is forwarded to emulator_set_dr() and
then kvm_set_dr(). The latter checks that the written value is valid,
otherwise returning an error, in which case the emulator is supposed to
inject a #GP fault into the guest.

Commit 996ff5429e98 ("KVM: x86: move kvm_inject_gp up from kvm_set_dr
to callers") changed the contract of kvm_set_dr() (and thus
emulator_set_dr()), returning 1 as an error instead of -1, but the
caller in em_dr_write() was never updated, checking only if the returned
value is negative. The end result is that em_dr_write() does not detect
the error, so an invalid write does not generate a #GP, but at the same
time the register value is not updated.

The practical impact is limited, as check_dr_write() already checks DR6
and DR7 manually. However, it misses DR4/DR5, which alias DR6/DR7 when
CR4.DE=0.

Fix this by treating any non-zero return from set_dr() as a reason to
inject #GP.

Fixes: 996ff5429e98 ("KVM: x86: move kvm_inject_gp up from kvm_set_dr to callers")
Signed-off-by: Carlos López <clopez@xxxxxxx>
---
arch/x86/kvm/emulate.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 585a8ceab220..de138ef92dc6 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -3299,7 +3299,7 @@ static int em_dr_write(struct x86_emulate_ctxt *ctxt)
val = ctxt->src.val & ~0U;

/* #UD condition is already handled. */
- if (ctxt->ops->set_dr(ctxt, ctxt->modrm_reg, val) < 0)
+ if (ctxt->ops->set_dr(ctxt, ctxt->modrm_reg, val) != 0)
return emulate_gp(ctxt, 0);

/* Disable writeback. */

base-commit: d1568b1332b6b3b36b222c2868fc102727c12a34
--
2.51.0