On Tue, Sep 08, 2026, Tharit Tangkijwanichakul wrote:
> kvm_is_valid_sregs() validates the incoming CR0, CR4, and efer values but
> never checks CR8.
>
> When userspace passes a CR8 value with any of the
> reserved bits [63:4] set, __set_sregs_common() forwards it to
> kvm_set_cr8(), which rejects the reserved bits and returns early. That
> return value is not checked, so the ioctl reports success while the
> requested value is silently dropped. A subsequent KVM_GET_SREGS then
> returns a CR8 different from the one userspace believed it had written.
>
> Factor the reserved-bit check out into kvm_is_valid_cr8() and use it both
> in kvm_set_cr8() and in kvm_is_valid_sregs().
>
> Fixes: 2f5bb3fe5835 ("KVM: x86: Move the bulk of register specific code from
> x86.c to regs.c")
Heh, this goes back much further than just moving code around, all the way to:
6aa8b732ca01 ("[PATCH] kvm: userspace interface")
which did this in kvm_vcpu_ioctl_set_sregs():
6aa8b732ca01 (Avi Kivity 2006-12-10 02:21:36 -0800 2109)
vcpu->cr8 = sregs->cr8;
I suppose one could argue that:
Fixes: 7017fc3d1a12 ("KVM: Define and use cr8 access functions")
is more appropriate, since this specific behavior was introduced then. I'll
probably just shove both in there and massage the changelog to explain the
history.
No need for a v2, I'll fixup when applying. Thanks!