lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <CALEuBamV3oXcTm1bE=m6O6XcXR=rrFaMgjaLyZqSOG2ghDDqqw@mail.gmail.com>
Date: Thu, 15 Jan 2026 04:32:21 +0800
From: 齐柯宇 <qikeyu2017@...il.com>
To: pawell@...ence.com, gregkh@...uxfoundation.org
Cc: linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] usb: cdns2: fix use-after-free in cdns2_gadget_giveback

This fix addresses a use-after-free vulnerability discovered through
static code analysis of the cdns2_gadget_giveback() function.

The vulnerability exists because after usb_gadget_giveback_request()
is called, the code continues to access request->buf. However,
usb_gadget_giveback_request() invokes the request's complete callback,
and certain gadget function drivers (such as FunctionFS with DMABUF)
may directly free the request within this callback.

Call flow leading to use-after-free:

  cdns2_gadget_giveback()
    -> usb_gadget_giveback_request()
       -> request->complete()  [e.g., ffs_epfile_dmabuf_io_complete]
          -> usb_ep_free_request()  // request is freed here
    -> if (request->buf == pdev->zlp_buf)  // UAF: accessing freed memory
       -> cdns2_gadget_ep_free_request()   // potential double-free

Data flow analysis shows that this vulnerability can be triggered when:
1. A user application uses FunctionFS with DMABUF transfer capability
2. The user attaches a DMABUF via FUNCTIONFS_DMABUF_ATTACH ioctl
3. The user initiates a transfer via FUNCTIONFS_DMABUF_TRANSFER ioctl
4. Upon transfer completion, ffs_epfile_dmabuf_io_complete() is called
   as the complete callback, which frees the request
5. cdns2_gadget_giveback() then accesses the freed request->buf field

Evidence that complete callback can free the request (f_fs.c):

  static void ffs_epfile_dmabuf_io_complete(struct usb_ep *ep,
                                            struct usb_request *req)
  {
      ffs_dmabuf_signal_done(req->context, req->status);
      usb_ep_free_request(ep, req);  // frees the request directly
  }

The fix saves the ZLP check result before calling the complete callback
and uses mutually exclusive logic: requests with complete callbacks are
owned by the gadget function driver, while only ZLP requests without
complete callbacks are freed by the UDC driver.

Fixes: 3eb1f1efe204 ("usb: cdns2: Add main part of Cadence USBHS driver")
Signed-off-by: Kery Qi <qikeyu2017@...il.com>
---
 drivers/usb/gadget/udc/cdns2/cdns2-gadget.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
index 9b53daf76583..8997623cca5a 100644
--- a/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-gadget.c
@@ -240,6 +240,7 @@ void cdns2_gadget_giveback(struct cdns2_endpoint *pep,
 {
   struct usb_request *request = &preq->request;
   struct cdns2_device *pdev = pep->pdev;
+  bool is_zlp = (request->buf == pdev->zlp_buf);

   list_del_init(&preq->list);

@@ -257,10 +258,14 @@ void cdns2_gadget_giveback(struct cdns2_endpoint *pep,
      spin_unlock(&pdev->lock);
      usb_gadget_giveback_request(&pep->endpoint, request);
      spin_lock(&pdev->lock);
-  }
-
-  if (request->buf == pdev->zlp_buf)
+  } else if (is_zlp) {
+     /*
+      * Only ZLP requests without a complete callback are freed
+      * by the driver. Requests with complete callbacks are
+      * owned by the gadget function driver.
+      */
      cdns2_gadget_ep_free_request(&pep->endpoint, request);
+  }
 }

 static void cdns2_wa1_restore_cycle_bit(struct cdns2_endpoint *pep)
-- 
2.34.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ