From nobody Mon May 25 08:12:39 2026 Received: from mail-wm1-f45.google.com (mail-wm1-f45.google.com [209.85.128.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 04C662F7EF2 for ; Fri, 15 May 2026 18:54:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778871266; cv=none; b=t4KgE9J69xezodeUiQaH4WaS1LMiT4PW17eU6izQCEyKqXOSO7JfSnH0xR5IMTLGTlZo+tJaDmUz+kdtGu5S8G+IvLcx83wdgBVRDtKrxTDJCf0Zmzqzo9124KmN10INSFQNd5sE/ZDsEYLk+iyTxiKQn0GbsLEoNPnx8ckaPic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778871266; c=relaxed/simple; bh=1ep5ZLVgq0P6ZOuRIHNhve6Q35NR/xV4JtQP4fUWqVQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=dNTi6Q/mh1plKQCcQimJqKrbn+U72Bkxan/MRojYrGMTiPlI0Zcq4KRjkEKQ7pGSYRdxqfu4C3AR3+M4GlBn0T41wiXlHOLXuqXrIoNz2JWQ6XudC0I3rumzIKS97fGWGabG+sTyf5PJYiiTuPTBd8apba24s06piUN0BPz2STE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=e5Cnek7F; arc=none smtp.client-ip=209.85.128.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="e5Cnek7F" Received: by mail-wm1-f45.google.com with SMTP id 5b1f17b1804b1-4891ca4ce02so2655e9.1 for ; Fri, 15 May 2026 11:54:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1778871262; x=1779476062; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=SuHPlWmIOJ+p8xvCO2qGzAHb3LeLHxGU5jkoCFo5buk=; b=e5Cnek7FNN6wB4gRgZEqeaHt5Oi9Uz0dym7Vn4/rOHsyReunpz3VaS7I5UaZCOtEII Lb8gFFmw7i3jvifD7lfHnLXvxTl+pF6BqE4sJMXkg1gTQiNCVwiKg/rTQ8Zjn2r7lwlf pE1NcaFm5ycl1MJHrjnEiAbGLssOcteP2fxphlIMaVnkKAf+2lptTedpmD8ew1boUU7h rRoKD2CX4lyuCZj5P7/j8r/UtBalHpi44oHPLCeB1Ey/lRoM6ksLhF9OnVbSw7gjQT79 7yZZLMzI0cb0Upc3dxEV7s5nWNUgrEruffQtWSd0mQnkqkPv9ZJARAkSskbS5hzU1hps sZKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778871262; x=1779476062; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=SuHPlWmIOJ+p8xvCO2qGzAHb3LeLHxGU5jkoCFo5buk=; b=ZPsZOlaGcii7mqdFgIw0Df9Id7x5kaXiu4bCQpQ/5y/XwApIgz3C/KVqRWNz6RTzxG 0oY0z1G1IFKAh2Q/fweLLsYy3TcUavcue0ImwzlSMR/wSbz1OacyDXAf0/CvtDEvyCkM XyHw4MgzDPbuQQ8LJ+op9J6PikDx+cpwqMVzr87XdppbZWFsBJQ355M+fmLIaJ9wFCXi Y7R4EJTVEIWuSVpyTpSfe4HGxBhIn1LVMnwG34xqiJwMiYjuv2VVKjYIzFQPh9iuhUtN hffKhDYIs1Fyrgn6x2vLdzv5rRzaP8B+X4wkVmiRuCdqQtf/L1cFp6PLZBcOMZb845Xj ScpA== X-Forwarded-Encrypted: i=1; AFNElJ/jGw376YZteeODA6gABE6xaehIoz/ZQNAFBXZRJ5e6gF674EX2T2qF5i61xQjvkq0FPIhJqfKZ0oT0PuI=@vger.kernel.org X-Gm-Message-State: AOJu0YzL7WUB3e8/3IExK+YeUtOc84iEimOQAwj/vKbZfej2/OIf+pfg f1xjgP2GDtQeNPO/1gkLnoOXuHLKBG0Kd/8TF03SRU3zOg1xsUsIic0eK6F9miTd4A== X-Gm-Gg: Acq92OFxWLjgd7NsKERCMd/ALIbIEeA+yEkaIAXm6XLWz2twkHyOXGmZGX06xSbQFal CUilv5zCWLqjDkDzN5XPyO/xOZMHdokPUGk6TS8EcXZn/LA+jIVJW0PhJvGajj+MLwrQ1EbuFKw JZRzSjkri2gT/mJY4zVM0ofuwZIqcdNHLudbOlLpEI0UVFHov6bBeAkh9POXhh5cJ+yiZOsbUXM X6s4mXpy4qQyEWR7SgAQZhpNDPt1UFeEwWZ4UBtxiOArvfCYI+KMMNSstiPPs3JY3vYTYdZ+HUx yRI0UU7wdGeaI2eyrXZT5nwThK6Nupk5XpBOQ6dpEbeSr2lg00TTHNt7XeSWHAvS/SC74YJU++w LyTFrn2uQeeAP9hp8brI9uCdWhiLiWsGYAbP5IkTqwTl+MFKQGceJ4yst+3908qT5Ql0J4FTiGa RaViVal4hZIdilrko6pA6M5p0imJ2QNBTYx/ssc46zpSbNyBOw3rfeuXPAtK7SeQ== X-Received: by 2002:a05:600c:4ed3:b0:48f:de33:777a with SMTP id 5b1f17b1804b1-48ff4c84507mr85275e9.11.1778871261929; Fri, 15 May 2026 11:54:21 -0700 (PDT) Received: from localhost ([2a00:79e0:288a:8:7481:4dac:8e80:6e9b]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48fe57943b2sm79586725e9.8.2026.05.15.11.54.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 11:54:21 -0700 (PDT) From: Jann Horn Date: Fri, 15 May 2026 20:54:08 +0200 Subject: [PATCH 1/3] af_unix: Fix UAF read of tail->len in unix_stream_data_wait() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-unix-recv-wait-v1-1-76adb5f063d5@google.com> References: <20260515-unix-recv-wait-v1-0-76adb5f063d5@google.com> In-Reply-To: <20260515-unix-recv-wait-v1-0-76adb5f063d5@google.com> To: Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: Hannes Frederic Sowa , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Jann Horn , stable@vger.kernel.org X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=ed25519-sha256; t=1778871255; l=5214; i=jannh@google.com; s=20240730; h=from:subject:message-id; bh=1ep5ZLVgq0P6ZOuRIHNhve6Q35NR/xV4JtQP4fUWqVQ=; b=biFR0H5BnKM6bLseIWGzRNTfIvRlm/vD4ABNpEGL50UdomtRVOj4eqEfC+9PyYKMKMdKTjh0A rAlLz7dcLkAC2zvT+3nOa1m74jTU89NiW9kWrw5r0IALbjgMEdzGlgb X-Developer-Key: i=jannh@google.com; a=ed25519; pk=AljNtGOzXeF6khBXDJVVvwSEkVDGnnZZYqfWhP1V+C8= 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 !=3D 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 =3D 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 =3D 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 !=3D last`: false `tail`: true `tail->len !=3D 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 AFAIK is not supposed to happen. Fixes: 2b514574f7e8 ("net: af_unix: implement splice for stream af_unix soc= kets") Cc: stable@vger.kernel.org Signed-off-by: Jann Horn --- net/unix/af_unix.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1cbf36ea043b..dc71ed79be4a 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2711,8 +2711,7 @@ static int unix_read_skb(struct sock *sk, skb_read_ac= tor_t recv_actor) * Sleep until more data has arrived. But check for races.. */ static long unix_stream_data_wait(struct sock *sk, long timeo, - struct sk_buff *last, unsigned int last_len, - bool freezable) + struct sk_buff *last, bool freezable) { unsigned int state =3D TASK_INTERRUPTIBLE | freezable * TASK_FREEZABLE; struct sk_buff *tail; @@ -2725,7 +2724,6 @@ static long unix_stream_data_wait(struct sock *sk, lo= ng timeo, =20 tail =3D skb_peek_tail(&sk->sk_receive_queue); if (tail !=3D last || - (tail && tail->len !=3D last_len) || sk->sk_err || (sk->sk_shutdown & RCV_SHUTDOWN) || signal_pending(current) || @@ -2921,7 +2919,6 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, int flags =3D state->flags; bool check_creds =3D false; struct scm_cookie scm; - unsigned int last_len; struct unix_sock *u; int copied =3D 0; int err =3D 0; @@ -2967,7 +2964,6 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, goto unlock; } last =3D skb =3D skb_peek(&sk->sk_receive_queue); - last_len =3D last ? last->len : 0; =20 again: #if IS_ENABLED(CONFIG_AF_UNIX_OOB) @@ -3001,8 +2997,7 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, =20 mutex_unlock(&u->iolock); =20 - timeo =3D unix_stream_data_wait(sk, timeo, last, - last_len, freezable); + timeo =3D unix_stream_data_wait(sk, timeo, last, freezable); =20 if (signal_pending(current)) { err =3D sock_intr_errno(timeo); @@ -3019,7 +3014,6 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, while (skip >=3D unix_skb_len(skb)) { skip -=3D unix_skb_len(skb); last =3D skb; - last_len =3D skb->len; skb =3D skb_peek_next(skb, &sk->sk_receive_queue); if (!skb) goto again; @@ -3094,7 +3088,6 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, =20 skip =3D 0; last =3D skb; - last_len =3D skb->len; unix_state_lock(sk); skb =3D skb_peek_next(skb, &sk->sk_receive_queue); if (skb) --=20 2.54.0.563.g4f69b47b94-goog From nobody Mon May 25 08:12:39 2026 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 90B0C37DAD7 for ; Fri, 15 May 2026 18:54:26 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778871271; cv=none; b=r3AY88+tgwwZINm8oVKtAdoJmPdWx//EACKRYQ0ygolzEaiwODosv4pBIqHLDd7V2GasJ4dtMR/u4S6ChbZAnJI+swFZ56eoE7MkbF7QJ0OgimJyGovr+KuE9mMo7Ld1tZa6ABVCt5ubUViICJ6DF26euQeTmWsWCnOf68sw0OE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778871271; c=relaxed/simple; bh=5eaIm7oQrXrv26FV2waWzgjgidPzic9XkF5iTxDoZAA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=kBYWAFvI27IAYSj9kxFVnCN3tvsVZbGXfccgoICRfQwprMKpo8N/t+HioNxWcxo22ogvqzUu/w8z4cNdfiSgWIcxQdl9RHEAa7YDZJoRf+Ii9pdlCP3Onkpqs41t1vjjuP+v+HckwWHY1BqYMmS5vjIwzs2p5FhpqiDLusEeo8I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=YTN8QEiG; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="YTN8QEiG" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-4891b4934ffso1015e9.0 for ; Fri, 15 May 2026 11:54:26 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1778871265; x=1779476065; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=PNFlWNxHBBoOTkz1i9JncC0yIj0DqDbA8cq/UI1Bf44=; b=YTN8QEiGHHdnprLQd4QF4cecW35GhQVlLJOKOfrlbUIpLU3YETnSZ7SAZ75pD4+xLU JE95jMSsbzu7tvXxTEblYm67ZGMfe/XDBqYu9l9KCvf94QEbwgn2mVSnf+QDmBdO6yUu /JOROf/9RRxy4kRG2d2LLjwPrLrWHvN98DT8Q3xowg5Z5J4Q3BrqkQT6/2faP8j/N7Ei Bkmoa7IdWTvOBsy91glQdiElDn7pmakZxbVgrfE5WsA1HFEnVXh9HICSaz3ZGAusL6aT x5ftNRrsF4nOV+5ATj3tUzsa8cqi5nQRNxo4u2VEaaPgDJlirOcYBlnOy7ES2iFNLF+o f8Ow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778871265; x=1779476065; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=PNFlWNxHBBoOTkz1i9JncC0yIj0DqDbA8cq/UI1Bf44=; b=Xy+DLttQi7OB1THssnyfndt+/OeBTFA62jkWmFouDyqXvIitXi8GJPrVYrSQirKWoV WlYcWJX7jFTL8RVBxYldIa2l+bmrjcVERz/+iFlE7IeDCJIkBNj2iy60oDHVInsfdaAo dQO0qCV34XByODM4qlrKVQrMmsA3s0GMdbk96sNaGpptGwcJGTXRvc3/XzUCfJDKIEql 4w39TfGE3utTiKmHY69UhGU+pN4ELvv6wTWS035SwlW0O2rP2HLsTHDp2mMAY+Bviktq iB9fc8qnRidYGAzoO2BpWgRR/6tynk0edoQ7PNvdt6uUtoWovIYraBjc7FQK1ZtsbWes OtzQ== X-Forwarded-Encrypted: i=1; AFNElJ+qU6PzXpjQh5uuhyv5RJMmZwstgGkkFHKjRzojD4aPTN5ZpjpzdLKLQbOIXKB5WniO3LpKGfhsGwbETf8=@vger.kernel.org X-Gm-Message-State: AOJu0YxKj9+bjjRwTKE1uUq3kJ+1thmPKr2QwPeo8AuPRlhc2EiiGFSZ KZTHrfFxEdcv7+VfwyS62mPSckJpViXt3OabFbV6Om0uNIbJke56IO4LoG7sc+HLRA== X-Gm-Gg: Acq92OFP9VJJHIMgDXEbZulT6MXYaQTBj7tSyqKBLfwkHrrlm1YPlXvnKn7qzLVUZbX Lhse7GB53D05PoLzsZipPWT9fXxcMygv49uE40F7f5xFo2/EzlzovrP0tNHkgvHwbzwBortVjbV FCXI2akf9Qp3zREFhVjvpAdc584VO1zM1H6YGg6eETu/E/ZwWr597pdrbel6RLGHcaUs+1Hq51b kFOfrVqIK5VBYfoYR7TyRz5dHNPnh51gEclpFJ70U9M2zF7oLg5JVMqc3rKDNqp3cgivr+aaPZk H1ogPaD8TCgYEgnkio+YCSPsvopN0zRRA9kEvQTDrmcJMu4Ck+MnaCo8QvVtPpaSa1CYy18DPoV WRzrvC5lnMVbyL1he1dAFSzJh5ho9TgUbPnf8oPw0kqgWbexow8NDiAFkO9sCgmy1/w8muUc5Xz nIINDNtbFQEDmC3oYzBFYx1CEvdfQznEepR+L/ZeK9Nk00v9x/UdmbDBQ5FVmtVQ== X-Received: by 2002:a05:600c:605a:b0:48a:55dc:9c1e with SMTP id 5b1f17b1804b1-48ff4b2c3bfmr64135e9.10.1778871264521; Fri, 15 May 2026 11:54:24 -0700 (PDT) Received: from localhost ([2a00:79e0:288a:8:7481:4dac:8e80:6e9b]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48febe79ce3sm20112695e9.31.2026.05.15.11.54.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 11:54:24 -0700 (PDT) From: Jann Horn Date: Fri, 15 May 2026 20:54:09 +0200 Subject: [PATCH 2/3] af_unix: Simplify unix_stream_data_wait() Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-unix-recv-wait-v1-2-76adb5f063d5@google.com> References: <20260515-unix-recv-wait-v1-0-76adb5f063d5@google.com> In-Reply-To: <20260515-unix-recv-wait-v1-0-76adb5f063d5@google.com> To: Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: Hannes Frederic Sowa , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Jann Horn X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=ed25519-sha256; t=1778871255; l=4212; i=jannh@google.com; s=20240730; h=from:subject:message-id; bh=5eaIm7oQrXrv26FV2waWzgjgidPzic9XkF5iTxDoZAA=; b=6VwkbRKbXyM57UZcd+u9NRFFl6a2vqKgQ5vgB5wq6NdR+FNOk105mWuSrcOwz+9Bf2Z+LL7U7 XiNleUuhKGzCWlSfUq4kCilsFmjn9b9WtFSLwY6wfd01XIiUGPC3fl7 X-Developer-Key: i=jannh@google.com; a=ed25519; pk=AljNtGOzXeF6khBXDJVVvwSEkVDGnnZZYqfWhP1V+C8= The current implementation of unix_stream_data_wait() works like this: - unix_stream_read_generic() grabs locks - unix_stream_read_generic() determines that the read must block - unix_stream_read_generic() drops locks - unix_stream_data_wait() sets up a wait_queue_entry - unix_stream_data_wait() rechecks that the read must still block, with less locking protection than unix_stream_read_generic() - unix_stream_data_wait() waits, then loops back to recheck again That seems needlessly complicated; and it also involves an ugly comparison between a potentially-dangling `last` pointer and another potentially-dangling `tail` pointer. Instead, let's set up a wait_queue_entry while the locks grabbed by unix_stream_read_generic() are still held, and after the wait, directly retry the read. Signed-off-by: Jann Horn --- net/unix/af_unix.c | 49 ++++++++++++++----------------------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index dc71ed79be4a..b38804e2c5ac 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -2710,39 +2710,22 @@ static int unix_read_skb(struct sock *sk, skb_read_= actor_t recv_actor) /* * Sleep until more data has arrived. But check for races.. */ -static long unix_stream_data_wait(struct sock *sk, long timeo, - struct sk_buff *last, bool freezable) +static long unix_stream_data_wait(struct sock *sk, long timeo, bool freeza= ble) +__releases(&unix_sk(sk)->iolock) +__releases(&unix_sk(sk)->lock) { unsigned int state =3D TASK_INTERRUPTIBLE | freezable * TASK_FREEZABLE; - struct sk_buff *tail; DEFINE_WAIT(wait); =20 - unix_state_lock(sk); - - for (;;) { - prepare_to_wait(sk_sleep(sk), &wait, state); - - tail =3D skb_peek_tail(&sk->sk_receive_queue); - if (tail !=3D last || - sk->sk_err || - (sk->sk_shutdown & RCV_SHUTDOWN) || - signal_pending(current) || - !timeo) - break; - - sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); - unix_state_unlock(sk); - timeo =3D schedule_timeout(timeo); - unix_state_lock(sk); - - if (sock_flag(sk, SOCK_DEAD)) - break; + prepare_to_wait(sk_sleep(sk), &wait, state); + unix_state_unlock(sk); + mutex_unlock(&unix_sk(sk)->iolock); =20 - sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); - } + sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk); + timeo =3D schedule_timeout(timeo); + sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk); =20 finish_wait(sk_sleep(sk), &wait); - unix_state_unlock(sk); return timeo; } =20 @@ -2955,7 +2938,7 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, skip =3D max(sk_peek_offset(sk, flags), 0); =20 do { - struct sk_buff *skb, *last; + struct sk_buff *skb; int chunk; =20 unix_state_lock(sk); @@ -2963,7 +2946,7 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, err =3D -ECONNRESET; goto unlock; } - last =3D skb =3D skb_peek(&sk->sk_receive_queue); + skb =3D skb_peek(&sk->sk_receive_queue); =20 again: #if IS_ENABLED(CONFIG_AF_UNIX_OOB) @@ -2989,15 +2972,13 @@ static int unix_stream_read_generic(struct unix_str= eam_read_state *state, if (sk->sk_shutdown & RCV_SHUTDOWN) goto unlock; =20 - unix_state_unlock(sk); if (!timeo) { err =3D -EAGAIN; - break; + goto unlock; } =20 - mutex_unlock(&u->iolock); - - timeo =3D unix_stream_data_wait(sk, timeo, last, freezable); + /* does unix_state_unlock() and drops u->iolock */ + timeo =3D unix_stream_data_wait(sk, timeo, freezable); =20 if (signal_pending(current)) { err =3D sock_intr_errno(timeo); @@ -3013,7 +2994,6 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, =20 while (skip >=3D unix_skb_len(skb)) { skip -=3D unix_skb_len(skb); - last =3D skb; skb =3D skb_peek_next(skb, &sk->sk_receive_queue); if (!skb) goto again; @@ -3087,7 +3067,6 @@ static int unix_stream_read_generic(struct unix_strea= m_read_state *state, break; =20 skip =3D 0; - last =3D skb; unix_state_lock(sk); skb =3D skb_peek_next(skb, &sk->sk_receive_queue); if (skb) --=20 2.54.0.563.g4f69b47b94-goog From nobody Mon May 25 08:12:39 2026 Received: from mail-wm1-f50.google.com (mail-wm1-f50.google.com [209.85.128.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 710DE37C0E5 for ; Fri, 15 May 2026 18:54:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778871275; cv=none; b=u3/V1Ua9BgDlTDp1ZrSXkncGF2ekYeUy5Z8n9uNwvZWnrJqcsYfvNt9Cf47ewbuMo947oMFaum0oKAw1nJvnSM9X4AfIjGMfhBZRqXkiqJpkfKxuIGBTc+hw161tfkKju4zLpIQQZBLHLARAAN4cl+MY+xmXasesuRPmJecZRR8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778871275; c=relaxed/simple; bh=DB0n+V52Tzs8cERe6V5xZXHKeaQoXCM9NaKvtCnxM7M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Xm+NBmEtFg76O6U6IyHwCj1SOqFh+4ffxQ7qk/e/ZPKXHlu72gfHYf8AoD538EsbEjMJ7mNI2xYaTPas5JaUcdLWdyGqsgp80Fxb1v8dq4yV5HmhpTlbBgwhShgbrlqkxBw62O6818fmljEdx7oz09JxQjb99iQKme80ppQb82g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=Z+P9dBJJ; arc=none smtp.client-ip=209.85.128.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="Z+P9dBJJ" Received: by mail-wm1-f50.google.com with SMTP id 5b1f17b1804b1-4891ca4ce02so2745e9.1 for ; Fri, 15 May 2026 11:54:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1778871268; x=1779476068; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=cPjE7lCG+YuPbG9M1JzuS9pJL4rG/0cntCt8pBzDzv0=; b=Z+P9dBJJtrKuXC+WZZ0VT/WvnIguzk/fLgVX47FyGxSq7p41rHwkX/ebcy4gbYWnsv hkYT3lCYoX+HObL8gmZwQYgFEEhsFct5GTPp9Wxvq0pBfdI8bdGgJ/r2TKtoyw8YYEEz rSiI8E8gVUrGSeZ7mEfFsi1ikqPyxYNacHu3NG1NAlICxIw4qYfklPJn0g1t7EqWPwWa zMKJwagTRm5i1DA10JkEXjxpwz0xBPv6XXXp41F8besuIkSjQMguPGe8HoZD0N5n7RYr z4BieY1dEbbecY/7oxTHNBYJ+z3kOTVtOq73hC/gFBnOl48HAyaFSxqq5QK3NHcRDweO WWGw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778871268; x=1779476068; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=cPjE7lCG+YuPbG9M1JzuS9pJL4rG/0cntCt8pBzDzv0=; b=AlfABs00DLO6jtQBh1nU5IQpAM1ifFhX1AxPB764HL2LdvxnN7B0MaaDALsvaepLWR TTVwMU+KHecLxLG8ZkKlxVlncEGVwbBfxSzHVnrGxbWlVThieBOmvhdlowCl/va38zfe Ly4gi8xevyV5Q8ISfqywNdmLyHbmwHj0d86FyrOQcDTU5MgFAu1Jtd4BtO2dE69dhfyh Bv/1cOVSuSSoRmyENHuXI3eS1RqTzO2pX+W9vkH7eZ8vOfTmYNIe0Y4uw2yeLFEpyfoM avt16T8F+sWeioPanyWaL4T5MyqukI+Y5TV6lrmA0gAzDC8ydanyTB/PXfvBvUWWug3x stmQ== X-Forwarded-Encrypted: i=1; AFNElJ/roOCGPjL+aV0O1vkHtsUk1s6shjMcmzPBG/JuG6QDtuZcMNItJohresXAp6z+StxQW1+gO0wg6bgaozk=@vger.kernel.org X-Gm-Message-State: AOJu0YwZDgdyEq5yHRRD09su437rMz9knD3D4zX3nYQdkMBsUFq5Ggfh rYxIbLfudvXA+I/hG68/wYUJitT4FYIzucqaE0iYwJ8mDdEXOQnkzYyYdlQFd3lRjg== X-Gm-Gg: Acq92OHGMybV6lw+7zqDgwffRd5VuQIteOzsp08gXxsLc4aS3AT2FrdSRAYX8LA6O8e J3CBCcCvWmOd0LyplP+2hm/URLnp3psmbHPLoYtVoVGv/owcRdCeheVaJ5NBbNtxYQE1nhfaOQC oMy61gDd3MppkE8jea9nD3zA3QRY80PwIW8Qdbe/484c/SEH21l3VU9RHuLZIEwyLmyyy1d/opR mWovwL3VH9+enMu7WLL5Jg/t40qAH1sa1zQQqGCPhJF/uFdTkxmZwzMNmEhCWx1oRoj7vMNDe/f tqjlLJqocVe6bYWtoohY1+4GoZDPbw1t78uTrlpPSl5R31nUAp+Re81e5dKJl8C1EHN0nRY9YCC wUueF+fTYiefkbBoVxFuPVu4Vn5HaLZPBpniQ/JmRKNU0DlURqs+sD61R65pQ8DR3yF/ResdEjg /qrSqGJNiUz/3b0P5u26tZpO4XCcnTObA7Vgo1x8ZnhPPLODwp9gjaw8rLrFugEA== X-Received: by 2002:a05:600c:138a:b0:489:1f6a:4ac0 with SMTP id 5b1f17b1804b1-48ff41c2661mr164525e9.0.1778871267322; Fri, 15 May 2026 11:54:27 -0700 (PDT) Received: from localhost ([2a00:79e0:288a:8:7481:4dac:8e80:6e9b]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-48feae166dasm24658885e9.9.2026.05.15.11.54.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 15 May 2026 11:54:26 -0700 (PDT) From: Jann Horn Date: Fri, 15 May 2026 20:54:10 +0200 Subject: [PATCH 3/3] af_unix: prevent spurious reader wakeups by writer Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260515-unix-recv-wait-v1-3-76adb5f063d5@google.com> References: <20260515-unix-recv-wait-v1-0-76adb5f063d5@google.com> In-Reply-To: <20260515-unix-recv-wait-v1-0-76adb5f063d5@google.com> To: Kuniyuki Iwashima , "David S. Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman Cc: Hannes Frederic Sowa , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, Jann Horn X-Mailer: b4 0.15-dev X-Developer-Signature: v=1; a=ed25519-sha256; t=1778871255; l=1598; i=jannh@google.com; s=20240730; h=from:subject:message-id; bh=DB0n+V52Tzs8cERe6V5xZXHKeaQoXCM9NaKvtCnxM7M=; b=h9yWkuv++lnVf+DshyCBAH42pN5rw+SC/SRama1UcOBNv1YYgQEbZsgSV6YnzcnjwKb3Bz+g5 W+jyAq2FhLJA2jwhLG2iPh8SGK3nRNWwM4DtTg9FVTirTkeIOSMGYN9 X-Developer-Key: i=jannh@google.com; a=ed25519; pk=AljNtGOzXeF6khBXDJVVvwSEkVDGnnZZYqfWhP1V+C8= 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_a= ctor_t recv_actor) return recv_actor(sk, skb); } =20 +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 =3D TASK_INTERRUPTIBLE | freezable * TASK_FREEZABLE; - DEFINE_WAIT(wait); + DEFINE_WAIT_FUNC(wait, unix_recv_wake); =20 prepare_to_wait(sk_sleep(sk), &wait, state); unix_state_unlock(sk); --=20 2.54.0.563.g4f69b47b94-goog