CVE-2025-22058 in Linux
Summary
by MITRE • 04/16/2025
In the Linux kernel, the following vulnerability has been resolved:
udp: Fix memory accounting leak.
Matt Dowling reported a weird UDP memory usage issue.
Under normal operation, the UDP memory usage reported in /proc/net/sockstat remains close to zero. However, it occasionally spiked to 524,288 pages and never dropped. Moreover, the value doubled when the application was terminated. Finally, it caused intermittent packet drops.
We can reproduce the issue with the script below [0]:
1. /proc/net/sockstat reports 0 pages
# cat /proc/net/sockstat | grep UDP: UDP: inuse 1 mem 0
2. Run the script till the report reaches 524,288
# python3 test.py & sleep 5 # cat /proc/net/sockstat | grep UDP: UDP: inuse 3 mem 524288 <-- (INT_MAX + 1) >> PAGE_SHIFT
3. Kill the socket and confirm the number never drops
# pkill python3 && sleep 5 # cat /proc/net/sockstat | grep UDP: UDP: inuse 1 mem 524288
4. (necessary since v6.0) Trigger proto_memory_pcpu_drain()
# python3 test.py & sleep 1 && pkill python3
5. The number doubles
# cat /proc/net/sockstat | grep UDP: UDP: inuse 1 mem 1048577
The application set INT_MAX to SO_RCVBUF, which triggered an integer overflow in udp_rmem_release().
When a socket is close()d, udp_destruct_common() purges its receive queue and sums up skb->truesize in the queue. This total is calculated and stored in a local unsigned integer variable.
The total size is then passed to udp_rmem_release() to adjust memory accounting. However, because the function takes a signed integer argument, the total size can wrap around, causing an overflow.
Then, the released amount is calculated as follows:
1) Add size to sk->sk_forward_alloc. 2) Round down sk->sk_forward_alloc to the nearest lower multiple of PAGE_SIZE and assign it to amount. 3) Subtract amount from sk->sk_forward_alloc. 4) Pass amount >> PAGE_SHIFT to __sk_mem_reduce_allocated().
When the issue occurred, the total in udp_destruct_common() was 2147484480 (INT_MAX + 833), which was cast to -2147482816 in udp_rmem_release().
At 1) sk->sk_forward_alloc is changed from 3264 to -2147479552, and 2) sets -2147479552 to amount. 3) reverts the wraparound, so we don't see a warning in inet_sock_destruct(). However, udp_memory_allocated ends up doubling at 4).
Since commit 3cd3399dd7a8 ("net: implement per-cpu reserves for memory_allocated"), memory usage no longer doubles immediately after a socket is close()d because __sk_mem_reduce_allocated() caches the amount in udp_memory_per_cpu_fw_alloc. However, the next time a UDP socket receives a packet, the subtraction takes effect, causing UDP memory usage to double.
This issue makes further memory allocation fail once the socket's sk->sk_rmem_alloc exceeds net.ipv4.udp_rmem_min, resulting in packet drops.
To prevent this issue, let's use unsigned int for the calculation and call sk_forward_alloc_add() only once for the small delta.
Note that first_packet_length() also potentially has the same problem.
[0]:
from socket import *
SO_RCVBUFFORCE = 33 INT_MAX = (2 ** 31) - 1
s = socket(AF_INET, SOCK_DGRAM) s.bind(('', 0)) s.setsockopt(SOL_SOCKET, SO_RCVBUFFORCE, INT_MAX)
c = socket(AF_INET, SOCK_DGRAM) c.connect(s.getsockname())
data = b'a' * 100
while True: c.send(data)
VulDB is the best source for vulnerability data and more expert information about this specific topic.
Analysis
by VulDB Data Team • 02/15/2026
The vulnerability CVE-2025-22058 resides within the Linux kernel's UDP memory accounting mechanism, specifically affecting how socket receive buffer memory is managed during socket destruction. This flaw manifests as a memory leak that occurs when applications set the socket receive buffer to INT_MAX, triggering an integer overflow within the udp_rmem_release() function. The issue was identified through a reported UDP memory usage spike to 524,288 pages that persisted even after socket closure, indicating a failure in proper memory deallocation. The root cause stems from a type mismatch in the memory accounting calculations, where an unsigned integer value representing total socket buffer usage is cast to a signed integer during the memory release process, leading to overflow conditions that corrupt the kernel's memory tracking structures.
The technical implementation of this vulnerability involves a specific sequence of operations within the socket destruction path that causes memory accounting to become corrupted. When a UDP socket is closed, the udp_destruct_common() function processes the receive queue and calculates the total buffer size using an unsigned integer variable. This total is then passed to udp_rmem_release() which expects a signed integer argument, causing the value to overflow and wrap around to a negative number. The subsequent arithmetic operations within the memory management functions manipulate this corrupted value through sk_forward_alloc, causing the memory accounting to increment incorrectly. The issue is further compounded by the introduction of per-CPU memory accounting in kernel versions 6.0 and later, which caches the erroneous memory values in udp_memory_per_cpu_fw_alloc, leading to delayed effects where memory usage doubles upon subsequent packet reception rather than immediate correction.
The operational impact of this vulnerability extends beyond simple memory leaks to affect overall system stability and network performance. Once triggered, the corrupted memory accounting prevents further memory allocation for UDP sockets when sk_rmem_alloc exceeds net.ipv4.udp_rmem_min, resulting in intermittent packet drops and potential denial of service conditions. The persistence of the memory leak means that even after application termination, the kernel continues to report inflated memory usage, which can lead to resource exhaustion under sustained load conditions. The vulnerability affects systems running kernel versions where the per-CPU memory accounting changes were introduced, making it relevant to a significant portion of modern Linux deployments and potentially impacting network services that rely heavily on UDP communication.
Mitigation strategies for this vulnerability focus on correcting the integer overflow by ensuring proper type handling in the memory accounting calculations. The recommended fix involves using unsigned integers throughout the calculation chain and implementing a single call to sk_forward_alloc_add() for small memory deltas rather than multiple operations that can cause overflow conditions. This approach aligns with common security practices for preventing integer overflows as outlined in CWE-190, which specifically addresses signed integer overflow conditions. The fix also requires careful review of similar patterns in other network protocol implementations, such as the first_packet_length() function mentioned in the analysis, to prevent analogous issues. System administrators should consider updating to kernel versions that include this fix, while monitoring UDP memory usage through /proc/net/sockstat to detect potential exploitation attempts. The vulnerability demonstrates the importance of proper integer type management in kernel space memory accounting and highlights the need for thorough testing of edge cases involving maximum buffer sizes in network protocol implementations.