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

Commit 7fea26c1 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "usb: gadget: f_hid: fix: Prevent accessing released memory"

parents 79e6f4cf 49c3a6de
Loading
Loading
Loading
Loading
+20 −4
Original line number Diff line number Diff line
@@ -197,6 +197,13 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
	/* pick the first one */
	list = list_first_entry(&hidg->completed_out_req,
				struct f_hidg_req_list, list);

	/*
	 * Remove this from list to protect it from beign free()
	 * while host disables our function
	 */
	list_del(&list->list);

	req = list->req;
	count = min_t(unsigned int, count, req->actual - list->pos);
	spin_unlock_irqrestore(&hidg->spinlock, flags);
@@ -212,16 +219,21 @@ static ssize_t f_hidg_read(struct file *file, char __user *buffer,
	 * call, taking into account its current read position.
	 */
	if (list->pos == req->actual) {
		spin_lock_irqsave(&hidg->spinlock, flags);
		list_del(&list->list);
		kfree(list);
		spin_unlock_irqrestore(&hidg->spinlock, flags);

		req->length = hidg->report_length;
		ret = usb_ep_queue(hidg->out_ep, req, GFP_KERNEL);
		if (ret < 0)
		if (ret < 0) {
			free_ep_req(hidg->out_ep, req);
			return ret;
		}
	} else {
		spin_lock_irqsave(&hidg->spinlock, flags);
		list_add(&list->list, &hidg->completed_out_req);
		spin_unlock_irqrestore(&hidg->spinlock, flags);

		wake_up(&hidg->read_queue);
	}

	return count;
}
@@ -455,6 +467,7 @@ static void hidg_disable(struct usb_function *f)
{
	struct f_hidg *hidg = func_to_hidg(f);
	struct f_hidg_req_list *list, *next;
        unsigned long flags;

	usb_ep_disable(hidg->in_ep);
	hidg->in_ep->driver_data = NULL;
@@ -462,10 +475,13 @@ static void hidg_disable(struct usb_function *f)
	usb_ep_disable(hidg->out_ep);
	hidg->out_ep->driver_data = NULL;

	spin_lock_irqsave(&hidg->spinlock, flags);
	list_for_each_entry_safe(list, next, &hidg->completed_out_req, list) {
		free_ep_req(hidg->out_ep, list->req);
		list_del(&list->list);
		kfree(list);
	}
	spin_unlock_irqrestore(&hidg->spinlock, flags);
}

static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+2 −8
Original line number Diff line number Diff line
@@ -215,12 +215,6 @@ static inline struct usb_request *midi_alloc_ep_req(struct usb_ep *ep,
	return alloc_ep_req(ep, length, length);
}

static void midi_free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
	kfree(req->buf);
	usb_ep_free_request(ep, req);
}

static const uint8_t f_midi_cin_length[] = {
	0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1
};
@@ -286,7 +280,7 @@ f_midi_complete(struct usb_ep *ep, struct usb_request *req)
		if (ep == midi->out_ep)
			f_midi_handle_out_data(ep, req);

		midi_free_ep_req(ep, req);
		free_ep_req(ep, req);
		return;

	case -EOVERFLOW:	/* buffer overrun on read means that
@@ -585,7 +579,7 @@ static void f_midi_transmit(struct f_midi *midi, struct usb_request *req)
	if (req->length > 0)
		usb_ep_queue(ep, req, GFP_ATOMIC);
	else
		midi_free_ep_req(ep, req);
		free_ep_req(ep, req);
}

static void f_midi_in_tasklet(unsigned long data)
+0 −6
Original line number Diff line number Diff line
@@ -435,12 +435,6 @@ static inline struct usb_request *ss_alloc_ep_req(struct usb_ep *ep, int len)
	return alloc_ep_req(ep, len, buflen);
}

void free_ep_req(struct usb_ep *ep, struct usb_request *req)
{
	kfree(req->buf);
	usb_ep_free_request(ep, req);
}

static void disable_ep(struct usb_composite_dev *cdev, struct usb_ep *ep)
{
	int			value;
+0 −1
Original line number Diff line number Diff line
@@ -69,7 +69,6 @@ void lb_modexit(void);
int lb_modinit(void);

/* common utilities */
void free_ep_req(struct usb_ep *ep, struct usb_request *req);
void disable_endpoints(struct usb_composite_dev *cdev,
		struct usb_ep *in, struct usb_ep *out,
		struct usb_ep *iso_in, struct usb_ep *iso_out,
+0 −1
Original line number Diff line number Diff line
@@ -11,7 +11,6 @@
 * published by the Free Software Foundation.
 */

#include <linux/usb/gadget.h>
#include "u_f.h"

struct usb_request *alloc_ep_req(struct usb_ep *ep, int len, int default_len)
Loading