diff --git a/drivers/misc/vmw_vmci/vmci_host.c b/drivers/misc/vmw_vmci/vmci_host.c index b64944367ac5..fd41bad0a73d 100644 --- a/drivers/misc/vmw_vmci/vmci_host.c +++ b/drivers/misc/vmw_vmci/vmci_host.c @@ -293,6 +293,8 @@ static int vmci_host_get_version(struct vmci_host_dev *vmci_host_dev, #define vmci_ioctl_err(fmt, ...) \ pr_devel("%s: " fmt, ioctl_name, ##__VA_ARGS__) +static DEFINE_MUTEX(init_rec_mutex); + static int vmci_host_do_init_context(struct vmci_host_dev *vmci_host_dev, const char *ioctl_name, void __user *uptr) @@ -306,6 +308,7 @@ static int vmci_host_do_init_context(struct vmci_host_dev *vmci_host_dev, return -EFAULT; } + mutex_lock(&init_rec_mutex); mutex_lock(&vmci_host_dev->lock); if (vmci_host_dev->ct_type != VMCIOBJ_NOT_SET) { @@ -354,6 +357,7 @@ static int vmci_host_do_init_context(struct vmci_host_dev *vmci_host_dev, out: mutex_unlock(&vmci_host_dev->lock); + mutex_unlock(&init_rec_mutex); return retval; } @@ -426,8 +430,11 @@ static int vmci_host_do_receive_datagram(struct vmci_host_dev *vmci_host_dev, return -EINVAL; } - if (copy_from_user(&recv_info, uptr, sizeof(recv_info))) - return -EFAULT; + mutex_lock(&init_rec_mutex); + if (copy_from_user(&recv_info, uptr, sizeof(recv_info))) { + retval = -EFAULT; + goto out; + } size = recv_info.len; recv_info.result = vmci_ctx_dequeue_datagram(vmci_host_dev->context, @@ -437,11 +444,17 @@ static int vmci_host_do_receive_datagram(struct vmci_host_dev *vmci_host_dev, void __user *ubuf = (void __user *)(uintptr_t)recv_info.addr; retval = copy_to_user(ubuf, dg, VMCI_DG_SIZE(dg)); kfree(dg); - if (retval != 0) - return -EFAULT; + if (retval != 0) { + retval = -EFAULT; + goto out; + } } - return copy_to_user(uptr, &recv_info, sizeof(recv_info)) ? -EFAULT : 0; + retval = copy_to_user(uptr, &recv_info, sizeof(recv_info)) ? -EFAULT : 0; + +out: + mutex_unlock(&init_rec_mutex); + return retval; } static int vmci_host_do_alloc_queuepair(struct vmci_host_dev *vmci_host_dev,