OSDN Git Service

usb: gadget: f_cdev: Fix NULL ptr dereference in usb_cser_notify
authorHemant Kumar <hemantk@codeaurora.org>
Thu, 28 Jul 2016 19:00:36 +0000 (12:00 -0700)
committerHemant Kumar <hemantk@codeaurora.org>
Fri, 29 Jul 2016 18:46:23 +0000 (11:46 -0700)
Upon usb disconnect or composition switch notify ep request buffer
as well as the request are freed. This is racing with user space
ioctl on character device trying to send the notification to USB
host. As a result notify ep request buffer is being dereferenced
causing NULL pointer dereference. Fix the issue by checking
is_connected flag by taking port lock before accessing notify
ep request and request buffer.

Change-Id: I380efdf90305a65d4cde46dfe44762ac11c87678
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
drivers/usb/gadget/function/f_cdev.c

index 0a9a3af..b22ea65 100644 (file)
@@ -529,6 +529,14 @@ static int usb_cser_notify(struct f_cdev *port, u8 type, u16 value,
        const unsigned                  len = sizeof(*notify) + length;
        void                            *buf;
        int                             status;
+       unsigned long                   flags;
+
+       spin_lock_irqsave(&port->port_lock, flags);
+       if (!port->is_connected) {
+               spin_unlock_irqrestore(&port->port_lock, flags);
+               pr_debug("%s: port disconnected\n", __func__);
+               return -ENODEV;
+       }
 
        req = port->port_usb.notify_req;
        port->port_usb.notify_req = NULL;
@@ -544,7 +552,9 @@ static int usb_cser_notify(struct f_cdev *port, u8 type, u16 value,
        notify->wValue = cpu_to_le16(value);
        notify->wIndex = cpu_to_le16(port->port_usb.data_id);
        notify->wLength = cpu_to_le16(length);
+       /* 2 byte data copy */
        memcpy(buf, data, length);
+       spin_unlock_irqrestore(&port->port_lock, flags);
 
        status = usb_ep_queue(ep, req, GFP_ATOMIC);
        if (status < 0) {