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

Commit fae9fe40 authored by Mayank Rana's avatar Mayank Rana
Browse files

usb: gadget: f_fs: Fix NULL pointer dereference related crash



Commit dd102bc5 ("USB: gadget: f_fs: Allocate extra buffer for
IN endpoint") added functionality to allocate extra buffer with USB
IN endpoint for each adb write request. This results into NULL
pointer dereference crash while epfile_io() is trying to access
ffs->gagdet->extra_buf_alloc against ffs_func_unbind().
ffs_func_unbind() marks ffs->gadget as NULL. Fix this issue by
using spin_lock when ffs->gadget is being updated and accessed.

CRs-Fixed: 994049
Change-Id: I7ebad4fd2b2c4cc7654336447cd5753891ba4f51
Signed-off-by: default avatarMayank Rana <mrana@codeaurora.org>
parent 241c08df
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -713,7 +713,6 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
{
	struct ffs_epfile *epfile = file->private_data;
	struct ffs_ep *ep;
	struct ffs_data *ffs = epfile->ffs;
	char *data = NULL;
	ssize_t ret, data_len = -EINVAL;
	int halt;
@@ -789,9 +788,10 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
		data_len = io_data->read ?
			   usb_ep_align_maybe(gadget, ep->ep, io_data->len) :
			   io_data->len;

		extra_buf_alloc = gadget->extra_buf_alloc;
		spin_unlock_irq(&epfile->ffs->eps_lock);

		extra_buf_alloc = ffs->gadget->extra_buf_alloc;
		if (!io_data->read)
			data = kmalloc(data_len + extra_buf_alloc,
					GFP_KERNEL);
@@ -1671,13 +1671,17 @@ static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev)

static void functionfs_unbind(struct ffs_data *ffs)
{
	unsigned long flags;

	ENTER();

	if (!WARN_ON(!ffs->gadget)) {
		usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req);
		spin_lock_irqsave(&ffs->eps_lock, flags);
		ffs->ep0req = NULL;
		ffs->gadget = NULL;
		clear_bit(FFS_FL_BOUND, &ffs->flags);
		spin_unlock_irqrestore(&ffs->eps_lock, flags);
		ffs_data_put(ffs);
	}
}