diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2008-04-19 15:33:56 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2008-04-27 11:21:46 -0400 |
commit | 66c0b394f08fd89236515c1c84485ea712a157be (patch) | |
tree | bb6e9e5c0d6297f93617d222ea11f3c134ccab99 | |
parent | 960b3991698872f68f09d51f4c2794ad484fe1fd (diff) |
KVM: kill file->f_count abuse in kvm
Use kvm own refcounting instead of playing with ->filp->f_count.
That will allow to get rid of a lot of crap in anon_inode_getfd() and
kill a race in kvm_dev_ioctl_create_vm() (file might have been closed
immediately by another thread, so ->filp might point to already freed
struct file when we get around to setting it).
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Avi Kivity <avi@qumranet.com>
-rw-r--r-- | include/linux/kvm_host.h | 1 | ||||
-rw-r--r-- | virt/kvm/kvm_main.c | 12 |
2 files changed, 6 insertions, 7 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 4e16682ee8bb..398978972b7a 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -110,7 +110,6 @@ struct kvm { | |||
110 | KVM_PRIVATE_MEM_SLOTS]; | 110 | KVM_PRIVATE_MEM_SLOTS]; |
111 | struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; | 111 | struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; |
112 | struct list_head vm_list; | 112 | struct list_head vm_list; |
113 | struct file *filp; | ||
114 | struct kvm_io_bus mmio_bus; | 113 | struct kvm_io_bus mmio_bus; |
115 | struct kvm_io_bus pio_bus; | 114 | struct kvm_io_bus pio_bus; |
116 | struct kvm_vm_stat stat; | 115 | struct kvm_vm_stat stat; |
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d3cb4cc0a5aa..c82cf15730a1 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -818,7 +818,7 @@ static int kvm_vcpu_release(struct inode *inode, struct file *filp) | |||
818 | { | 818 | { |
819 | struct kvm_vcpu *vcpu = filp->private_data; | 819 | struct kvm_vcpu *vcpu = filp->private_data; |
820 | 820 | ||
821 | fput(vcpu->kvm->filp); | 821 | kvm_put_kvm(vcpu->kvm); |
822 | return 0; | 822 | return 0; |
823 | } | 823 | } |
824 | 824 | ||
@@ -840,9 +840,10 @@ static int create_vcpu_fd(struct kvm_vcpu *vcpu) | |||
840 | 840 | ||
841 | r = anon_inode_getfd(&fd, &inode, &file, | 841 | r = anon_inode_getfd(&fd, &inode, &file, |
842 | "kvm-vcpu", &kvm_vcpu_fops, vcpu); | 842 | "kvm-vcpu", &kvm_vcpu_fops, vcpu); |
843 | if (r) | 843 | if (r) { |
844 | kvm_put_kvm(vcpu->kvm); | ||
844 | return r; | 845 | return r; |
845 | atomic_inc(&vcpu->kvm->filp->f_count); | 846 | } |
846 | return fd; | 847 | return fd; |
847 | } | 848 | } |
848 | 849 | ||
@@ -877,6 +878,7 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, int n) | |||
877 | mutex_unlock(&kvm->lock); | 878 | mutex_unlock(&kvm->lock); |
878 | 879 | ||
879 | /* Now it's all set up, let userspace reach it */ | 880 | /* Now it's all set up, let userspace reach it */ |
881 | kvm_get_kvm(kvm); | ||
880 | r = create_vcpu_fd(vcpu); | 882 | r = create_vcpu_fd(vcpu); |
881 | if (r < 0) | 883 | if (r < 0) |
882 | goto unlink; | 884 | goto unlink; |
@@ -1176,12 +1178,10 @@ static int kvm_dev_ioctl_create_vm(void) | |||
1176 | return PTR_ERR(kvm); | 1178 | return PTR_ERR(kvm); |
1177 | r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm); | 1179 | r = anon_inode_getfd(&fd, &inode, &file, "kvm-vm", &kvm_vm_fops, kvm); |
1178 | if (r) { | 1180 | if (r) { |
1179 | kvm_destroy_vm(kvm); | 1181 | kvm_put_kvm(kvm); |
1180 | return r; | 1182 | return r; |
1181 | } | 1183 | } |
1182 | 1184 | ||
1183 | kvm->filp = file; | ||
1184 | |||
1185 | return fd; | 1185 | return fd; |
1186 | } | 1186 | } |
1187 | 1187 | ||