CVE-2026-80810
NoneCVSS
—
EPSS
0.2%
Published
Sep 4, 2026
CISA due date
—
Cloudanix analysis
A bug in the Linux kernel can let a program that uses advanced input-output features corrupt memory when very large memory pages are involved, potentially causing crashes or security bypasses on affected machines.
- Exploitation
- Local Privilege
- Attacker needs
- Local User
- Complexity
- High
- Impact
- Privilege Gain
- Component
- OS kernel
- Class
- Buffer Overflow
- Remediation
- Upgrade
- Effort
- Medium
- Patch risk
- Low
What it actually does
Incorrect use of a plain int literal in a left-shift for folio size calculation causes overflow and underestimation on 64-bit kernels when folio_shift is 32 or greater, resulting in out-of-bounds writes to the bvec array and reads past the end of the registered bvec buffer in io_vec_fill_bvec().
Why it matters to the business
Systems running affected kernels with io_uring and gigantic hugetlb pages may experience kernel memory corruption, crashes, or potential local privilege escalation; the narrow conditions and low EPSS indicate limited immediate widespread risk but still require prompt patching on high-value hosts.
How an attack unfolds
An attacker with local access crafts an io_uring submission that registers a buffer backed by a gigantic hugetlb page (folio_shift >= 32), then issues operations that invoke io_estimate_bvec_size() followed by io_vec_fill_bvec(); the mismatch between the correctly sized array and the tiny 4-byte folio chunks causes repeated writes past the allocated bvec array and reads beyond the registered buffer.
How to fix it
Upgrade to a kernel containing the upstream fix that changes the literal to 1UL in io_vec_fill_bvec(); rebuild and reboot, or apply the one-line patch if backporting is required; disable io_uring via sysctl where the feature is not needed.
How to confirm the fix worked
Confirm the source change from "1 << imu->folio_shift" to "1UL << imu->folio_shift" in io_uring/rsrc.c; verify running kernel version includes the commit; test with a synthetic io_uring workload that exercises gigantic hugetlb pages.
Typical attack path
- Obtain local code execution on a vulnerable Linux host
- Allocate or map a gigantic hugetlb page (16G on arm64 64K page configs)
- Register the page via io_uring IORING_REGISTER_BUFFERS or similar
- Submit an io_uring request whose iovec spans the page such that segment count estimation uses the real shift
- Trigger io_vec_fill_bvec() to induce repeated out-of-bounds writes
How to detect it
Review kernel logs for oops or panic messages referencing io_vec_fill_bvec or io_uring rsrc; inspect io_uring submission traces for unusually large iovecs on registered buffers; no public exploit artifacts are known.
What your security team should do
- Prioritize patching on any system that enables io_uring and supports gigantic hugetlb pages
- Audit workloads for io_uring usage and consider disabling it via kernel command line or sysctl where feasible
- Monitor for future CVEs in io_uring and maintain rapid kernel update pipelines
The record
In the Linux kernel, the following vulnerability has been resolved: io_uring/rsrc: fix folio size overflow in io_vec_fill_bvec() io_vec_fill_bvec() computes the folio size with a plain int 1: unsigned long folio_size = 1 << imu->folio_shift; imu->folio_shift is unsigned int and comes from folio_shift() of the folio backing the registered buffer, so it can be 32 or more on a 64 bit kernel. Shifting int 1 that far is undefined, and on x86 and arm64 the count is taken modulo 32, so a shift of 34 yields 4 rather than 16G. Every other folio_shift shift in this file already uses 1UL. The result is that the segment estimate and the fill loop disagree. io_estimate_bvec_size() sizes the bvec array with the real shift: max_segs += (iov[i].iov_len >> shift) + 2; so a 1M iovec on a 16G folio is charged 2 segments, while io_vec_fill_bvec() then walks the same iovec in folio_size chunks of 4 bytes and writes res_bvec[bvec_idx] a quarter of a million times, past the end of the array it was given. src_bvec is advanced once per iteration as well, so imu->bvec is read past its end at the same time. validate_fixed_range() only checks that the range is inside the registered buffer and does not bound the segment count. Reaching it needs a folio with a shift of at least 32, which means a gigantic hugetlb page: 16G on arm64 with 64K pages, where CONT_PMD_SHIFT is 34 and hugetlb_add_hstate(CONT_PMD_SHIFT - PAGE_SHIFT) registers that size, and likewise on powerpc. x86_64 tops out at 1G, so a shift of 30, which still fits in int and is unaffected. Use 1UL, as the rest of the file does.
Affected packages
| Ecosystem | Package | Introduced | Fixed |
|---|