From: ZhaoQiang <zhao.qiang11@xxxxxxxxxx> When processing the ioctl request for creating a device in the kvm_vm_ioctl()function,the branch did not reclaim the successfully created device,which caused memory leak. Signed-off-by: ZhaoQiang <zhao.qiang11@xxxxxxxxxx> Signed-off-by: Yi Wang <wang.yi59@xxxxxxxxxx> --- virt/kvm/kvm_main.c | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 72c4e6b39389..f4fbc935faea 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -52,6 +52,7 @@ #include <linux/lockdep.h> #include <linux/kthread.h> #include <linux/suspend.h> +#include <linux/syscalls.h> #include <asm/processor.h> #include <asm/ioctl.h> @@ -4092,6 +4093,40 @@ static int kvm_ioctl_create_device(struct kvm *kvm, return 0; } +static int kvm_ioctl_destroy_device(struct kvm *kvm, + struct kvm_create_device *cd) +{ + struct kvm_device_ops *ops = NULL; + struct kvm_device *dev; + struct file *file; + int type; + + if (cd->type >= ARRAY_SIZE(kvm_device_ops_table)) + return -ENODEV; + + type = array_index_nospec(cd->type, ARRAY_SIZE(kvm_device_ops_table)); + ops = kvm_device_ops_table[type]; + if (ops == NULL) + return -ENODEV; + + file = fget(cd->fd); + if (!file) + return -ENODEV; + + dev = file->private_data; + if (!dev) + return -ENODEV; + + kvm_put_kvm(kvm); + mutex_lock(&kvm->lock); + list_del(&device->vm_node); + mutex_unlock(&kvm->lock); + ops->destroy(dev); + ksys_close(cd->fd); + + return 0; +} + static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) { switch (arg) { @@ -4448,8 +4483,10 @@ static long kvm_vm_ioctl(struct file *filp, goto out; r = -EFAULT; - if (copy_to_user(argp, &cd, sizeof(cd))) + if (copy_to_user(argp, &cd, sizeof(cd))) { + kvm_ioctl_destroy_device(kvm, &cd); goto out; + } r = 0; break; -- 2.27.0