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

Commit 09b7d695 authored by Vijayavardhan Vennapusa's avatar Vijayavardhan Vennapusa Committed by Mayank Rana
Browse files

USB: f_qdss: Fix crash issue during connect_work



If it happens that usb_qdss_close() gets called before
completion of qdss_connect_work(), there is a chance that endless
request being accessed in connect_work(), which will be freed in
usb_qdss_close(). Fix that issue by having proper check for
endless request under spinlock protection.

Change-Id: Ied14137e01bf685547c093b907484b4dee583fda
Signed-off-by: default avatarVijayavardhan Vennapusa <vvreddy@codeaurora.org>
parent 998590af
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -474,6 +474,7 @@ static void usb_qdss_disconnect_work(struct work_struct *work)
{
	struct f_qdss *qdss;
	int status;
	unsigned long flags;

	qdss = container_of(work, struct f_qdss, disconnect_w);
	pr_debug("usb_qdss_disconnect_work\n");
@@ -496,6 +497,14 @@ static void usb_qdss_disconnect_work(struct work_struct *work)
		status = set_qdss_data_connection(qdss, 0);
		if (status)
			pr_err("qdss_disconnect error");

		spin_lock_irqsave(&qdss->lock, flags);
		if (qdss->endless_req) {
			usb_ep_free_request(qdss->port.data,
					qdss->endless_req);
			qdss->endless_req = NULL;
		}
		spin_unlock_irqrestore(&qdss->lock, flags);
	}

	/*
@@ -528,6 +537,8 @@ static void usb_qdss_connect_work(struct work_struct *work)
{
	struct f_qdss *qdss;
	int status;
	struct usb_request *req = NULL;
	unsigned long flags;

	qdss = container_of(work, struct f_qdss, connect_w);

@@ -548,8 +559,13 @@ static void usb_qdss_connect_work(struct work_struct *work)
	if (qdss->ch.notify)
		qdss->ch.notify(qdss->ch.priv, USB_QDSS_CONNECT,
						NULL, &qdss->ch);
	spin_lock_irqsave(&qdss->lock, flags);
	req = qdss->endless_req;
	spin_unlock_irqrestore(&qdss->lock, flags);
	if (!req)
		return;

	status = usb_ep_queue(qdss->port.data, qdss->endless_req, GFP_ATOMIC);
	status = usb_ep_queue(qdss->port.data, req, GFP_ATOMIC);
	if (status)
		pr_err("%s: usb_ep_queue error (%d)\n", __func__, status);
}
@@ -849,9 +865,11 @@ void usb_qdss_close(struct usb_qdss_ch *ch)
		return;
	}

	if (qdss->endless_req) {
		usb_ep_dequeue(qdss->port.data, qdss->endless_req);
		usb_ep_free_request(qdss->port.data, qdss->endless_req);
		qdss->endless_req = NULL;
	}
	gadget = qdss->gadget;
	ch->app_conn = 0;
	spin_unlock_irqrestore(&qdss_lock, flags);