| From bippy-5f407fcff5a0 Mon Sep 17 00:00:00 2001 |
| From: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| To: <linux-cve-announce@vger.kernel.org> |
| Reply-to: <cve@kernel.org>, <linux-kernel@vger.kernel.org> |
| Subject: CVE-2024-56644: net/ipv6: release expired exception dst cached in socket |
| |
| Description |
| =========== |
| |
| In the Linux kernel, the following vulnerability has been resolved: |
| |
| net/ipv6: release expired exception dst cached in socket |
| |
| Dst objects get leaked in ip6_negative_advice() when this function is |
| executed for an expired IPv6 route located in the exception table. There |
| are several conditions that must be fulfilled for the leak to occur: |
| * an ICMPv6 packet indicating a change of the MTU for the path is received, |
| resulting in an exception dst being created |
| * a TCP connection that uses the exception dst for routing packets must |
| start timing out so that TCP begins retransmissions |
| * after the exception dst expires, the FIB6 garbage collector must not run |
| before TCP executes ip6_negative_advice() for the expired exception dst |
| |
| When TCP executes ip6_negative_advice() for an exception dst that has |
| expired and if no other socket holds a reference to the exception dst, the |
| refcount of the exception dst is 2, which corresponds to the increment |
| made by dst_init() and the increment made by the TCP socket for which the |
| connection is timing out. The refcount made by the socket is never |
| released. The refcount of the dst is decremented in sk_dst_reset() but |
| that decrement is counteracted by a dst_hold() intentionally placed just |
| before the sk_dst_reset() in ip6_negative_advice(). After |
| ip6_negative_advice() has finished, there is no other object tied to the |
| dst. The socket lost its reference stored in sk_dst_cache and the dst is |
| no longer in the exception table. The exception dst becomes a leaked |
| object. |
| |
| As a result of this dst leak, an unbalanced refcount is reported for the |
| loopback device of a net namespace being destroyed under kernels that do |
| not contain e5f80fcf869a ("ipv6: give an IPv6 dev to blackhole_netdev"): |
| unregister_netdevice: waiting for lo to become free. Usage count = 2 |
| |
| Fix the dst leak by removing the dst_hold() in ip6_negative_advice(). The |
| patch that introduced the dst_hold() in ip6_negative_advice() was |
| 92f1655aa2b22 ("net: fix __dst_negative_advice() race"). But 92f1655aa2b22 |
| merely refactored the code with regards to the dst refcount so the issue |
| was present even before 92f1655aa2b22. The bug was introduced in |
| 54c1a859efd9f ("ipv6: Don't drop cache route entry unless timer actually |
| expired.") where the expired cached route is deleted and the sk_dst_cache |
| member of the socket is set to NULL by calling dst_negative_advice() but |
| the refcount belonging to the socket is left unbalanced. |
| |
| The IPv4 version - ipv4_negative_advice() - is not affected by this bug. |
| When the TCP connection times out ipv4_negative_advice() merely resets the |
| sk_dst_cache of the socket while decrementing the refcount of the |
| exception dst. |
| |
| The Linux kernel CVE team has assigned CVE-2024-56644 to this issue. |
| |
| |
| Affected and fixed versions |
| =========================== |
| |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 5.4.287 with commit a95808252e8acc0123bacd2dff8b9af10bc145b7 |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 5.10.231 with commit b90d061345bb8cd51fece561a800bae1c95448a6 |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 5.15.174 with commit 0b8903e6c881f72c6849d4952de742c656eb5ab9 |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 6.1.120 with commit 535add1e9f274502209cb997801208bbe1ae6c6f |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 6.6.66 with commit f43d12fd0fa8ee5b9caf8a3927e10d06431764d2 |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 6.12.5 with commit 8b591bd522b71c42a82898290e35d32b482047e4 |
| Issue introduced in 2.6.34 with commit 54c1a859efd9fd6cda05bc700315ba2519c14eba and fixed in 6.13 with commit 3301ab7d5aeb0fe270f73a3d4810c9d1b6a9f045 |
| Issue introduced in 2.6.33.2 with commit 9c93e9c757c7d3d96027a06b9b4c4e37ca87ded7 |
| |
| 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-2024-56644 |
| 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/ipv6/route.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/a95808252e8acc0123bacd2dff8b9af10bc145b7 |
| https://git.kernel.org/stable/c/b90d061345bb8cd51fece561a800bae1c95448a6 |
| https://git.kernel.org/stable/c/0b8903e6c881f72c6849d4952de742c656eb5ab9 |
| https://git.kernel.org/stable/c/535add1e9f274502209cb997801208bbe1ae6c6f |
| https://git.kernel.org/stable/c/f43d12fd0fa8ee5b9caf8a3927e10d06431764d2 |
| https://git.kernel.org/stable/c/8b591bd522b71c42a82898290e35d32b482047e4 |
| https://git.kernel.org/stable/c/3301ab7d5aeb0fe270f73a3d4810c9d1b6a9f045 |