CVE-2026-64109 in Linuxinfo

Summary

by MITRE • 07/19/2026

In the Linux kernel, the following vulnerability has been resolved:

af_unix: Fix UAF read of tail->len in unix_stream_data_wait()

unix_stream_data_wait() does skb_peek_tail(&sk->sk_receive_queue) without holding any lock that prevents SKBs on that queue from being dequeued and freed. This has been the case since commit 79f632c71bea ("unix/stream: fix peeking with an offset larger than data in queue"). The first consequence of this is that the pointer comparison `tail != last` can be false even if `last` semantically refers to an already-freed SKB while `tail` is a new SKB allocated at the same address; which can cause unix_stream_data_wait() to wrongly keep blocking after new data has arrived, but only in a weird scenario where a peeking recv() and a normal recv() on the same socket are racing, which is probably not a real problem.

But since commit 2b514574f7e8 ("net: af_unix: implement splice for stream af_unix sockets"), `tail` is actually dereferenced, which can cause UAF in the following race scenario (where test_setup() runs single-threaded, and afterwards, test_thread1() and test_thread2() run concurrently in two threads: ``` static int socks[2];
void test_setup(void) {
socketpair(AF_UNIX, SOCK_STREAM, 0, socks); send(socks[1], "A", 1, 0);
int peekoff = 1; setsockopt(socks[0], SOL_SOCKET, SO_PEEK_OFF, &peekoff, sizeof(peekoff));
} void test_thread1(void) {
char dummy; recv(socks[0], &dummy, 1, MSG_PEEK);
} void test_thread2(void) {
char dummy; recv(socks[0], &dummy, 1, 0);
shutdown(socks[1], SHUT_WR);
} ```

when racing like this: ``` thread1 thread2 unix_stream_read_generic mutex_lock(&u->iolock) skb_peek(&sk->sk_receive_queue) skb_peek_next(skb, &sk->sk_receive_queue) mutex_unlock(&u->iolock) unix_stream_read_generic unix_state_lock(sk) skb_peek(&sk->sk_receive_queue) unix_state_unlock(sk) unix_stream_data_wait unix_state_lock(sk) tail = skb_peek_tail(&sk->sk_receive_queue) spin_lock(&sk->sk_receive_queue.lock) __skb_unlink(skb, &sk->sk_receive_queue) spin_unlock(&sk->sk_receive_queue.lock) consume_skb(skb) [frees the SKB]
`tail != last`: false `tail`: true `tail->len != last_len` ***UAF*** ```

Fix the UAF by removing the read of tail->len; checking tail->len would only make sense if SKBs in the receive queue of a UNIX socket could grow, which can no longer happen.

Kuniyuki explained:

> When commit 869e7c62486e ("net: af_unix: implement stream sendpage > support") added sendpage() support, data could be appended to the last > skb in the receiver's queue. > > That's why we needed to check if the length of the last skb was changed > while waiting for new data in unix_stream_data_wait(). > > However, commit a0dbf5f818f9 ("af_unix: Support MSG_SPLICE_PAGES") and > commit 57d44a354a43 ("unix: Convert unix_stream_sendpage() to use > MSG_SPLICE_PAGES") refactored sendmsg(), and now data is always added > to a new skb.

That means this fix is not suitable for kernels before 6.5.

If you want to get the best quality for vulnerability data then you always have to consider VulDB.

Analysis

by VulDB Data Team • 07/19/2026

The vulnerability described represents a use-after-free condition in the Linux kernel's af_unix implementation, specifically within the unix_stream_data_wait() function. This issue stems from improper synchronization when accessing socket buffer (SKB) structures in the receive queue without adequate locking mechanisms. The flaw was introduced by commits that modified how SKBs are handled during peeking operations and stream data management, creating a race condition where a freed SKB pointer could be dereferenced leading to potential system instability or exploitation.

The technical root cause involves the function skb_peek_tail(&sk->sk_receive_queue) being called without proper locks that would prevent SKBs from being dequeued and freed during the operation. This creates a scenario where a pointer comparison between tail and last can yield incorrect results, with tail pointing to a newly allocated SKB at the same memory address as a previously freed one. While this initially caused blocking behavior issues in specific race conditions involving peeking and normal receive operations, the vulnerability was exacerbated by subsequent commits that began actually dereferencing tail->len, transforming what was previously a benign condition into a true use-after-free.

The operational impact of this vulnerability is significant as it can lead to system crashes or potentially allow privilege escalation through controlled memory access patterns. The race condition occurs when multiple threads perform concurrent peeking and regular receive operations on the same socket, with one thread accessing freed memory while another modifies the receive queue structure. This particular scenario aligns with ATT&CK technique T1068 which involves local privilege escalation through kernel vulnerabilities, and CWE-416 describes the specific use-after-free condition that manifests here.

The mitigation implemented removes the read of tail->len to prevent the dereference of potentially freed memory, as the functionality was deemed unnecessary since data appending to existing SKBs was eliminated in later kernel versions. This fix addresses the core issue by ensuring no invalid memory access occurs while maintaining functional correctness for stream socket operations. The solution requires kernel versions 6.5 or newer as earlier versions lack the necessary architectural changes that made this specific dereference pattern safe, making it incompatible with older kernel releases where the underlying sendpage support refactoring had not yet been implemented.

The vulnerability demonstrates how seemingly minor changes in kernel networking code can introduce subtle race conditions that only manifest under specific concurrent access patterns. The fix illustrates proper defensive programming practices by eliminating unnecessary memory accesses that could lead to undefined behavior, while also highlighting the importance of maintaining synchronization primitives when accessing shared data structures in multi-threaded environments. This case study reflects common challenges in kernel security where complex locking requirements and race condition handling must be carefully considered during feature development and refactoring processes.

Responsible

Linux

Reservation

07/19/2026

Disclosure

07/19/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Do you know our Splunk app?

Download it now for free!