| From bippy-1.2.0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@kernel.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2025-22059: udp: Fix multiple wraparounds of sk->sk_rmem_alloc. |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| udp: Fix multiple wraparounds of sk->sk_rmem_alloc. |
| |
| __udp_enqueue_schedule_skb() has the following condition: |
| |
| if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf) |
| goto drop; |
| |
| sk->sk_rcvbuf is initialised by net.core.rmem_default and later can |
| be configured by SO_RCVBUF, which is limited by net.core.rmem_max, |
| or SO_RCVBUFFORCE. |
| |
| If we set INT_MAX to sk->sk_rcvbuf, the condition is always false |
| as sk->sk_rmem_alloc is also signed int. |
| |
| Then, the size of the incoming skb is added to sk->sk_rmem_alloc |
| unconditionally. |
| |
| This results in integer overflow (possibly multiple times) on |
| sk->sk_rmem_alloc and allows a single socket to have skb up to |
| net.core.udp_mem[1]. |
| |
| For example, if we set a large value to udp_mem[1] and INT_MAX to |
| sk->sk_rcvbuf and flood packets to the socket, we can see multiple |
| overflows: |
| |
| # cat /proc/net/sockstat | grep UDP: |
| UDP: inuse 3 mem 7956736 <-- (7956736 << 12) bytes > INT_MAX * 15 |
| ^- PAGE_SHIFT |
| # ss -uam |
| State Recv-Q ... |
| UNCONN -1757018048 ... <-- flipping the sign repeatedly |
| skmem:(r2537949248,rb2147483646,t0,tb212992,f1984,w0,o0,bl0,d0) |
| |
| Previously, we had a boundary check for INT_MAX, which was removed by |
| commit 6a1f12dd85a8 ("udp: relax atomic operation on sk->sk_rmem_alloc"). |
| |
| A complete fix would be to revert it and cap the right operand by |
| INT_MAX: |
| |
| rmem = atomic_add_return(size, &sk->sk_rmem_alloc); |
| if (rmem > min(size + (unsigned int)sk->sk_rcvbuf, INT_MAX)) |
| goto uncharge_drop; |
| |
| but we do not want to add the expensive atomic_add_return() back just |
| for the corner case. |
| |
| Casting rmem to unsigned int prevents multiple wraparounds, but we still |
| allow a single wraparound. |
| |
| # cat /proc/net/sockstat | grep UDP: |
| UDP: inuse 3 mem 524288 <-- (INT_MAX + 1) >> 12 |
| |
| # ss -uam |
| State Recv-Q ... |
| UNCONN -2147482816 ... <-- INT_MAX + 831 bytes |
| skmem:(r2147484480,rb2147483646,t0,tb212992,f3264,w0,o0,bl0,d14468947) |
| |
| So, let's define rmem and rcvbuf as unsigned int and check skb->truesize |
| only when rcvbuf is large enough to lower the overflow possibility. |
| |
| Note that we still have a small chance to see overflow if multiple skbs |
| to the same socket are processed on different core at the same time and |
| each size does not exceed the limit but the total size does. |
| |
| Note also that we must ignore skb->truesize for a small buffer as |
| explained in commit 363dc73acacb ("udp: be less conservative with |
| sock rmem accounting"). |
| |
| The Linux kernel CVE team has assigned CVE-2025-22059 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 6.10 with commit 6a1f12dd85a8b24f871dfcf467378660af9c064d and fixed in 6.12.23 with commit 94d5ad7b41122be33ebc2a6830fe710cba1ecd75 |
| Issue introduced in 6.10 with commit 6a1f12dd85a8b24f871dfcf467378660af9c064d and fixed in 6.13.11 with commit 1f529988efe9870db802cb79d01d8f473099b4d7 |
| Issue introduced in 6.10 with commit 6a1f12dd85a8b24f871dfcf467378660af9c064d and fixed in 6.14.2 with commit 7571aadd20289e9ea10ebfed0986f39ed8b3c16b |
| Issue introduced in 6.10 with commit 6a1f12dd85a8b24f871dfcf467378660af9c064d and fixed in 6.15 with commit 5a465a0da13ee9fbd7d3cd0b2893309b0fe4b7e3 |
| |
| Please see https://www.kernel.org for a full list of currently supported |
| kernel versions by the kernel community. |
| |
| Unaffected versions might change over time as fixes are backported to |
| older supported kernel versions. The official CVE entry at |
| https://cve.org/CVERecord/?id=CVE-2025-22059 |
| will be updated if fixes are backported, please check that for the most |
| up to date information about this issue. |
| |
| |
| Affected files |
| ============== |
| |
| The file(s) affected by this issue are: |
| net/ipv4/udp.c |
| |
| |
| Mitigation |
| ========== |
| |
| The Linux kernel CVE team recommends that you update to the latest |
| stable kernel version for this, and many other bugfixes. Individual |
| changes are never tested alone, but rather are part of a larger kernel |
| release. Cherry-picking individual commits is not recommended or |
| supported by the Linux kernel community at all. If however, updating to |
| the latest release is impossible, the individual changes to resolve this |
| issue can be found at these commits: |
| https://git.kernel.org/stable/c/94d5ad7b41122be33ebc2a6830fe710cba1ecd75 |
| https://git.kernel.org/stable/c/1f529988efe9870db802cb79d01d8f473099b4d7 |
| https://git.kernel.org/stable/c/7571aadd20289e9ea10ebfed0986f39ed8b3c16b |
| https://git.kernel.org/stable/c/5a465a0da13ee9fbd7d3cd0b2893309b0fe4b7e3 |