History

KVM: Protect device ops->create and list_add with kvm->lock

KVM devices were manipulating list data structures without any form of synchronization, and some implementations of the create operations also suffered from a lack of synchronization. Now when we've split the xics create operation into create and init, we can hold the kvm->lock mutex while calling the create operation and when manipulating the devices list. The error path in the generic code gets slightly ugly because we have to take the mutex again and delete the device from the list, but holding the mutex during anon_inode_getfd or releasing/locking the mutex in the common non-error path seemed wrong.

Christoffer Dall committed 10 years ago

Commit a28ebea1 parent 023e9fd5 files · +27 −17Browse files

Unified · Split

5 files
  1. arch/arm/kvm/arm.c +5 −1
  2. arch/powerpc/kvm/book3s_xics.c +0 −2
  3. include/linux/kvm_host.h +6 −0
  4. virt/kvm/arm/vgic/vgic-init.c +4 −13
  5. virt/kvm/kvm_main.c +12 −1
arch/arm/kvm/arm.c+5−1
@@ -1009,9 +1009,13 @@ long kvm_arch_vm_ioctl(struct file *filp, · 1008 unmodified lines
10091009
10101010 switch (ioctl) {
10111011 case KVM_CREATE_IRQCHIP: {
1012+ int ret;
10121013 if (!vgic_present)
10131014 return -ENXIO;
1014− return kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
1015+ mutex_lock(&kvm->lock);
1016+ ret = kvm_vgic_create(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
1017+ mutex_unlock(&kvm->lock);
1018+ return ret;
10151019 }
10161020 case KVM_ARM_SET_DEVICE_ADDR: {
10171021 struct kvm_arm_device_addr dev_addr;
arch/powerpc/kvm/book3s_xics.c+0−2
@@ -1329,12 +1329,10 @@ static int kvmppc_xics_create(struct kvm_device *dev, u32 type) · 1328 unmodified lines
13291329 xics->kvm = kvm;
13301330
13311331 /* Already there ? */
1332− mutex_lock(&kvm->lock);
13331332 if (kvm->arch.xics)
13341333 ret = -EEXIST;
13351334 else
13361335 kvm->arch.xics = xics;
1337− mutex_unlock(&kvm->lock);
13381336
13391337 if (ret) {
13401338 kfree(xics);
include/linux/kvm_host.h+6−0
@@ -1113,6 +1113,12 @@ struct kvm_device { · 1112 unmodified lines
11131113 /* create, destroy, and name are mandatory */
11141114 struct kvm_device_ops {
11151115 const char *name;
1116+
1117+ /*
1118+ * create is called holding kvm->lock and any operations not suitable
1119+ * to do while holding the lock should be deferred to init (see
1120+ * below).
1121+ */
11161122 int (*create)(struct kvm_device *dev, u32 type);
11171123
11181124 /*
virt/kvm/arm/vgic/vgic-init.c+4−13
@@ -73,12 +73,8 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) · 72 unmodified lines
7373 int i, vcpu_lock_idx = -1, ret;
7474 struct kvm_vcpu *vcpu;
7575
76− mutex_lock(&kvm->lock);
77−
78− if (irqchip_in_kernel(kvm)) {
79− ret = -EEXIST;
80− goto out;
81− }
76+ if (irqchip_in_kernel(kvm))
77+ return -EEXIST;
8278
8379 /*
8480 * This function is also called by the KVM_CREATE_IRQCHIP handler,
@@ -87,10 +83,8 @@ int kvm_vgic_create(struct kvm *kvm, u32 type) · 2 unmodified lines
8783 * the proper checks already.
8884 */
8985 if (type == KVM_DEV_TYPE_ARM_VGIC_V2 &&
90− !kvm_vgic_global_state.can_emulate_gicv2) {
91− ret = -ENODEV;
92− goto out;
93− }
86+ !kvm_vgic_global_state.can_emulate_gicv2)
87+ return -ENODEV;
9488
9589 /*
9690 * Any time a vcpu is run, vcpu_load is called which tries to grab the
@@ -138,9 +132,6 @@ out_unlock: · 41 unmodified lines
138132 vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
139133 mutex_unlock(&vcpu->mutex);
140134 }
141−
142−out:
143− mutex_unlock(&kvm->lock);
144135 return ret;
145136 }
146137
virt/kvm/kvm_main.c+12−1
@@ -696,6 +696,11 @@ static void kvm_destroy_devices(struct kvm *kvm) · 695 unmodified lines
696696 {
697697 struct kvm_device *dev, *tmp;
698698
699+ /*
700+ * We do not need to take the kvm->lock here, because nobody else
701+ * has a reference to the struct kvm at this point and therefore
702+ * cannot access the devices list anyhow.
703+ */
699704 list_for_each_entry_safe(dev, tmp, &kvm->devices, vm_node) {
700705 list_del(&dev->vm_node);
701706 dev->ops->destroy(dev);
@@ -2832,11 +2837,15 @@ static int kvm_ioctl_create_device(struct kvm *kvm, · 2130 unmodified lines
28322837 dev->ops = ops;
28332838 dev->kvm = kvm;
28342839
2840+ mutex_lock(&kvm->lock);
28352841 ret = ops->create(dev, cd->type);
28362842 if (ret < 0) {
2843+ mutex_unlock(&kvm->lock);
28372844 kfree(dev);
28382845 return ret;
28392846 }
2847+ list_add(&dev->vm_node, &kvm->devices);
2848+ mutex_unlock(&kvm->lock);
28402849
28412850 if (ops->init)
28422851 ops->init(dev);
@@ -2844,10 +2853,12 @@ static int kvm_ioctl_create_device(struct kvm *kvm, · 1 unmodified line
28442853 ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
28452854 if (ret < 0) {
28462855 ops->destroy(dev);
2856+ mutex_lock(&kvm->lock);
2857+ list_del(&dev->vm_node);
2858+ mutex_unlock(&kvm->lock);
28472859 return ret;
28482860 }
28492861
2850− list_add(&dev->vm_node, &kvm->devices);
28512862 kvm_get_kvm(kvm);
28522863 cd->fd = ret;
28532864 return 0;

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t