|
@@ -1869,6 +1869,15 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
|
|
struct kvm *kvm = filp->private_data;
|
|
|
void __user *argp = (void __user *)arg;
|
|
|
int r = -EINVAL;
|
|
|
+ /*
|
|
|
+ * This union makes it completely explicit to gcc-3.x
|
|
|
+ * that these two variables' stack usage should be
|
|
|
+ * combined, not added together.
|
|
|
+ */
|
|
|
+ union {
|
|
|
+ struct kvm_pit_state ps;
|
|
|
+ struct kvm_memory_alias alias;
|
|
|
+ } u;
|
|
|
|
|
|
switch (ioctl) {
|
|
|
case KVM_SET_TSS_ADDR:
|
|
@@ -1900,17 +1909,14 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
|
|
case KVM_GET_NR_MMU_PAGES:
|
|
|
r = kvm_vm_ioctl_get_nr_mmu_pages(kvm);
|
|
|
break;
|
|
|
- case KVM_SET_MEMORY_ALIAS: {
|
|
|
- struct kvm_memory_alias alias;
|
|
|
-
|
|
|
+ case KVM_SET_MEMORY_ALIAS:
|
|
|
r = -EFAULT;
|
|
|
- if (copy_from_user(&alias, argp, sizeof alias))
|
|
|
+ if (copy_from_user(&u.alias, argp, sizeof(struct kvm_memory_alias)))
|
|
|
goto out;
|
|
|
- r = kvm_vm_ioctl_set_memory_alias(kvm, &alias);
|
|
|
+ r = kvm_vm_ioctl_set_memory_alias(kvm, &u.alias);
|
|
|
if (r)
|
|
|
goto out;
|
|
|
break;
|
|
|
- }
|
|
|
case KVM_CREATE_IRQCHIP:
|
|
|
r = -ENOMEM;
|
|
|
kvm->arch.vpic = kvm_create_pic(kvm);
|
|
@@ -1952,37 +1958,51 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
|
|
}
|
|
|
case KVM_GET_IRQCHIP: {
|
|
|
/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
|
|
|
- struct kvm_irqchip chip;
|
|
|
+ struct kvm_irqchip *chip = kmalloc(sizeof(*chip), GFP_KERNEL);
|
|
|
|
|
|
- r = -EFAULT;
|
|
|
- if (copy_from_user(&chip, argp, sizeof chip))
|
|
|
+ r = -ENOMEM;
|
|
|
+ if (!chip)
|
|
|
goto out;
|
|
|
+ r = -EFAULT;
|
|
|
+ if (copy_from_user(chip, argp, sizeof *chip))
|
|
|
+ goto get_irqchip_out;
|
|
|
r = -ENXIO;
|
|
|
if (!irqchip_in_kernel(kvm))
|
|
|
- goto out;
|
|
|
- r = kvm_vm_ioctl_get_irqchip(kvm, &chip);
|
|
|
+ goto get_irqchip_out;
|
|
|
+ r = kvm_vm_ioctl_get_irqchip(kvm, chip);
|
|
|
if (r)
|
|
|
- goto out;
|
|
|
+ goto get_irqchip_out;
|
|
|
r = -EFAULT;
|
|
|
- if (copy_to_user(argp, &chip, sizeof chip))
|
|
|
- goto out;
|
|
|
+ if (copy_to_user(argp, chip, sizeof *chip))
|
|
|
+ goto get_irqchip_out;
|
|
|
r = 0;
|
|
|
+ get_irqchip_out:
|
|
|
+ kfree(chip);
|
|
|
+ if (r)
|
|
|
+ goto out;
|
|
|
break;
|
|
|
}
|
|
|
case KVM_SET_IRQCHIP: {
|
|
|
/* 0: PIC master, 1: PIC slave, 2: IOAPIC */
|
|
|
- struct kvm_irqchip chip;
|
|
|
+ struct kvm_irqchip *chip = kmalloc(sizeof(*chip), GFP_KERNEL);
|
|
|
|
|
|
- r = -EFAULT;
|
|
|
- if (copy_from_user(&chip, argp, sizeof chip))
|
|
|
+ r = -ENOMEM;
|
|
|
+ if (!chip)
|
|
|
goto out;
|
|
|
+ r = -EFAULT;
|
|
|
+ if (copy_from_user(chip, argp, sizeof *chip))
|
|
|
+ goto set_irqchip_out;
|
|
|
r = -ENXIO;
|
|
|
if (!irqchip_in_kernel(kvm))
|
|
|
- goto out;
|
|
|
- r = kvm_vm_ioctl_set_irqchip(kvm, &chip);
|
|
|
+ goto set_irqchip_out;
|
|
|
+ r = kvm_vm_ioctl_set_irqchip(kvm, chip);
|
|
|
if (r)
|
|
|
- goto out;
|
|
|
+ goto set_irqchip_out;
|
|
|
r = 0;
|
|
|
+ set_irqchip_out:
|
|
|
+ kfree(chip);
|
|
|
+ if (r)
|
|
|
+ goto out;
|
|
|
break;
|
|
|
}
|
|
|
case KVM_ASSIGN_PCI_DEVICE: {
|
|
@@ -2008,31 +2028,29 @@ long kvm_arch_vm_ioctl(struct file *filp,
|
|
|
break;
|
|
|
}
|
|
|
case KVM_GET_PIT: {
|
|
|
- struct kvm_pit_state ps;
|
|
|
r = -EFAULT;
|
|
|
- if (copy_from_user(&ps, argp, sizeof ps))
|
|
|
+ if (copy_from_user(&u.ps, argp, sizeof(struct kvm_pit_state)))
|
|
|
goto out;
|
|
|
r = -ENXIO;
|
|
|
if (!kvm->arch.vpit)
|
|
|
goto out;
|
|
|
- r = kvm_vm_ioctl_get_pit(kvm, &ps);
|
|
|
+ r = kvm_vm_ioctl_get_pit(kvm, &u.ps);
|
|
|
if (r)
|
|
|
goto out;
|
|
|
r = -EFAULT;
|
|
|
- if (copy_to_user(argp, &ps, sizeof ps))
|
|
|
+ if (copy_to_user(argp, &u.ps, sizeof(struct kvm_pit_state)))
|
|
|
goto out;
|
|
|
r = 0;
|
|
|
break;
|
|
|
}
|
|
|
case KVM_SET_PIT: {
|
|
|
- struct kvm_pit_state ps;
|
|
|
r = -EFAULT;
|
|
|
- if (copy_from_user(&ps, argp, sizeof ps))
|
|
|
+ if (copy_from_user(&u.ps, argp, sizeof u.ps))
|
|
|
goto out;
|
|
|
r = -ENXIO;
|
|
|
if (!kvm->arch.vpit)
|
|
|
goto out;
|
|
|
- r = kvm_vm_ioctl_set_pit(kvm, &ps);
|
|
|
+ r = kvm_vm_ioctl_set_pit(kvm, &u.ps);
|
|
|
if (r)
|
|
|
goto out;
|
|
|
r = 0;
|