| From f6e1dc813456231d6a70faceaf2f868ae6190f77 Mon Sep 17 00:00:00 2001 |
| From: Chandana Kishori Chiluveru <cchiluve@codeaurora.org> |
| Date: Tue, 1 Oct 2019 13:16:48 +0530 |
| Subject: [PATCH] usb: gadget: composite: Fix possible double free memory bug |
| |
| commit 1c20c89b0421b52b2417bb0f62a611bc669eda1d upstream. |
| |
| composite_dev_cleanup call from the failure of configfs_composite_bind |
| frees up the cdev->os_desc_req and cdev->req. If the previous calls of |
| bind and unbind is successful these will carry stale values. |
| |
| Consider the below sequence of function calls: |
| configfs_composite_bind() |
| composite_dev_prepare() |
| - Allocate cdev->req, cdev->req->buf |
| composite_os_desc_req_prepare() |
| - Allocate cdev->os_desc_req, cdev->os_desc_req->buf |
| configfs_composite_unbind() |
| composite_dev_cleanup() |
| - free the cdev->os_desc_req->buf and cdev->req->buf |
| Next composition switch |
| configfs_composite_bind() |
| - If it fails goto err_comp_cleanup will call the |
| composite_dev_cleanup() function |
| composite_dev_cleanup() |
| - calls kfree up with the stale values of cdev->req->buf and |
| cdev->os_desc_req from the previous configfs_composite_bind |
| call. The free call on these stale values leads to double free. |
| |
| Hence, Fix this issue by setting request and buffer pointer to NULL after |
| kfree. |
| |
| Signed-off-by: Chandana Kishori Chiluveru <cchiluve@codeaurora.org> |
| Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c |
| index dfcabadeed01..33115e19756c 100644 |
| --- a/drivers/usb/gadget/composite.c |
| +++ b/drivers/usb/gadget/composite.c |
| @@ -2156,14 +2156,18 @@ void composite_dev_cleanup(struct usb_composite_dev *cdev) |
| usb_ep_dequeue(cdev->gadget->ep0, cdev->os_desc_req); |
| |
| kfree(cdev->os_desc_req->buf); |
| + cdev->os_desc_req->buf = NULL; |
| usb_ep_free_request(cdev->gadget->ep0, cdev->os_desc_req); |
| + cdev->os_desc_req = NULL; |
| } |
| if (cdev->req) { |
| if (cdev->setup_pending) |
| usb_ep_dequeue(cdev->gadget->ep0, cdev->req); |
| |
| kfree(cdev->req->buf); |
| + cdev->req->buf = NULL; |
| usb_ep_free_request(cdev->gadget->ep0, cdev->req); |
| + cdev->req = NULL; |
| } |
| cdev->next_string_id = 0; |
| device_remove_file(&cdev->gadget->dev, &dev_attr_suspended); |
| -- |
| 2.7.4 |
| |