Executive brief
The Linux kernel's NVMe PCI driver contains a memory allocation bug in the calculation of Physical Region Page (PRP) list sizes. The driver miscalculates the required memory pool size, causing it to allocate insufficient memory. When specific I/O conditions occur (a 4MB transfer with 127 physical segments on queues without SGL support), the driver writes beyond the allocated buffer, corrupting kernel memory and potentially causing system crashes or instability.
Technical details
The vulnerability is a unit-conversion error in the nvme_pci_npages_prp() function within drivers/nvme/host/pci.c. The code failed to convert NVME_MAX_KB_SZ from kilobytes to bytes before calculating the number of required PRP entries, causing the divisor calculation to be off by a factor of 1024. This results in underestimating the number of PRP lists required; the worst case needs 2 lists but the code allocated only 1. When the driver exceeds the allocated mempool bounds, it performs out-of-bounds memory writes. The vulnerability requires specific I/O patterns (4MB transfers with exactly 127 physical segments on non-SGL-supporting queues) but has been observed in practice via kernel fence (kfence) detection. The fix converts max_bytes to the correct unit before the calculation. Patches were merged into Linux stable trees starting in early 2023.
Affected products
- Linux Linux kernel Versions prior to fix (patches backported to stable trees starting 2023-01-04)
Timeline
- 2022-12-19: disclosed: Patch authored by Keith Busch
- 2023-01-04: patched: Backported to stable trees starting linux-5.15.y and later