CVE-2026-63894: usb: gadget: f_fs: serialize DMABUF cancel against request completion

Published Jul 19, 2026
·
Updated

In the Linux kernel, the following vulnerability has been resolved:

usb: gadget: ffs: serialize DMABUF cancel against request completion

ffsepfiledmabufiocomplete() calls usbepfreerequest() on the completed request but leaves priv->req, the back-pointer that ffsdmabuftransfer() set on submission, pointing at the freed memory. A later FUNCTIONFSDMABUFDETACH ioctl or ffsepfilerelease() on the close path still sees priv->req non-NULL under ffs->epslock:

if (priv->ep && priv->req) usbepdequeue(priv->ep, priv->req);

so usbepdequeue() is called on a freed usbrequest.

On dummyhcd the dequeue path only walks a live queue and pointer-compares, so the freed pointer reads without faulting and KASAN requires an explicit check at the FunctionFS call site to surface the use-after-free. On SG-capable in-tree UDCs the dequeue path dereferences the supplied request immediately:

chipidea's epdequeue() does containerof(req, struct cihwreq, req) and reads hwreq->req.status before acquiring its own lock. cdnsp's cdnspgadgetepdequeue() reads request->status first.

The narrower option of clearing priv->req via cmpxchg() in the completion does not close the race: the completion runs without epslock, so a cancel path holding epslock can still observe priv->req non-NULL, race a concurrent completion that clears and frees, and pass the freed pointer to usbepdequeue(). A slightly longer fix that moves the free into the cleanup work is needed.

Same class of lifetime race as the recent usbip-vudc timer fix [1].

Take epslock in the sole place that mutates priv->req from the callback direction by moving usbepfreerequest() out of the completion into ffsdmabufcleanup(), the existing work handler scheduled by ffsdmabufsignaldone() on ffs->iocompletionwq. Clear priv->req there under epslock before freeing, and only clear if priv->req still names our request (a subsequent ffsdmabuftransfer() on the same attachment may have queued a new one).

This keeps the existing dummyhcd sync-dequeue invariant: the completion callback is still invoked by the UDC without epslock held (dummyhcd drops its own lock before calling the callback), and the callback now takes no ffs lock at all. Serialization against the cancel path happens in cleanup, which runs from the workqueue with no ffs lock held on entry.

The priv ref count protects the containing ffsdmabufpriv: ffsdmabuftransfer() takes a ref via ffsdmabufget(), cleanup drops it via ffsdmabufput(), so priv stays live for the cleanup even after the cancel path's listdel + ffsdmabufput.

The ffsdmabuftransfer() error path no longer frees usbreq inline: fence->req and fence->ep are set before usbepqueue(), so ffsdmabufcleanup() (scheduled by the error-path ffsdmabufsignaldone()) owns the free regardless of whether the queue succeeded.

Reproduced under KASAN on both detach and close paths against dummyhcd with an observability hook (kasancheckbyte(priv->req) immediately before usbepdequeue) at the two FunctionFS cancel sites to surface the stale-pointer access; the hook is not part of this patch. The KASAN allocator / free stacks in the captured splats identify the same request: alloc in dummyallocrequest, free in dummytimer, fault reached from ffsepfilerelease (close) and from the FUNCTIONFSDMABUFDETACH ioctl (detach). With the patch applied, both paths are silent under the same hook.

The bug is reached from the FunctionFS device node, which in real deployments is owned by the privileged gadget daemon (adbd, UMS, composite gadget services, etc.); it is not reachable from unprivileged userspace or from a USB host on the cable. FunctionFS mounts default to GLOBALROOTUID, but the filesystem supports uid=, gid=, and fmode= delegation to a non-root gadget daemon, so on real deployments the attacker may be a less-privileged service rather than root.

Affected Software

1 affected component
Linux Linux kernel

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade Linux kernel USB gadget FunctionFS (usb: gadget: f_fs: serialize DMABUF cancel against request completion) to a version that resolves this vulnerability.

    Patch usb: gadget: f_fs: serialize DMABUF cancel against request completion

Event History

Jul 19, 2026
CVE Published
via MITRE·02:55 PM
Data Sourced
via MITRE·02:55 PM
DescriptionSeverity
Data Sourced
via NVD·04:17 PM
DescriptionSeverity

Frequently Asked Questions

1

What is the severity of CVE-2026-63894?

CVE-2026-63894 has a severity rating of high, with a score of 7.8.

2

How do I fix CVE-2026-63894?

To fix CVE-2026-63894, update your Linux kernel to the latest version where this vulnerability has been resolved.

3

What type of vulnerability is CVE-2026-63894?

CVE-2026-63894 is categorized as a 'Use After Free' vulnerability.

4

What software is affected by CVE-2026-63894?

CVE-2026-63894 affects the Linux kernel.

5

What are the potential impacts of CVE-2026-63894?

The potential impacts of CVE-2026-63894 include elevated privileges and denial of service due to improper handling of DMABUF requests.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203