Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2026-64109

Gravedad CVSS v3.1:
ALTA
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
19/07/2026
Última modificación:
20/07/2026

Descripción

*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> af_unix: Fix UAF read of tail-&gt;len in unix_stream_data_wait()<br /> <br /> unix_stream_data_wait() does skb_peek_tail(&amp;sk-&gt;sk_receive_queue) without<br /> holding any lock that prevents SKBs on that queue from being dequeued and<br /> freed.<br /> This has been the case since commit 79f632c71bea ("unix/stream: fix<br /> peeking with an offset larger than data in queue").<br /> The first consequence of this is that the pointer comparison<br /> `tail != last` can be false even if `last` semantically refers to an<br /> already-freed SKB while `tail` is a new SKB allocated at the same address;<br /> which can cause unix_stream_data_wait() to wrongly keep blocking after new<br /> data has arrived, but only in a weird scenario where a peeking recv() and<br /> a normal recv() on the same socket are racing, which is probably not a<br /> real problem.<br /> <br /> But since commit 2b514574f7e8 ("net: af_unix: implement splice for stream<br /> af_unix sockets"), `tail` is actually dereferenced, which can cause UAF in<br /> the following race scenario (where test_setup() runs single-threaded,<br /> and afterwards, test_thread1() and test_thread2() run concurrently in<br /> two threads:<br /> ```<br /> static int socks[2];<br /> void test_setup(void) {<br /> socketpair(AF_UNIX, SOCK_STREAM, 0, socks);<br /> send(socks[1], "A", 1, 0);<br /> int peekoff = 1;<br /> setsockopt(socks[0], SOL_SOCKET, SO_PEEK_OFF, &amp;peekoff, sizeof(peekoff));<br /> }<br /> void test_thread1(void) {<br /> char dummy;<br /> recv(socks[0], &amp;dummy, 1, MSG_PEEK);<br /> }<br /> void test_thread2(void) {<br /> char dummy;<br /> recv(socks[0], &amp;dummy, 1, 0);<br /> shutdown(socks[1], SHUT_WR);<br /> }<br /> ```<br /> <br /> when racing like this:<br /> ```<br /> thread1 thread2<br /> unix_stream_read_generic<br /> mutex_lock(&amp;u-&gt;iolock)<br /> skb_peek(&amp;sk-&gt;sk_receive_queue)<br /> skb_peek_next(skb, &amp;sk-&gt;sk_receive_queue)<br /> mutex_unlock(&amp;u-&gt;iolock)<br /> unix_stream_read_generic<br /> unix_state_lock(sk)<br /> skb_peek(&amp;sk-&gt;sk_receive_queue)<br /> unix_state_unlock(sk)<br /> unix_stream_data_wait<br /> unix_state_lock(sk)<br /> tail = skb_peek_tail(&amp;sk-&gt;sk_receive_queue)<br /> spin_lock(&amp;sk-&gt;sk_receive_queue.lock)<br /> __skb_unlink(skb, &amp;sk-&gt;sk_receive_queue)<br /> spin_unlock(&amp;sk-&gt;sk_receive_queue.lock)<br /> consume_skb(skb) [frees the SKB]<br /> `tail != last`: false<br /> `tail`: true<br /> `tail-&gt;len != last_len` ***UAF***<br /> ```<br /> <br /> Fix the UAF by removing the read of tail-&gt;len; checking tail-&gt;len would<br /> only make sense if SKBs in the receive queue of a UNIX socket could grow,<br /> which can no longer happen.<br /> <br /> Kuniyuki explained:<br /> <br /> &gt; When commit 869e7c62486e ("net: af_unix: implement stream sendpage<br /> &gt; support") added sendpage() support, data could be appended to the last<br /> &gt; skb in the receiver&amp;#39;s queue.<br /> &gt;<br /> &gt; That&amp;#39;s why we needed to check if the length of the last skb was changed<br /> &gt; while waiting for new data in unix_stream_data_wait().<br /> &gt;<br /> &gt; However, commit a0dbf5f818f9 ("af_unix: Support MSG_SPLICE_PAGES") and<br /> &gt; commit 57d44a354a43 ("unix: Convert unix_stream_sendpage() to use<br /> &gt; MSG_SPLICE_PAGES") refactored sendmsg(), and now data is always added<br /> &gt; to a new skb.<br /> <br /> That means this fix is not suitable for kernels before 6.5.