[PATCH 3/3] af_unix: prevent spurious reader wakeups by writer
From: Jann Horn
Date: Fri May 15 2026 - 14:56:49 EST
Currently, a blocking recv() on a unix stream socket will wake up every
time an SKB that was sent from the socket is consumed by the peer.
So, in a synchronous communication scenario where the client sends a
message to the server, and then the client blocks in recv() until it
receives a reply from the server, the client will get a spurious wakeup
when the server receives the client's message.
Similar to other receive paths such as __skb_wait_for_more_packets(), use
DEFINE_WAIT_FUNC() to filter wakeups.
Signed-off-by: Jann Horn <jannh@xxxxxxxxxx>
---
net/unix/af_unix.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index b38804e2c5ac..f36ab3e5a5bb 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2707,6 +2707,14 @@ static int unix_read_skb(struct sock *sk, skb_read_actor_t recv_actor)
return recv_actor(sk, skb);
}
+static int unix_recv_wake(wait_queue_entry_t *wait, unsigned int mode,
+ int sync, void *key)
+{
+ if (key && !(key_to_poll(key) & (EPOLLIN | EPOLLERR)))
+ return 0;
+ return autoremove_wake_function(wait, mode, sync, key);
+}
+
/*
* Sleep until more data has arrived. But check for races..
*/
@@ -2715,7 +2723,7 @@ __releases(&unix_sk(sk)->iolock)
__releases(&unix_sk(sk)->lock)
{
unsigned int state = TASK_INTERRUPTIBLE | freezable * TASK_FREEZABLE;
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, unix_recv_wake);
prepare_to_wait(sk_sleep(sk), &wait, state);
unix_state_unlock(sk);
--
2.54.0.563.g4f69b47b94-goog