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

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

Merge "usb: gadget: f_mtp: Securing vfs_write and unbind with less mutex"

parents 09657429 5bed3e93
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -150,6 +150,7 @@ struct mtp_dev {
	} perf[MAX_ITERATION];
	unsigned int dbg_read_index;
	unsigned int dbg_write_index;
	struct mutex  read_mutex;
};

static void *_mtp_ipc_log;
@@ -609,12 +610,11 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
	mtp_log("(%zu) state:%d\n", count, dev->state);

	/* we will block until we're online */
	mtp_log("waiting for online state\n");
	ret = wait_event_interruptible(dev->read_wq,
		dev->state != STATE_OFFLINE);
	if (ret < 0) {
		r = ret;
		goto done;
		goto wait_err;
	}

	len = ALIGN(count, dev->ep_out->maxpacket);
@@ -649,6 +649,11 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
	dev->state = STATE_BUSY;
	spin_unlock_irq(&dev->lock);

	mutex_lock(&dev->read_mutex);
	if (dev->state == STATE_OFFLINE) {
		r = -EIO;
		goto done;
	}
requeue_req:
	/* queue a request */
	req = dev->rx_req[0];
@@ -693,6 +698,8 @@ static ssize_t mtp_read(struct file *fp, char __user *buf,
		r = -EIO;

done:
	mutex_unlock(&dev->read_mutex);
wait_err:
	spin_lock_irq(&dev->lock);
	if (dev->state == STATE_CANCELED)
		r = -ECANCELED;
@@ -936,7 +943,7 @@ static void receive_file_work(struct work_struct *data)
	if (!IS_ALIGNED(count, dev->ep_out->maxpacket))
		mtp_log("- count(%lld) not multiple of mtu(%d)\n",
						count, dev->ep_out->maxpacket);

	mutex_lock(&dev->read_mutex);
	while (count > 0 || write_req) {
		if (count > 0) {
			/* queue a request */
@@ -1019,7 +1026,7 @@ static void receive_file_work(struct work_struct *data)
			read_req = NULL;
		}
	}

	mutex_unlock(&dev->read_mutex);
	mtp_log("returning %d\n", r);
	/* write the result */
	dev->xfer_result = r;
@@ -1469,6 +1476,8 @@ mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
	fi_mtp = container_of(f->fi, struct mtp_instance, func_inst);
	mtp_string_defs[INTERFACE_STRING_INDEX].id = 0;
	mtp_log("dev: %pK\n", dev);

	mutex_lock(&dev->read_mutex);
	while ((req = mtp_req_get(dev, &dev->tx_idle)))
		mtp_request_free(req, dev->ep_in);
	for (i = 0; i < RX_REQ_MAX; i++)
@@ -1479,6 +1488,8 @@ mtp_function_unbind(struct usb_configuration *c, struct usb_function *f)
	dev->state = STATE_OFFLINE;
	dev->cdev = NULL;
	spin_unlock_irq(&dev->lock);
	mutex_unlock(&dev->read_mutex);

	kfree(f->os_desc_table);
	f->os_desc_n = 0;
	fi_mtp->func_inst.f = NULL;
@@ -1819,6 +1830,8 @@ struct usb_function_instance *alloc_inst_mtp_ptp(bool mtp_config)
	usb_os_desc_prepare_interf_dir(&fi_mtp->func_inst.group, 1,
					descs, names, THIS_MODULE);

	mutex_init(&fi_mtp->dev->read_mutex);

	return  &fi_mtp->func_inst;
}
EXPORT_SYMBOL_GPL(alloc_inst_mtp_ptp);