CVE-2025-40214

Severity CVSS v4.0:
Pending analysis
Type:
Unavailable / Other
Publication date:
04/12/2025
Last modified:
04/12/2025

Description

In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> af_unix: Initialise scc_index in unix_add_edge().<br /> <br /> Quang Le reported that the AF_UNIX GC could garbage-collect a<br /> receive queue of an alive in-flight socket, with a nice repro.<br /> <br /> The repro consists of three stages.<br /> <br /> 1)<br /> 1-a. Create a single cyclic reference with many sockets<br /> 1-b. close() all sockets<br /> 1-c. Trigger GC<br /> <br /> 2)<br /> 2-a. Pass sk-A to an embryo sk-B<br /> 2-b. Pass sk-X to sk-X<br /> 2-c. Trigger GC<br /> <br /> 3)<br /> 3-a. accept() the embryo sk-B<br /> 3-b. Pass sk-B to sk-C<br /> 3-c. close() the in-flight sk-A<br /> 3-d. Trigger GC<br /> <br /> As of 2-c, sk-A and sk-X are linked to unix_unvisited_vertices,<br /> and unix_walk_scc() groups them into two different SCCs:<br /> <br /> unix_sk(sk-A)-&gt;vertex-&gt;scc_index = 2 (UNIX_VERTEX_INDEX_START)<br /> unix_sk(sk-X)-&gt;vertex-&gt;scc_index = 3<br /> <br /> Once GC completes, unix_graph_grouped is set to true.<br /> Also, unix_graph_maybe_cyclic is set to true due to sk-X&amp;#39;s<br /> cyclic self-reference, which makes close() trigger GC.<br /> <br /> At 3-b, unix_add_edge() allocates unix_sk(sk-B)-&gt;vertex and<br /> links it to unix_unvisited_vertices.<br /> <br /> unix_update_graph() is called at 3-a. and 3-b., but neither<br /> unix_graph_grouped nor unix_graph_maybe_cyclic is changed<br /> because both sk-B&amp;#39;s listener and sk-C are not in-flight.<br /> <br /> 3-c decrements sk-A&amp;#39;s file refcnt to 1.<br /> <br /> Since unix_graph_grouped is true at 3-d, unix_walk_scc_fast()<br /> is finally called and iterates 3 sockets sk-A, sk-B, and sk-X:<br /> <br /> sk-A -&gt; sk-B (-&gt; sk-C)<br /> sk-X -&gt; sk-X<br /> <br /> This is totally fine. All of them are not yet close()d and<br /> should be grouped into different SCCs.<br /> <br /> However, unix_vertex_dead() misjudges that sk-A and sk-B are<br /> in the same SCC and sk-A is dead.<br /> <br /> unix_sk(sk-A)-&gt;scc_index == unix_sk(sk-B)-&gt;scc_index vertex-&gt;out_degree<br /> ^-- 1 in-flight count for sk-B<br /> -&gt; sk-A is dead !?<br /> <br /> The problem is that unix_add_edge() does not initialise scc_index.<br /> <br /> Stage 1) is used for heap spraying, making a newly allocated<br /> vertex have vertex-&gt;scc_index == 2 (UNIX_VERTEX_INDEX_START)<br /> set by unix_walk_scc() at 1-c.<br /> <br /> Let&amp;#39;s track the max SCC index from the previous unix_walk_scc()<br /> call and assign the max + 1 to a new vertex&amp;#39;s scc_index.<br /> <br /> This way, we can continue to avoid Tarjan&amp;#39;s algorithm while<br /> preventing misjudgments.

Impact