Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ade232c6 authored by Sujeev Dias's avatar Sujeev Dias Committed by Gerrit - the friendly Code Review server
Browse files

mhi: dev: uci: block file open until MHI remove is complete



Race condition exists between open and remove where after open
obtain the device node and MHI remove frees the same device. To
avoid this scenario, block file open from obtaining device node
while remove is executing.

CRs-Fixed: 2356376
Change-Id: I1aad5c7848b791a2e03ea0acac643b9a2bda3ba2
Signed-off-by: default avatarSujeev Dias <sdias@codeaurora.org>
parent 0eef6c41
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -441,11 +441,10 @@ static int mhi_uci_open(struct inode *inode, struct file *filp)
			break;
		}
	}
	mutex_unlock(&mhi_uci_drv.lock);

	/* could not find a minor node */
	if (ret)
		return ret;
		goto error_exit;

	mutex_lock(&uci_dev->mutex);
	if (!uci_dev->enabled) {
@@ -473,6 +472,7 @@ static int mhi_uci_open(struct inode *inode, struct file *filp)

	filp->private_data = uci_dev;
	mutex_unlock(&uci_dev->mutex);
	mutex_unlock(&mhi_uci_drv.lock);

	return 0;

@@ -487,6 +487,9 @@ static int mhi_uci_open(struct inode *inode, struct file *filp)
 error_open_chan:
	mutex_unlock(&uci_dev->mutex);

error_exit:
	mutex_unlock(&mhi_uci_drv.lock);

	return ret;
}

@@ -505,8 +508,11 @@ static void mhi_uci_remove(struct mhi_device *mhi_dev)

	MSG_LOG("Enter\n");

	/* disable the node */

	mutex_lock(&mhi_uci_drv.lock);
	mutex_lock(&uci_dev->mutex);

	/* disable the node */
	spin_lock_irq(&uci_dev->dl_chan.lock);
	spin_lock_irq(&uci_dev->ul_chan.lock);
	uci_dev->enabled = false;
@@ -518,9 +524,7 @@ static void mhi_uci_remove(struct mhi_device *mhi_dev)
	/* delete the node to prevent new opens */
	device_destroy(mhi_uci_drv.class, uci_dev->devt);
	uci_dev->dev = NULL;
	mutex_lock(&mhi_uci_drv.lock);
	list_del(&uci_dev->node);
	mutex_unlock(&mhi_uci_drv.lock);

	/* safe to free memory only if all file nodes are closed */
	if (!uci_dev->ref_count) {
@@ -528,11 +532,14 @@ static void mhi_uci_remove(struct mhi_device *mhi_dev)
		mutex_destroy(&uci_dev->mutex);
		clear_bit(MINOR(uci_dev->devt), uci_minors);
		kfree(uci_dev);
		mutex_unlock(&mhi_uci_drv.lock);
		return;
	}

	MSG_LOG("Exit\n");
	mutex_unlock(&uci_dev->mutex);
	mutex_unlock(&mhi_uci_drv.lock);

}

static int mhi_uci_probe(struct mhi_device *mhi_dev,