{"id":"CVE-2026-90044","state":"PUBLISHED","title":"usb: gadget: f_fs: Fix Use-After-Free in AIO error path","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nusb: gadget: f_fs: Fix Use-After-Free in AIO error path\n\nIn ffs_epfile_write_iter() and ffs_epfile_read_iter(), when ffs_epfile_io()\nfails with an error other than -EIOCBQUEUED, the io_data structure (`p`) is\nfreed. However, for AIO operations, the kiocb cancel function was already\narmed and kiocb->private was set to `p`.\n\nIf a concurrent cancel operation (such as sys_io_cancel()) executes after\nffs_epfile_io() fails but before the function frees `p`, a Use-After-Free\ncan occur when the cancellation handler accesses the freed pointer.\n\nTo securely fix this race condition, we must properly un-arm the\ncancellation. Invoking `kiocb->ki_complete()` does exactly this by\nacquiring `ctx->ctx_lock` and safely removing the kiocb from the active\nsequence. In doing so, it ensures that a parallel io_cancel can no longer\ndiscover the kiocb, effectively closing the race window.\n\nWe then return -EIOCBQUEUED to notify the VFS layer that the kiocb has been\nconsumed and it should avoid attempting to complete the request again or\ntriggering subsequent completion handlers.","publishedAt":"2026-09-16T10:33:41.695Z","updatedAt":"2026-10-30T12:33:56.040Z","severity":{"score":7.8,"label":"High","version":"3.1","vector":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","source":"Linux"},"assigner":"Linux","products":["Linux Linux"],"affected":[{"vendor":"Linux","product":"Linux","defaultStatus":"unaffected","versions":[{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"922a29e1f8573fd405eea1a73a52112c4e7fcfc4","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"0a2f71ccf9c2053de725e9a7922d081f3f3a3804","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"b5f0e80a03e87bd932487e03248eae3ba3ed7b45","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"153b5ecd29ed055562400bc17c91df3fd869b0ce","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"4a2fb2d12b87b43724230abb52a1440617c7b6cc","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"e78dcb1f7ec271449c54984dc90c62a5ba272de7","versionType":"git"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/usb/gadget/function/f_fs.c"]},{"vendor":"Linux","product":"Linux","defaultStatus":"affected","versions":[{"version":"4.0","status":"affected"},{"version":"0","status":"unaffected","lessThan":"4.0","versionType":"semver"},{"version":"6.1.191","status":"unaffected","lessThanOrEqual":"6.1.*","versionType":"semver"},{"version":"6.6.160","status":"unaffected","lessThanOrEqual":"6.6.*","versionType":"semver"},{"version":"6.12.111","status":"unaffected","lessThanOrEqual":"6.12.*","versionType":"semver"},{"version":"6.18.51","status":"unaffected","lessThanOrEqual":"6.18.*","versionType":"semver"},{"version":"7.2.5","status":"unaffected","lessThanOrEqual":"7.2.*","versionType":"semver"},{"version":"7.3","status":"unaffected","lessThanOrEqual":"*","versionType":"original_commit_for_fix"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/usb/gadget/function/f_fs.c"]}],"references":["https://git.kernel.org/stable/c/922a29e1f8573fd405eea1a73a52112c4e7fcfc4","https://git.kernel.org/stable/c/0a2f71ccf9c2053de725e9a7922d081f3f3a3804","https://git.kernel.org/stable/c/b5f0e80a03e87bd932487e03248eae3ba3ed7b45","https://git.kernel.org/stable/c/153b5ecd29ed055562400bc17c91df3fd869b0ce","https://git.kernel.org/stable/c/4a2fb2d12b87b43724230abb52a1440617c7b6cc","https://git.kernel.org/stable/c/e78dcb1f7ec271449c54984dc90c62a5ba272de7"],"weaknesses":[],"ingestedAt":"2026-10-30T12:52:04.348Z","source":{"repository":"CVEProject/cvelistV5","path":"cves/2026/90xxx/CVE-2026-90044.json","commit":"1f312381e38164a43607eebab851b151dd16861e","baselineCommit":"556c9d3a8cd17e218bb8e452ba7cd619a384ff47"},"raw":{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-90044","state":"PUBLISHED","datePublished":"2026-09-16T10:33:41.695Z","dateUpdated":"2026-10-30T12:33:56.040Z","assignerShortName":"Linux","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","dateReserved":"2026-09-11T19:38:34.783Z"},"containers":{"cna":{"title":"usb: gadget: f_fs: Fix Use-After-Free in AIO error path","descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nusb: gadget: f_fs: Fix Use-After-Free in AIO error path\n\nIn ffs_epfile_write_iter() and ffs_epfile_read_iter(), when ffs_epfile_io()\nfails with an error other than -EIOCBQUEUED, the io_data structure (`p`) is\nfreed. However, for AIO operations, the kiocb cancel function was already\narmed and kiocb->private was set to `p`.\n\nIf a concurrent cancel operation (such as sys_io_cancel()) executes after\nffs_epfile_io() fails but before the function frees `p`, a Use-After-Free\ncan occur when the cancellation handler accesses the freed pointer.\n\nTo securely fix this race condition, we must properly un-arm the\ncancellation. Invoking `kiocb->ki_complete()` does exactly this by\nacquiring `ctx->ctx_lock` and safely removing the kiocb from the active\nsequence. In doing so, it ensures that a parallel io_cancel can no longer\ndiscover the kiocb, effectively closing the race window.\n\nWe then return -EIOCBQUEUED to notify the VFS layer that the kiocb has been\nconsumed and it should avoid attempting to complete the request again or\ntriggering subsequent completion handlers."}],"affected":[{"vendor":"Linux","product":"Linux","defaultStatus":"unaffected","versions":[{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"922a29e1f8573fd405eea1a73a52112c4e7fcfc4","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"0a2f71ccf9c2053de725e9a7922d081f3f3a3804","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"b5f0e80a03e87bd932487e03248eae3ba3ed7b45","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"153b5ecd29ed055562400bc17c91df3fd869b0ce","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"4a2fb2d12b87b43724230abb52a1440617c7b6cc","versionType":"git"},{"version":"de2080d41b5d584205e408d72021f0f335a046fc","status":"affected","lessThan":"e78dcb1f7ec271449c54984dc90c62a5ba272de7","versionType":"git"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/usb/gadget/function/f_fs.c"]},{"vendor":"Linux","product":"Linux","defaultStatus":"affected","versions":[{"version":"4.0","status":"affected"},{"version":"0","status":"unaffected","lessThan":"4.0","versionType":"semver"},{"version":"6.1.191","status":"unaffected","lessThanOrEqual":"6.1.*","versionType":"semver"},{"version":"6.6.160","status":"unaffected","lessThanOrEqual":"6.6.*","versionType":"semver"},{"version":"6.12.111","status":"unaffected","lessThanOrEqual":"6.12.*","versionType":"semver"},{"version":"6.18.51","status":"unaffected","lessThanOrEqual":"6.18.*","versionType":"semver"},{"version":"7.2.5","status":"unaffected","lessThanOrEqual":"7.2.*","versionType":"semver"},{"version":"7.3","status":"unaffected","lessThanOrEqual":"*","versionType":"original_commit_for_fix"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/usb/gadget/function/f_fs.c"]}],"references":[{"url":"https://git.kernel.org/stable/c/922a29e1f8573fd405eea1a73a52112c4e7fcfc4"},{"url":"https://git.kernel.org/stable/c/0a2f71ccf9c2053de725e9a7922d081f3f3a3804"},{"url":"https://git.kernel.org/stable/c/b5f0e80a03e87bd932487e03248eae3ba3ed7b45"},{"url":"https://git.kernel.org/stable/c/153b5ecd29ed055562400bc17c91df3fd869b0ce"},{"url":"https://git.kernel.org/stable/c/4a2fb2d12b87b43724230abb52a1440617c7b6cc"},{"url":"https://git.kernel.org/stable/c/e78dcb1f7ec271449c54984dc90c62a5ba272de7"}],"metrics":[{"cvssV3_1":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH"},"scenarios":[{"lang":"en","value":"AV:L - The UAF is in FunctionFS epfile AIO (`ffs_epfile_write_iter`/`read_iter` via `io_submit`/`io_cancel` on functionfs ep files), a local syscall path. `ffs_epfile_io()` can fail with `-EAGAIN` on `O_NONBLOCK` before any USB host is involved; this is the gadget userspace API, matching CVE-2024-36894/CVE-2026-63894 as Local rather than Physical.\nAC:L - The attacker controls both sides: one thread `io_submit`s AIO that fails after `kiocb_set_cancel_fn` (O_NONBLOCK `-EAGAIN`, halt, `-EFAULT`), while another calls `io_cancel`/`io_destroy`. The race between `kfree(p)` and `aio_remove_iocb` is freely retryable, so a race the attacker creates is AC:L.\nPR:L - FunctionFS mounts commonly use `uid=`/`gid=`/`fmode=` to delegate ep files to unprivileged gadget daemons (adbd/shell on Android, MTP, embedded USB services). Once mounted by init, those accounts can open ep files and issue AIO without init-namespace root.\nUI:N - The attacker performs `io_submit` and `io_cancel`/`io_destroy` on their own FunctionFS endpoint fds. No separate victim action is required beyond an already-deployed FunctionFS gadget.\nS:U - The use-after-free corrupts kernel heap (`ffs_io_data`) within the same host kernel security authority. This is ordinary local privilege escalation, not a VM escape or IOMMU/sandbox boundary cross.\nC:H - Use-after-free of `ffs_io_data`: `ffs_aio_cancel()` reads `kiocb->private` after `kfree`. Reclaim of that kmalloc object lets the attacker control `io_data->ep`/`req` and leak kernel memory via UDC dequeue; UAFs are scored High for confidentiality.\nI:H - A reclaimed `ffs_io_data` yields attacker-controlled pointers passed to `usb_ep_dequeue()` from `ffs_aio_cancel`, providing a heap write and control-flow hijack primitive. Kernel UAFs are scored High for integrity.\nA:H - Dereferencing the freed `ffs_io_data` in `ffs_aio_cancel` causes kernel oops/panic even without a full exploit; any such crash is High availability impact."}]}],"providerMetadata":{"shortName":"Linux","orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","dateUpdated":"2026-10-30T12:33:56.040Z"},"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.0","versionEndExcluding":"6.1.191"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.0","versionEndExcluding":"6.6.160"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.0","versionEndExcluding":"6.12.111"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.0","versionEndExcluding":"6.18.51"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.0","versionEndExcluding":"7.2.5"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.0","versionEndExcluding":"7.3"}]}]}],"x_generator":{"engine":"bippy-1.2.0"}}}}}