{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-99227","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","state":"PUBLISHED","assignerShortName":"Linux","dateReserved":"2026-09-25T10:25:14.402Z","datePublished":"2026-11-02T16:06:36.101Z","dateUpdated":"2026-11-03T19:12:59.440Z"},"containers":{"cna":{"providerMetadata":{"orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux","dateUpdated":"2026-11-03T19:12:59.440Z"},"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nio_uring/waitid: prevent cancel reference wrap\n\nio_waitid packs the cancellation state into bit 31 of ->refs and uses\nbits 30:0 as a 31-bit reference counter:\n\n  #define IO_WAITID_CANCEL_FLAG BIT(31)\n  #define IO_WAITID_REF_MASK    GENMASK(30, 0)\n\n__io_waitid_cancel() marks a request canceled, then increments the low\nbits of ->refs to claim completion ownership. When another path owns the\nrequest, the increment remains even though cancellation returns false.\nThe request remains discoverable by cancellation, so repeated failed\nattempts can wrap the 31-bit reference field to zero. A later\ncancellation can claim ownership and complete the request a second time.\n\nUse atomic_fetch_or() when setting the cancel flag and inspect the old\nflag value. The first cancel attempt continues to the existing ownership\nincrement, preserving its wake and issuer handoff semantics. Later\nattempts see the cancel flag and return without incrementing the\nreference field.\n\nThis makes repeated failed cancellation attempts idempotent while\nleaving the first-cancel state transitions unchanged."}],"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 wrap is triggered from local io_uring_enter() IORING_OP_ASYNC_CANCEL or io_uring_register(IORING_REGISTER_SYNC_CANCEL), which reach the patched __io_waitid_cancel() via io_try_cancel()->io_waitid_cancel()->io_cancel_remove()->io_waitid_cancel_cb(). Per kernel guidance, io_uring is Local; no remote protocol carries the cancel.\nAC:L - The attacker creates an IORING_SETUP_DEFER_TASKRUN ring, submits IORING_OP_WAITID, forks/exits a child so io_waitid_wait() takes a ref and queues io_waitid_cb() without running it (enter without IORING_ENTER_GETEVENTS), then repeats cancel until the 31-bit IO_WAITID_REF_MASK in iw->refs wraps. The sequence is fully attacker-controlled.\nPR:L - io_uring_setup() calls io_uring_allowed() and sysctl_io_uring_disabled defaults to 0. IORING_OP_WAITID and IORING_OP_ASYNC_CANCEL have no capability check, and waiting on the attacker’s own children via kernel_waitid_prepare() needs none.\nUI:N - The attacker creates the ring, submits the WAITID SQE, forks the child that wakes io_waitid_wait(), and issues the repeated cancels against that request. No other user must act.\nS:U - Double-complete of the waitid io_kiocb and the resulting work_list corruption stay inside the host kernel. This is ordinary in-kernel UAF/LPE, not a VM, IOMMU, or sandbox boundary crossing.\nC:H - After the wrap, __io_waitid_cancel() claims the still-listed request and io_req_queue_tw_complete() mpscq_push()es the same io_kiocb already queued by io_waitid_wait(), so the consumer later walks a freed req_cachep object. That UAF read of the recycled request is High confidentiality.\nI:H - The same double mpscq_push writes node->next (including an A->A cycle) on an io_kiocb that io_waitid_complete() has already torn down; after io_req_task_complete() frees it, reclaim of that slab object is a UAF write of a list next pointer and a second completion, i.e. High integrity.\nA:H - The A->A work_list cycle hangs __io_run_local_work() under uring_lock (soft lockup), and the subsequent pop of the freed io_kiocb oopses. Any kernel hang or UAF crash is High availability."}]}],"affected":[{"product":"Linux","vendor":"Linux","defaultStatus":"unaffected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["io_uring/waitid.c"],"versions":[{"version":"f31ecf671ddc498f20219453395794ff2383e06b","lessThan":"20b67288574c7c3df6b8ea7ed3b7af90a868006f","status":"affected","versionType":"git"},{"version":"f31ecf671ddc498f20219453395794ff2383e06b","lessThan":"5bfeee1774791602a0d53eb717f00f172127a017","status":"affected","versionType":"git"},{"version":"f31ecf671ddc498f20219453395794ff2383e06b","lessThan":"857aa2012b91cad6fdef54a4b6c632d9d0b6e64f","status":"affected","versionType":"git"},{"version":"f31ecf671ddc498f20219453395794ff2383e06b","lessThan":"22fb4a4518e305164c7f203608287564de292f34","status":"affected","versionType":"git"},{"version":"f31ecf671ddc498f20219453395794ff2383e06b","lessThan":"98787d3fa4e99564d2b2bc21255b21f670c450d0","status":"affected","versionType":"git"}]},{"product":"Linux","vendor":"Linux","defaultStatus":"affected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["io_uring/waitid.c"],"versions":[{"version":"6.7","status":"affected"},{"version":"0","lessThan":"6.7","status":"unaffected","versionType":"semver"},{"version":"6.12.115","lessThanOrEqual":"6.12.*","status":"unaffected","versionType":"semver"},{"version":"6.18.60","lessThanOrEqual":"6.18.*","status":"unaffected","versionType":"semver"},{"version":"7.2.14","lessThanOrEqual":"7.2.*","status":"unaffected","versionType":"semver"},{"version":"7.3.1","lessThanOrEqual":"7.3.*","status":"unaffected","versionType":"semver"},{"version":"7.4-rc1","lessThanOrEqual":"*","status":"unaffected","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.7","versionEndExcluding":"6.12.115"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.7","versionEndExcluding":"6.18.60"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.7","versionEndExcluding":"7.2.14"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.7","versionEndExcluding":"7.3.1"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.7","versionEndExcluding":"7.4-rc1"}]}]}],"references":[{"url":"https://git.kernel.org/stable/c/20b67288574c7c3df6b8ea7ed3b7af90a868006f"},{"url":"https://git.kernel.org/stable/c/5bfeee1774791602a0d53eb717f00f172127a017"},{"url":"https://git.kernel.org/stable/c/857aa2012b91cad6fdef54a4b6c632d9d0b6e64f"},{"url":"https://git.kernel.org/stable/c/22fb4a4518e305164c7f203608287564de292f34"},{"url":"https://git.kernel.org/stable/c/98787d3fa4e99564d2b2bc21255b21f670c450d0"}],"title":"io_uring/waitid: prevent cancel reference wrap","x_generator":{"engine":"bippy-1.2.0"}}}}