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 --- 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