Import Source
https://github.com/microsoft/AzureLinuxVulnerabilityData/blob/main/osv/AZL-89016.json
JSON Data
https://api.osv.dev/v1/vulns/AZL-89016
Upstream
Published
2026-05-28T10:16:26Z
Modified
2026-08-28T17:46:35.796618209Z
Summary
CVE-2026-46110 affecting package kernel for versions less than 6.6.141.1-1
Details

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

net: stmmac: Prevent NULL deref when RX memory exhausted

The CPU receives frames from the MAC through conventional DMA: the CPU allocates buffers for the MAC, then the MAC fills them and returns ownership to the CPU. For each hardware RX queue, the CPU and MAC coordinate through a shared ring array of DMA descriptors: one descriptor per DMA buffer. Each descriptor includes the buffer's physical address and a status flag ("OWN") indicating which side owns the buffer: OWN=0 for CPU, OWN=1 for MAC. The CPU is only allowed to set the flag and the MAC is only allowed to clear it, and both must move through the ring in sequence: thus the ring is used for both "submissions" and "completions."

In the stmmac driver, stmmacrx() bookmarks its position in the ring with the cur_rx index. The main receive loop in that function checks for rxdescs[currx].own=0, gives the corresponding buffer to the network stack (NULLing the pointer), and increments cur_rx modulo the ring size. After the loop exits, stmmacrx_refill(), which bookmarks its position with dirty_rx, allocates fresh buffers and rearms the descriptors (setting OWN=1). If it fails any allocation, it simply stops early (leaving OWN=0) and will retry where it left off when next called.

This means descriptors have a three-stage lifecycle (terms my own): - empty (OWN=1, buffer valid) - full (OWN=0, buffer valid and populated) - dirty (OWN=0, buffer NULL)

But because stmmacrx() only checks OWN, it confuses full/dirty. In the past (see 'Fixes:'), there was a bug where the loop could cycle cur_rx all the way back to the first descriptor it dirtied, resulting in a NULL dereference when mistaken for full. The aforementioned commit resolved that specific failure by capping the loop's iteration limit at dma_rx_size - 1, but this is only a partial fix: if the previous stmmacrxrefill() didn't complete, then there are leftover dirty descriptors that the loop might encounter without needing to cycle fully around. The current code therefore panics (see 'Closes:') when stmmacrx_refill() is memory-starved long enough for cur_rx to catch up to dirty_rx.

Fix this by explicitly checking, before advancing cur_rx, if the next entry is dirty; exit the loop if so. This prevents processing of the final, used descriptor until stmmacrxrefill() succeeds, but fully prevents the cur_rx == dirty_rx ambiguity as the previous bugfix intended: so remove the clamp as well. Since stmmacrxzc() is a copy-paste-and-tweak of stmmacrx() and the code structure is identical, any fix to stmmacrx() will also need a corresponding fix for stmmacrxzc(). Therefore, apply the same check there.

In stmmacrx() (not stmmacrxzc()), a related bug remains: after the MAC sets OWN=0 on the final descriptor, it will be unable to send any further DMA-complete IRQs until it's given more empty descriptors. Currently, the driver simply hopes that the next stmmacrx_refill() succeeds, risking an indefinite stall of the receive process if not. But this is not a regression, so it can be addressed in a future change.

References

Affected packages

Azure Linux:3 / kernel

Package

Name
kernel
Purl
pkg:rpm/azure-linux/kernel

Affected ranges

Type
ECOSYSTEM
Events
Introduced
0Unknown introduced version / All previous versions are affected
Fixed
6.6.141.1-1

Database specific

source
"https://github.com/microsoft/AzureLinuxVulnerabilityData/blob/main/osv/AZL-89016.json"