mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-27 04:54:41 +08:00
KVM: x86: Fix KVM_CAP_SYNC_REGS's sync_regs() TOCTOU issues
In a spirit of using a sledgehammer to crack a nut, make sync_regs() feed
__set_sregs() and kvm_vcpu_ioctl_x86_set_vcpu_events() with kernel's own
copy of data.
Both __set_sregs() and kvm_vcpu_ioctl_x86_set_vcpu_events() assume they
have exclusive rights to structs they operate on. While this is true when
coming from an ioctl handler (caller makes a local copy of user's data),
sync_regs() breaks this contract; a pointer to a user-modifiable memory
(vcpu->run->s.regs) is provided. This can lead to a situation when incoming
data is checked and/or sanitized only to be re-set by a user thread running
in parallel.
Signed-off-by: Michal Luczaj <mhal@rbox.co>
Fixes: 01643c51bf
("KVM: x86: KVM_CAP_SYNC_REGS")
Link: https://lore.kernel.org/r/20230728001606.2275586-2-mhal@rbox.co
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
parent
fdf0eaf114
commit
0d033770d4
@ -11777,15 +11777,22 @@ static int sync_regs(struct kvm_vcpu *vcpu)
|
||||
__set_regs(vcpu, &vcpu->run->s.regs.regs);
|
||||
vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_REGS;
|
||||
}
|
||||
|
||||
if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_SREGS) {
|
||||
if (__set_sregs(vcpu, &vcpu->run->s.regs.sregs))
|
||||
struct kvm_sregs sregs = vcpu->run->s.regs.sregs;
|
||||
|
||||
if (__set_sregs(vcpu, &sregs))
|
||||
return -EINVAL;
|
||||
|
||||
vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_SREGS;
|
||||
}
|
||||
|
||||
if (vcpu->run->kvm_dirty_regs & KVM_SYNC_X86_EVENTS) {
|
||||
if (kvm_vcpu_ioctl_x86_set_vcpu_events(
|
||||
vcpu, &vcpu->run->s.regs.events))
|
||||
struct kvm_vcpu_events events = vcpu->run->s.regs.events;
|
||||
|
||||
if (kvm_vcpu_ioctl_x86_set_vcpu_events(vcpu, &events))
|
||||
return -EINVAL;
|
||||
|
||||
vcpu->run->kvm_dirty_regs &= ~KVM_SYNC_X86_EVENTS;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user