From: Carlos López 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 the bug by treating any non-zero return from set_dr() as a reason to inject #GP. Note, the manual checks on DR6 and DR7 are flawed, as they incorrectly prioritize the #GP over a DR7.GD=1 #DB (the General Detect #DB has priority on both Intel and AMD). Note #2, relying on ->set_dr() to detect #GP is also flawed as all exceptions have higher priority than the instruction intercept on SVM, i.e. the manual checks need to be extended to DR4 and DR5 (after the priority bug is fixed). Fixes: 996ff5429e98 ("KVM: x86: move kvm_inject_gp up from kvm_set_dr to callers") Signed-off-by: Carlos López Link: https://patch.msgid.link/20260601133320.91479-2-clopez@suse.de [sean: drop explicit "!= 0", massage changelog] Signed-off-by: Sean Christopherson --- 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 b566ab5c7515..75cd8b6136aa 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)) return emulate_gp(ctxt, 0); /* Disable writeback. */ -- 2.54.0.1136.gdb2ca164c4-goog