CVE-2024-56644
Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
27/12/2024
Last modified:
27/12/2024
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
net/ipv6: release expired exception dst cached in socket<br />
<br />
Dst objects get leaked in ip6_negative_advice() when this function is<br />
executed for an expired IPv6 route located in the exception table. There<br />
are several conditions that must be fulfilled for the leak to occur:<br />
* an ICMPv6 packet indicating a change of the MTU for the path is received,<br />
resulting in an exception dst being created<br />
* a TCP connection that uses the exception dst for routing packets must<br />
start timing out so that TCP begins retransmissions<br />
* after the exception dst expires, the FIB6 garbage collector must not run<br />
before TCP executes ip6_negative_advice() for the expired exception dst<br />
<br />
When TCP executes ip6_negative_advice() for an exception dst that has<br />
expired and if no other socket holds a reference to the exception dst, the<br />
refcount of the exception dst is 2, which corresponds to the increment<br />
made by dst_init() and the increment made by the TCP socket for which the<br />
connection is timing out. The refcount made by the socket is never<br />
released. The refcount of the dst is decremented in sk_dst_reset() but<br />
that decrement is counteracted by a dst_hold() intentionally placed just<br />
before the sk_dst_reset() in ip6_negative_advice(). After<br />
ip6_negative_advice() has finished, there is no other object tied to the<br />
dst. The socket lost its reference stored in sk_dst_cache and the dst is<br />
no longer in the exception table. The exception dst becomes a leaked<br />
object.<br />
<br />
As a result of this dst leak, an unbalanced refcount is reported for the<br />
loopback device of a net namespace being destroyed under kernels that do<br />
not contain e5f80fcf869a ("ipv6: give an IPv6 dev to blackhole_netdev"):<br />
unregister_netdevice: waiting for lo to become free. Usage count = 2<br />
<br />
Fix the dst leak by removing the dst_hold() in ip6_negative_advice(). The<br />
patch that introduced the dst_hold() in ip6_negative_advice() was<br />
92f1655aa2b22 ("net: fix __dst_negative_advice() race"). But 92f1655aa2b22<br />
merely refactored the code with regards to the dst refcount so the issue<br />
was present even before 92f1655aa2b22. The bug was introduced in<br />
54c1a859efd9f ("ipv6: Don&#39;t drop cache route entry unless timer actually<br />
expired.") where the expired cached route is deleted and the sk_dst_cache<br />
member of the socket is set to NULL by calling dst_negative_advice() but<br />
the refcount belonging to the socket is left unbalanced.<br />
<br />
The IPv4 version - ipv4_negative_advice() - is not affected by this bug.<br />
When the TCP connection times out ipv4_negative_advice() merely resets the<br />
sk_dst_cache of the socket while decrementing the refcount of the<br />
exception dst.
Impact
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/0b8903e6c881f72c6849d4952de742c656eb5ab9
- https://git.kernel.org/stable/c/3301ab7d5aeb0fe270f73a3d4810c9d1b6a9f045
- https://git.kernel.org/stable/c/535add1e9f274502209cb997801208bbe1ae6c6f
- https://git.kernel.org/stable/c/8b591bd522b71c42a82898290e35d32b482047e4
- https://git.kernel.org/stable/c/a95808252e8acc0123bacd2dff8b9af10bc145b7
- https://git.kernel.org/stable/c/b90d061345bb8cd51fece561a800bae1c95448a6
- https://git.kernel.org/stable/c/f43d12fd0fa8ee5b9caf8a3927e10d06431764d2