CVE-2026-23394

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
25/03/2026
Last modified:
25/03/2026

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> af_unix: Give up GC if MSG_PEEK intervened.<br /> <br /> Igor Ushakov reported that GC purged the receive queue of<br /> an alive socket due to a race with MSG_PEEK with a nice repro.<br /> <br /> This is the exact same issue previously fixed by commit<br /> cbcf01128d0a ("af_unix: fix garbage collect vs MSG_PEEK").<br /> <br /> After GC was replaced with the current algorithm, the cited<br /> commit removed the locking dance in unix_peek_fds() and<br /> reintroduced the same issue.<br /> <br /> The problem is that MSG_PEEK bumps a file refcount without<br /> interacting with GC.<br /> <br /> Consider an SCC containing sk-A and sk-B, where sk-A is<br /> close()d but can be recv()ed via sk-B.<br /> <br /> The bad thing happens if sk-A is recv()ed with MSG_PEEK from<br /> sk-B and sk-B is close()d while GC is checking unix_vertex_dead()<br /> for sk-A and sk-B.<br /> <br /> GC thread User thread<br /> --------- -----------<br /> unix_vertex_dead(sk-A)<br /> -&gt; true sk-A&amp;#39;s file refcount : 1 -&gt; 2<br /> <br /> close(sk-B)<br /> -&gt; sk-B&amp;#39;s file refcount : 2 -&gt; 1<br /> unix_vertex_dead(sk-B)<br /> -&gt; true<br /> <br /> Initially, sk-A&amp;#39;s file refcount is 1 by the inflight fd in sk-B<br /> recvq. GC thinks sk-A is dead because the file refcount is the<br /> same as the number of its inflight fds.<br /> <br /> However, sk-A&amp;#39;s file refcount is bumped silently by MSG_PEEK,<br /> which invalidates the previous evaluation.<br /> <br /> At this moment, sk-B&amp;#39;s file refcount is 2; one by the open fd,<br /> and one by the inflight fd in sk-A. The subsequent close()<br /> releases one refcount by the former.<br /> <br /> Finally, GC incorrectly concludes that both sk-A and sk-B are dead.<br /> <br /> One option is to restore the locking dance in unix_peek_fds(),<br /> but we can resolve this more elegantly thanks to the new algorithm.<br /> <br /> The point is that the issue does not occur without the subsequent<br /> close() and we actually do not need to synchronise MSG_PEEK with<br /> the dead SCC detection.<br /> <br /> When the issue occurs, close() and GC touch the same file refcount.<br /> If GC sees the refcount being decremented by close(), it can just<br /> give up garbage-collecting the SCC.<br /> <br /> Therefore, we only need to signal the race during MSG_PEEK with<br /> a proper memory barrier to make it visible to the GC.<br /> <br /> Let&amp;#39;s use seqcount_t to notify GC when MSG_PEEK occurs and let<br /> it defer the SCC to the next run.<br /> <br /> This way no locking is needed on the MSG_PEEK side, and we can<br /> avoid imposing a penalty on every MSG_PEEK unnecessarily.<br /> <br /> Note that we can retry within unix_scc_dead() if MSG_PEEK is<br /> detected, but we do not do so to avoid hung task splat from<br /> abusive MSG_PEEK calls.

Impact