Skip to main content

Linux Kernel EUVDEUVD-2026-45667

| CVE-2026-63894 HIGH
2026-07-19 Linux GHSA-xh4m-2r9c-xfr3
7.8
CVSS 3.1 · Vendor: Linux
Share

Severity by source

Vendor (Linux) PRIMARY
7.8 HIGH
AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
vuln.today AI
7.0 HIGH

Local FunctionFS node access (AV:L, PR:L via mount delegation); winning a completion-vs-cancel race makes it AC:H; kernel UAF yields high C/I/A, no scope change.

3.1 AV:L/AC:H/PR:L/UI:N/S:U/C:H/I:H/A:H
4.0 AV:L/AC:H/AT:N/PR:L/UI:N/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N
SUSE
HIGH
qualitative
Red Hat
7.0 MEDIUM
qualitative

Primary rating from Vendor (Linux).

CVSS VectorVendor: Linux

Attack Vector
Local
Attack Complexity
Low
Privileges Required
Low
User Interaction
None
Scope
Unchanged
Confidentiality
High
Integrity
High
Availability
High

Lifecycle Timeline

5
Analysis Generated
Jul 20, 2026 - 16:12 vuln.today
CVSS changed
Jul 20, 2026 - 15:22 NVD
7.8 (HIGH)
Patch available
Jul 19, 2026 - 17:19 EUVD
CVE Published
Jul 19, 2026 - 14:55 cve.org
HIGH 7.8
CVE Published
Jul 19, 2026 - 14:55 cve.org
UNKNOWN (no severity yet)

DescriptionCVE.org

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

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

ffs_epfile_dmabuf_io_complete() calls usb_ep_free_request() on the completed request but leaves priv->req, the back-pointer that ffs_dmabuf_transfer() set on submission, pointing at the freed memory. A later FUNCTIONFS_DMABUF_DETACH ioctl or ffs_epfile_release() on the close path still sees priv->req non-NULL under ffs->eps_lock:

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

so usb_ep_dequeue() is called on a freed usb_request.

On dummy_hcd 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 ep_dequeue() does

container_of(req, struct ci_hw_req, req) and reads hwreq->req.status before acquiring its own lock.

  • cdnsp's cdnsp_gadget_ep_dequeue() 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 eps_lock, so a cancel path holding eps_lock can still observe priv->req non-NULL, race a concurrent completion that clears and frees, and pass the freed pointer to usb_ep_dequeue(). 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 eps_lock in the sole place that mutates priv->req from the callback direction by moving usb_ep_free_request() out of the completion into ffs_dmabuf_cleanup(), the existing work handler scheduled by ffs_dmabuf_signal_done() on ffs->io_completion_wq. Clear priv->req there under eps_lock before freeing, and only clear if priv->req still names our request (a subsequent ffs_dmabuf_transfer() on the same attachment may have queued a new one).

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

The priv ref count protects the containing ffs_dmabuf_priv: ffs_dmabuf_transfer() takes a ref via ffs_dmabuf_get(), cleanup drops it via ffs_dmabuf_put(), so priv stays live for the cleanup even after the cancel path's list_del + ffs_dmabuf_put.

The ffs_dmabuf_transfer() error path no longer frees usb_req inline: fence->req and fence->ep are set before usb_ep_queue(), so ffs_dmabuf_cleanup() (scheduled by the error-path ffs_dmabuf_signal_done()) owns the free regardless of whether the queue succeeded.

Reproduced under KASAN on both detach and close paths against dummy_hcd with an observability hook (kasan_check_byte(priv->req) immediately before usb_ep_dequeue) 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 dummy_alloc_request, free in dummy_timer, fault reached from ffs_epfile_release (close) and from the FUNCTIONFS_DMABUF_DETACH 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 GLOBAL_ROOT_UID, 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.

AnalysisAI

Local privilege-boundary memory corruption in the Linux kernel USB gadget FunctionFS (f_fs) driver lets a process with access to the FunctionFS control node trigger a use-after-free by racing a DMABUF request completion against a FUNCTIONFS_DMABUF_DETACH ioctl or the file-close path. The completion frees the usb_request but leaves the priv->req back-pointer dangling, so the cancel path passes freed memory to usb_ep_dequeue(), corrupting kernel memory on SG-capable UDCs (chipidea, cdnsp) that dereference the request immediately. EPSS is low (0.20%, 10th percentile) and there is no public exploit identified at time of analysis; a vendor patch is available across stable trees.

Technical ContextAI

The flaw lives in drivers/usb/gadget/function/f_fs.c, the FunctionFS driver that exposes USB gadget endpoints to userspace via a mounted functionfs filesystem. The affected code path is the DMABUF zero-copy transfer feature (FUNCTIONFS_DMABUF_ATTACH/DETACH/TRANSFER ioctls) added around kernel 6.9. The root cause is a classic lifetime/ownership race (CWE-416 Use-After-Free, though the record lists CWE as N/A): ffs_epfile_dmabuf_io_complete() runs the completion callback without holding ffs->eps_lock and calls usb_ep_free_request() on the request, but never clears priv->req, the back-pointer set by ffs_dmabuf_transfer(). A concurrent cancel path holding eps_lock reads priv->ep && priv->req and calls usb_ep_dequeue() on the now-freed usb_request. On dummy_hcd the dequeue only pointer-compares against a live queue so it reads without faulting (KASAN-only), but real in-tree SG-capable UDCs immediately dereference: chipidea's ep_dequeue() does container_of(req, struct ci_hw_req, req) and reads hwreq->req.status, and cdnsp reads request->status before locking. The fix moves usb_ep_free_request() out of the lockless completion into ffs_dmabuf_cleanup() (the io_completion_wq work handler), clearing priv->req under eps_lock and only if it still names the same request, with the priv refcount keeping the container alive. CPE data identifies the affected product only generically as cpe:2.3:a:linux:linux.

RemediationAI

Vendor-released patch: update to a fixed stable kernel - 6.12.93, 6.18.35, 7.0.12, or mainline 7.1 (or any distribution kernel that backports the four fix commits listed on git.kernel.org, notably c872d8a065b3b499ce4c3ad168b5d34b68524f66 and its siblings). Apply via your distribution's kernel update channel and reboot. Where immediate patching is not possible, the concrete compensating control is to avoid delegating the FunctionFS mount to lower-privileged code: keep functionfs mounted with default GLOBAL_ROOT_UID ownership and do NOT use the uid=/gid=/fmode= mount options to hand the control/endpoint nodes to a non-root gadget daemon, which forces an attacker to already hold root (removing the privilege-boundary crossing). If DMABUF zero-copy transfers are not required by your gadget application, avoid using the FUNCTIONFS_DMABUF_ATTACH/TRANSFER/DETACH ioctls, or restrict the device so it does not operate in USB gadget mode - the trade-off is loss of zero-copy performance or of gadget functionality entirely. Advisory/reference: https://nvd.nist.gov/vuln/detail/CVE-2026-63894.

Vendor StatusVendor

SUSE

Severity: Important
Product Status
SUSE Linux Enterprise Desktop 15 SP7 Affected
SUSE Linux Enterprise Desktop 15 SP7 Affected
SUSE Linux Enterprise High Availability Extension 15 SP7 Affected
SUSE Linux Enterprise High Availability Extension 15 SP7 Affected
SUSE Linux Enterprise High Availability Extension 16.0 Affected

Share

EUVD-2026-45667 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy