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

Commit 31933d57 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "qdss_bridge: fix use-after-free is on cdev_put"

parents a466e5ee fca555a1
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
static struct class *mhi_class;
static enum mhi_dev_state dev_state = INIT_STATUS;
static enum mhi_ch curr_chan;
static struct qdss_bridge_drvdata *bridge_drvdata;

static const char * const str_mhi_curr_chan[] = {
		[QDSS]			= "QDSS",
@@ -767,9 +768,7 @@ static int mhi_uci_open(struct inode *inode, struct file *filp)
{
	int ret = -EIO;
	struct qdss_mhi_buf_tbl_t *buf_itr, *tmp;
	struct qdss_bridge_drvdata *drvdata = container_of(inode->i_cdev,
					struct qdss_bridge_drvdata,
					cdev);
	struct qdss_bridge_drvdata *drvdata = bridge_drvdata;

	spin_lock_bh(&drvdata->lock);
	if (drvdata->opened) {
@@ -851,9 +850,9 @@ static void qdss_mhi_remove(struct mhi_device *mhi_dev)
	} else
		spin_unlock_bh(&drvdata->lock);

	device_destroy(mhi_class, drvdata->cdev.dev);
	cdev_del(&drvdata->cdev);
	unregister_chrdev_region(drvdata->cdev.dev, 1);
	device_destroy(mhi_class, drvdata->cdev->dev);
	unregister_chrdev_region(drvdata->cdev->dev, 1);
	cdev_del(drvdata->cdev);
}

int qdss_mhi_init(struct qdss_bridge_drvdata *drvdata)
@@ -919,23 +918,27 @@ static int qdss_mhi_probe(struct mhi_device *mhi_dev,
		ret = -ENOMEM;
		return ret;
	}
	drvdata->cdev = cdev_alloc();
	if (!drvdata->cdev) {
		ret = -ENOMEM;
		return ret;
	}

	ret = alloc_chrdev_region(&dev, baseminor, count, "mhi_qdss");
	if (ret < 0) {
		pr_err("alloc_chrdev_region failed %d\n", ret);
		return ret;
	}
	cdev_init(&drvdata->cdev, &mhidev_fops);

	drvdata->cdev.owner = THIS_MODULE;
	drvdata->cdev.ops = &mhidev_fops;
	drvdata->cdev->owner = THIS_MODULE;
	drvdata->cdev->ops = &mhidev_fops;

	ret = cdev_add(&drvdata->cdev, dev, 1);
	ret = cdev_add(drvdata->cdev, dev, 1);
	if (ret)
		goto exit_unreg_chrdev_region;

	drvdata->dev = device_create(mhi_class, NULL,
			       drvdata->cdev.dev, drvdata,
			       drvdata->cdev->dev, drvdata,
			       "mhi_qdss");
	if (IS_ERR(drvdata->dev)) {
		pr_err("class_device_create failed %d\n", ret);
@@ -955,14 +958,15 @@ static int qdss_mhi_probe(struct mhi_device *mhi_dev,
		goto exit_destroy_device;
	}
	queue_work(drvdata->mhi_wq, &drvdata->open_work);
	bridge_drvdata = drvdata;
	return 0;

exit_destroy_device:
	device_destroy(mhi_class, drvdata->cdev.dev);
	device_destroy(mhi_class, drvdata->cdev->dev);
exit_cdev_add:
	cdev_del(&drvdata->cdev);
	cdev_del(drvdata->cdev);
exit_unreg_chrdev_region:
	unregister_chrdev_region(drvdata->cdev.dev, 1);
	unregister_chrdev_region(drvdata->cdev->dev, 1);
	return ret;

}
+2 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _QDSS_BRIDGE_H
@@ -45,7 +45,7 @@ struct qdss_bridge_drvdata {
	enum mhi_transfer_mode mode;
	spinlock_t lock;
	struct device *dev;
	struct cdev cdev;
	struct cdev *cdev;
	struct mhi_device *mhi_dev;
	struct work_struct read_work;
	struct work_struct read_done_work;