From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pl1-f176.google.com (mail-pl1-f176.google.com [209.85.214.176]) (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 6D4582D1907 for ; Mon, 24 Aug 2026 03:34:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542456; cv=none; b=WI4qQo56nbamXQZD+MfEC5ZUqY18sXEX6yUiTe3pu7PU5oUg1muLzfFNhlpIe3nrTxU0daujRsBx+wh3CY1W9qdb99e6GIkewXQqTLIWYw4JUU9QadRdjYhZSzL9FjjFxHdClMO2CwZ6cYMBrF8o7Yr3jMWsFN6W/k/NBY7X8XQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542456; c=relaxed/simple; bh=u3y54k+0lvhiUX1UbI9Aif7xvnSV+L7OHs/brlLc2gM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=p9ZeOHQxoHDYoNHqDKwNL94LoQliJ8kwIqh9cdiBOci2GJkH1fQNFjNfSqc/dYUzLlUIAImisnkzexyjtJ8lPddfZZjmk4JiWhJHlwUrzw9Qm0vPa0Ei5EZJ+0fXRvhYFi9gNBe/x7o6BfeD3s8fIeS0QsGPRoCUOKqzzEIceM0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QlKWiyL0; arc=none smtp.client-ip=209.85.214.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QlKWiyL0" Received: by mail-pl1-f176.google.com with SMTP id d9443c01a7336-2cca0c5799eso24699655ad.0 for ; Sun, 23 Aug 2026 20:34:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542455; x=1788147255; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=PXkKkJ4/pQ31f/Gro96CCtKQ7s8xDXf64Jn4C2P4P+U=; b=QlKWiyL0NyRb4RYjIX5UkaG/9hpll2qbBMlGJClSh08ERB8R/MeHbrb2MIADmDLEsj S7iMJAVpw99wGAB3atH2DuaMIJGY2W8S2KhsfjfjwzAzO19d6/JJOnuBiKxcWnlDl3je rO5WE4Kksdbwvlz1efFcvqwSS4kukt9FZtpIaYe+NdNYMRuVzqCefuV+WcMykjejNb1Y SNffqybGaLjFLdgG0hgSNyne9/js9IEeimAUCjwG9dVn1lCVJAj3r8mUzw08H92MIqs0 F1KTTnPZVDMXfEInben/KCI87VOSWwrBHXOBrtFF7fY5OvjM4HSURrlDCdAtEhG1f/+c DYBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542455; x=1788147255; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=PXkKkJ4/pQ31f/Gro96CCtKQ7s8xDXf64Jn4C2P4P+U=; b=qe9IaTh9Sbb7J3dGBUv71o6AOlQCQTSXLqNV9QEGLnHSI+eHuCdc6gqpEHdwxAGtf1 gX+0+chlWM5Uu3XHmmTRYT7lvEfGdEoiqb4kPKlL9pd5Tp7ivQcynkncluqd7DHsJgot HV5Rm08EHE8BL7MOR9IDy2gwXYRPhH4CyR2JuyE2fhnR0c0ai0Vw4j6NT2RpuCXheNBw X04vaEW3WEI6N0ekvKVTc87WXMiY1JXgL5Cy8gErCbtCx4TSoVGMfsmfMnO/yLlMiKOS 1/NRx426AREvZoVUrxb05LPna/ivJR5GzJ35bC6m26r2FvznudeMmZneC3P/ibGj0SBU U4fQ== X-Forwarded-Encrypted: i=1; AHgh+RoJLNdD5RcPZgKKIb42S3TAxOSRB+HD+iXJ2hG1sXE1QXQVDBC+SAbta6no/as6d1RWKONISFm+APz5mng=@vger.kernel.org X-Gm-Message-State: AFuF++mMOzzPRlQr1czc5pkRIwGsdtr3E1OS/RVyfd1K0VRGSCtlaC69 /cZZveJHcLq4fueBF5K4kf9wQN2KG25Y9wUeJCDiYOrkvBG0TyMN3AxM X-Gm-Gg: AR+sD10g1f+RFjwqfBzvwx8u+ZSiHQ4h0ZVOjSs2dPGLaAjZyTIWgsb1pDKD9K9PUC/ EwbJ/GVB8J2bDyRCVUuxGGs4UQ8IJwXuT+67m0W5ewFgOAvnmWOpC4a6rXUcwG+ueyLF7rAEUvB Qvp9J0uUW3stPjjguTxveBHvEgsY9Ay7C2isVC7jYADNZPTAhmqtziD26nXErY01KWGBBWInteJ RY82Q9XZsLE0quNYiWMX0EUx1id09HdzqNyqIZfNFaeQlnubQGAo1FFFP1N1pc7DYCLhnr5XVCY VK53/zREGt1ibttFwoAvebxo9bBdA7C0Kbs2dsxf6YtS14G1q/un2a0MHExzuS3sQb/w1kElSmH 2Tvn0ZbMExWwSU9rE8wOz/67jDbOZAFQk+CdddvxMYAr6rciGULvScjh1AA/fG3H9lMz9qyIIcz hGajPLhL7p9djxqnlg8Aljqx7SnI/Bnh2sK0BQLy2gpElQ5lh6dGgKOMo0X1BdQs14Iqz/Fv8Nc R4xOu0xOUc= X-Received: by 2002:a17:90b:4c49:b0:366:10f1:3d91 with SMTP id 98e67ed59e1d1-395c354d42dmr39650990a91.1.1787542454662; Sun, 23 Aug 2026 20:34:14 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:14 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 1/8] tcp: fix use-after-free of the listener's ipv6_pinfo after IPV6_ADDRFORM Date: Mon, 24 Aug 2026 12:32:45 +0900 Message-ID: <20260824033331.1084971-2-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" IPV6_ADDRFORM switches an established AF_INET6 TCP socket to tcp_prot and ipv4_specific. The socket is still a tcp6_sock, so ->pinet6 keeps pointing at the ipv6_pinfo inside it, and sk_destruct is left alone because commit d38afeec26ed ("tcp/udp: Call inet6_destroy_sock() in IPv6 sk->sk_destruct().") uses it to clean up the IPv6 resources. After connect(AF_UNSPEC) the socket can listen() again. Its children are then created by tcp_v4_syn_recv_sock() with opt_child_init NULL, and sk_clone() allocates them from tcp_prot, so each one is a plain tcp_sock that inherits ->pinet6 and sk_destruct from the listener. tcp_v6_mapped_child_init(), added by commit 858d2a4f67ff ("tcp: fix potential race in tcp_v6_syn_recv_sock()"), would overwrite ->pinet6, but tcp_v6_syn_recv_sock() is the only caller that passes it and it is not involved here. A child can outlive the listener. INET_ECN_xmit() and INET_ECN_dontxmit() test inet6_sk(sk) and not sk_family, so tcp_ecn_send() updates np->tclass through the stale pointer, and the child's destructor runs inet6_cleanup_sock() on the freed listener. In short: socket(AF_INET6) -> bind -> listen // a client connects over IPv4 accept() // the child is v4-mapped setsockopt(IPV6_ADDRFORM, PF_INET) // it becomes an AF_INET socket connect(AF_UNSPEC) -> bind -> listen // reuse it as an IPv4 server // a client connects again accept() close(the listener) close(the accepted socket) // use-after-free KASAN log: BUG: KASAN: slab-use-after-free in __tcp_transmit_skb+0x1070/0x2020 Read of size 1 at addr ffff888016671af3 by task poc/111 ... Call Trace: __tcp_transmit_skb+0x1070/0x2020 tcp_write_xmit+0xace/0x3380 __tcp_push_pending_frames+0x58/0x180 __tcp_close+0x4b8/0x7d0 tcp_close+0x23/0x90 inet_release+0x93/0x100 __sock_release+0x66/0x130 sock_close+0x18/0x20 __fput+0x1f0/0x4c0 __x64_sys_close+0x55/0x90 ... BUG: KASAN: slab-use-after-free in inet6_cleanup_sock+0x61/0x140 Write of size 8 at addr ffff888016671b20 by task poc/111 ... Call Trace: inet6_cleanup_sock+0x61/0x140 inet6_sock_destruct+0x12/0x20 __sk_destruct+0x4f/0x420 inet_release+0x93/0x100 __sock_release+0x66/0x130 sock_close+0x18/0x20 __fput+0x1f0/0x4c0 __x64_sys_close+0x55/0x90 ... Allocated by task 111: sk_prot_alloc+0x45/0x170 sk_clone+0x49/0x970 inet_csk_clone_lock+0x29/0x2c0 tcp_create_openreq_child+0x2a/0x10a0 tcp_v4_syn_recv_sock+0xd3/0x850 tcp_v6_syn_recv_sock+0xc12/0xd80 tcp_check_req+0x390/0x1080 tcp_v4_rcv+0xc15/0x21c0 ... Freed by task 14: slab_free_after_rcu_debug+0xd5/0x220 rcu_core+0x4fe/0xe20 ... The buggy address belongs to the object at ffff888016670e40 which belongs to the cache TCPv6 of size 3328 Fix this by clearing ->pinet6 and ->ipv6_fl_list on the child, and by returning early from inet6_cleanup_sock() when there is no ipv6_pinfo. tcp_v6_mapped_child_init() sets both fields, so the v4-mapped path is not affected. The converted listener keeps its own ipv6_pinfo, so there is nothing to clear on the IPV6_ADDRFORM side. Clearing ->pinet6 in tcp_disconnect() instead would keep this out of the fast path, but it leaves the pointer NULL on a socket that still has a file descriptor, and of the 120 inet6_sk() call sites only the two in inet_ecn.h check it for NULL, so _all_ the others have to be found and guarded first. At the point patched here the child is not in the ehash yet and has no sk_socket. Once the two fields are cleared it is no different from any other AF_INET child. Fixes: d38afeec26ed ("tcp/udp: Call inet6_destroy_sock() in IPv6 sk->sk_des= truct().") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- Changes in v2: - Clear ->pinet6 and ->ipv6_fl_list right after the inet fields are set instead of in an else arm of the opt_child_init test, so the child is already consistent on the put_and_exit path and the existing test is left untouched. - Explain why this is not done in tcp_disconnect(). - Add the reproducer and the KASAN reports. - v1: https://lore.kernel.org/all/antr7RCJAO578ZFW@v4bel/ --- net/ipv4/tcp_ipv4.c | 8 ++++++++ net/ipv6/af_inet6.c | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 190c7af4cf923a..302afe8ebcbcc3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1714,6 +1714,14 @@ struct sock *tcp_v4_syn_recv_sock(const struct sock = *sk, struct sk_buff *skb, inet_csk(newsk)->icsk_ext_hdr_len =3D inet_opt->opt.optlen; atomic_set(&newinet->inet_id, get_random_u16()); =20 +#if IS_ENABLED(CONFIG_IPV6) + /* Never inherit the listener's ipv6_pinfo; IPV6_ADDRFORM leaves it set + * on an AF_INET socket. tcp_v6_mapped_child_init() installs our own. + */ + newinet->pinet6 =3D NULL; + newinet->ipv6_fl_list =3D NULL; +#endif + /* Set ToS of the new socket based upon the value of incoming SYN. * ECT bits are set later in tcp_init_transfer(). */ diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 282912a1199992..68b330f6941d04 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -479,6 +479,10 @@ void inet6_cleanup_sock(struct sock *sk) struct sk_buff *skb; struct ipv6_txoptions *opt; =20 + /* AF_INET child of an IPV6_ADDRFORM'ed listener: nothing of its own. */ + if (!np) + return; + /* Release rx options */ =20 skb =3D xchg(&np->pktoptions, NULL); --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pg1-f173.google.com (mail-pg1-f173.google.com [209.85.215.173]) (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 B33E913777E for ; Mon, 24 Aug 2026 03:34:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542462; cv=none; b=uZ8Jy40DP5wwTohW1Lzsa8dTpfDqkmP64xeV3H8KjUP4OPXdQqaqSpmlkaGCqkdj+NXcGTseQmIsoQiT3rvu8o6q33cY/xpu9FLP6NVSxEFa8eFYKo//IholCwxDVUVIqndHGDcTG+NvkNsC3bXCIXEaika9cveJQwuk7xVO7wI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542462; c=relaxed/simple; bh=+dKnbTgDxN+0z3CbVk5mqFazg2JoVWNbuUu/8qkYY/s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=q8CeMGCDDqylTPaHr6HReCyYTOVHqEep+NY6B2oD8Yfo4AI1m5RkbGDhjilW/Qg6WtNqo7w87grTKsK+QyG84XU6CR6yzvYeWMkbzjzAQ4E8XYwv5RCdczZXj4cJ84qtN3zwUijC2xWF1wNcs2qKHr/DsoSe4pR1hV+KMnfOE8w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Q2vGIGxn; arc=none smtp.client-ip=209.85.215.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Q2vGIGxn" Received: by mail-pg1-f173.google.com with SMTP id 41be03b00d2f7-cbe6295f05bso2663110a12.1 for ; Sun, 23 Aug 2026 20:34:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542460; x=1788147260; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BDKSoho+eBexvjceZDtsEWeLiUwG16rb98ovhChMyds=; b=Q2vGIGxnK1/y4F3Fv7HrK/N/qqa7Pj1yY4g6xpp4b7eHhWDNoWPXXRlMW+1Nzsz7f+ k26p5xOPS7gba0rJlvo7K5vINS2avB6LyagZUcHK9I+xZaKNhgiG12mAPr2mWH8BOpDH OS1rWIzPOgFNpHBhZW1XCVFwiDjwteJKZ3OZT3LlfwSkmcxgz0v8ixzsq7XJt3cY7B0s SGkG6FUM7jLA49qXYPMfcA+tgFDCyhxXh/8krj76lz1Szh81OFCF6iVMfCGnaD+QdTyy /8NIndMAuezY4SMGcm2UnEuQxiUqGcuLQgnXLIQ2acn7i5bCEygIFuVlnNCzDQ9Hu2sH WQWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542460; x=1788147260; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BDKSoho+eBexvjceZDtsEWeLiUwG16rb98ovhChMyds=; b=ieB2cHC/UpTd1cSkDhvhGF0bEgUnXlDtpxtuabYFjqmoG//TUbm221W5TVVykKq1vA tVKYdgEA2VsHfgKOIQpFXRkbPdbCiGi3ur/srYvyMoDKaLuPaxTzMV5lScZVOPUV5dd5 ju35usgWF34PS9LlV+HR2ByL/uYjWq1TJMcD9XKKnqrr9jTBc0DmJS/zHjdpkbZWDzsE TpGF/UqlyK+a1aYfZuq73FYeB5X7gCpWK3n9wq72zD9D4NRNi8mOt/pjY3ce/p6PhR9+ W2xcXxq6m4a7AtP8dKyOHOgQIB7F+reigz0kvfNZM7duvg2RC64t0+MM1CW2Y+NxylgL u7mg== X-Forwarded-Encrypted: i=1; AHgh+Ro5C6ARQm+qiSiwHeQoMV5ozloj5FwY2D2+/j6mLI3NCg83J42vlzIkyKvTNh4Dx91ltwRG6jaEPOUagGk=@vger.kernel.org X-Gm-Message-State: AFuF++nLawh6jKQwXICq39zHhlHIDPTjJfvBh0IXPi22he+O8Hl+hJfn qSfj7xTOUUE6cP9VXlviuhiWct+Dz9Z+GzHmro40knyxfwqWyhLFkktf X-Gm-Gg: AR+sD13J2ESdDR99xMMwj/9lUk1PqVZWt6oxGaXez8FFF8w/P+l5U82eaQZ1bFFF4se 10B7Vf7l+zKU28IUJNHgt3RGb07jswdzfwDKpYmNS1+kjqfIZhruV2UCVnLeajLbUXLUtvuFSiQ C6wiP7I2/Xj60ZA4Z44ZypPqW7eYRNG8p1Aa77N5bs93TyRWEpuECmpbNC5UIGvk7Sgr+GwOPCN BHDgKLf8FztjayT/kvopbUbW+bZRx0mTnczX5oEJIT/BRoNzc4YQ7IkvFwC31QFTIAcTccs3mP6 rmBxWzIyj2ZAnO1BhrTJU7M08Q67DBpMtVkVoMORmci++u3VkGBRykKUAAWKGzBg/sEUzIT5Whw t9SCCPhrudX71lNt5XmQCjkuChdHk7A9b2jq3nSOuIeSMjOIHxo8GZTZfo424wmpqImm9LOtZ7h uyb9Y2rQdEQQyMIr+UwOh9js0OlmIHyZ1/Bht9AHbTI8bPvGPd/tu9oEcoxYWPogUM3kW4mB5UB BLywdEVFKc= X-Received: by 2002:a17:90b:1dd2:b0:385:3ab:fecb with SMTP id 98e67ed59e1d1-395c4c98f17mr23004718a91.4.1787542460044; Sun, 23 Aug 2026 20:34:20 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:19 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 2/8] tcp: fix imbalanced icsk_accept_queue count in tcp_check_req() Date: Mon, 24 Aug 2026 12:32:46 +0900 Message-ID: <20260824033331.1084971-3-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When TCP socket migration happens, tcp_v4_rcv() and tcp_v6_rcv() pass the new listener to tcp_check_req(). The listener that counted the request is still the one stored in req->rsk_listener. The embryonic reset path passes @sk to inet_csk_reqsk_queue_drop(). After migration this decrements the count on the new listener, which never counted the request, and the count on the original listener is never removed. The cited commit already changed the inet_csk_reqsk_queue_drop_and_put() call in the same function to req->rsk_listener. Do the same here. Fixes: d4f2c86b2b7e ("tcp: Migrate TCP_NEW_SYN_RECV requests at receiving t= he final ACK.") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- net/ipv4/tcp_minisocks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 12254e6eb2f343..0c3b35a381e327 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -974,7 +974,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_b= uff *skb, tcp_reset(sk, skb); } if (!fastopen) { - bool unlinked =3D inet_csk_reqsk_queue_drop(sk, req); + bool unlinked =3D inet_csk_reqsk_queue_drop(req->rsk_listener, req); =20 if (unlinked) __NET_INC_STATS(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pf1-f182.google.com (mail-pf1-f182.google.com [209.85.210.182]) (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 2C7D536894D for ; Mon, 24 Aug 2026 03:34:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.182 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542467; cv=none; b=XV2beTeB958dvZCltcZcA9PWjRYw1MHs0QUdGtRqZKHK/TJJXGbA0L6XpvUTDZacXMAUF2IyKIY2H/BaYUsswTjLFs26PzlhZlIu8cJNAW2deG4QjO+4pOsvoCJsL3Hm8kqz/9bBXn8i0D6CtIartHYVIQ9rvsaDWgNffqS4usc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542467; c=relaxed/simple; bh=fshRyVnVklSNFCrBGc5v+fvhYMKreR65qNagU/FO848=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RXCmbO//8MIHiFxY8lYKqQwh5qJjswQfrTjNiR72ukencly3B6TJwt2rN87rsYF+wyf0I4DuuiGpPgamdI5XaLyIvpAHuN61baeW7VSXoz3kfLJwS2JTKG1pMp/DWcWPJOGyLJvcotwHZ2eUupdvXkKOO+XSjXXTljFpU2ekcVQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Y4wKDlT/; arc=none smtp.client-ip=209.85.210.182 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Y4wKDlT/" Received: by mail-pf1-f182.google.com with SMTP id d2e1a72fcca58-8486ac3f347so3452556b3a.1 for ; Sun, 23 Aug 2026 20:34:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542465; x=1788147265; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=e3Ne4nEWByrW0EmFrdDA4ySM1EU9MVsFB0We73FOJj4=; b=Y4wKDlT/IyZgrxdbD748RoH8u5Zmr56XV6677dlSzAHS75yvkGczaKspktA5EPBgV0 zenyKOM7Ehm2cDmJsc5neT+nw49KHA9U0G5kgv6KLlcu8f2THNRtykNdNsf4P5Zd7d6+ vD7W7xNhY+oJdtrTGUMu1N7lKRd9WTxOwYPWaxy/Zzf37sXePThOvILs1gvrRtuDP/IY RN5YiRvPN+fPCT0KxM9en4h54GtY8RbEe/r5j9H0MboVZ1fSWpinBSFNPrpjiFbm747t PCWItsin2ALQAMpc2SJ63wfg64SqDh2ovZ833UKyX/4XZUXacx+Oug2VSlQpluzyovuB TgUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542465; x=1788147265; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=e3Ne4nEWByrW0EmFrdDA4ySM1EU9MVsFB0We73FOJj4=; b=aIzgJsj8+VQi/4AuR4Ql8ulYiQt4aAMp4cFqxNfqkSQZD48wwUWyjbnOYFtGG+DvBM r5vS4upsuiLn033fVe4NtBkHWurfHqrkRxeQk2fWvvIN6HUvGQo8aM+kq+vridKAG2vI Oql/lFLkqglIuDCmFguD/j+9oOob78Wbse3Vcbam0mPnphnhhFMDvFSErS9yAzgWOlQ4 wwQP78QFeLxpToBCVKuHTKBA621cy9I3MvhI+PIg3g02g6juSY13GPkm3LU8wUnPoQaW kl6mIftnEJ7Ft0sAVX9pMrrXFyaItoPuNm1fSFndrF14EIQmsLbnWzuNfCCILTjojvMZ NYYg== X-Forwarded-Encrypted: i=1; AHgh+RrP36PCaqqVxNsc3kTQm677awh7iD5ddMwa3wn8WbDT/MgOjgUXrYtC4sWvfWKeOUu52vW2No/ehBN/Ctw=@vger.kernel.org X-Gm-Message-State: AFuF++ma/NzpRaiwQrG0qAA5eAQD9DQoSIQrhPAj7ru0+9C7iRTsQT/N kkqOIoHFcJuORVHGApjtNheZgztsXe1yUvURf8TtbiWiONmW3r0WyOh3 X-Gm-Gg: AR+sD11fM0VTVuP+bGWL6/ZMcC/+5iVnSrc7EDpnmQSXXI/q1xJzJ20DZTKHTLQf2Ja o8lyGZ59sMm+oJm3XbbTAxz2spt6DyLYgH2EYkfcoGbjSnDxpG4Yx3R66UnSj+eLHU+EjVPcFOU gq64aS8ZL21i1r5pxjSYhYI3/afvGMSgCWqQ3pTVfkaw2Yep1SslwA4Md4skiuYLcWyfFKnXAL+ LPQWcqAVsfnOwLEuWoUliHcZ2gYvbiha52Fsm/Q8AyVEKyKVlObnWTL+8/stjQoSxFLSwcOyJUh vQF0c/+YZBSdFoXh5/aZHNbyYwm/O2Z1/zcZH3tm6uwuxBJ86TuhZQR5l/HytL6T88TPZuVnvif Kwr4mlcVT4qTchEJStkTZ8zwghRmI9HQ3C8+iAYwfHCmcsw5FOU+3EuzOiQnvQgtrMqWRkw8MkN 06xx+rHevArGsgnynCRi8u/YR+ZQFzWAUrpH8NUsGq9Qo9mgsDhlzOQaGLTiN2S55Mx6UbPI2oT KQv9xK2esw= X-Received: by 2002:a17:90b:268b:b0:38e:42f5:d096 with SMTP id 98e67ed59e1d1-395c4528324mr21965634a91.0.1787542465447; Sun, 23 Aug 2026 20:34:25 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:25 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 3/8] ipv6: fix request socket use-after-free after IPV6_ADDRFORM Date: Mon, 24 Aug 2026 12:32:47 +0900 Message-ID: <20260824033331.1084971-4-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" IPV6_ADDRFORM turns an AF_INET6 TCP socket into an AF_INET one. It requires the socket to be established, and a listener can get there with connect(AF_UNSPEC) followed by connect(). Request sockets queued while it was listening are still there: inet_csk_listen_stop() leaves them in the ehash, and their timers only drop them while the socket is not listening, so making it listen again keeps them alive. A request that arrived over IPv6 was hashed with inet6_ehashfn(). Its child is cloned from the converted socket and hashed with inet_ehashfn(), so it belongs in a different bucket. inet_ehash_insert() locks the child's bucket, warns about the mismatching hashes, and replaces the request with the child in the request's own bucket anyway. reqsk_queue_unlink() locks the bucket the request is really in, so there is no synchronization between the two. Both can see the request still hashed and both can drop the reference the ehash holds. The extra put takes the request's refcount to zero too early, so it is freed while it is still on the listener's accept queue. The listener is then closed, and inet_csk_listen_stop() reads the freed request and writes to it in reqsk_put(). In short: socket(AF_INET6) -> setsockopt(TCP_DEFER_ACCEPT, 120) -> bind -> listen // a native IPv6 client connects and sends nothing // the request stays in the bucket inet6_ehashfn() picked connect(AF_UNSPEC) // stop listening connect(a v4-mapped peer) // become established setsockopt(IPV6_ADDRFORM, PF_INET) // become an AF_INET socket connect(AF_UNSPEC), listen() // listen again // the client sends data and the leftover request completes close() // use-after-free KASAN log: BUG: KASAN: slab-use-after-free in inet_csk_listen_stop+0x1c2/0x760 Write of size 4 at addr ffff888010b7cbe0 by task init/1 ... Call Trace: inet_csk_listen_stop+0x1c2/0x760 __tcp_close+0x6c1/0x7b0 tcp_close+0x23/0x90 inet_release+0x93/0x100 __sock_release+0x66/0x130 sock_close+0x18/0x20 __fput+0x1f0/0x4c0 fput_close_sync+0xd2/0x170 __x64_sys_close+0x55/0x90 ... Allocated by task 0: inet_reqsk_alloc+0x8c/0x320 tcp_conn_request+0x324/0x11f0 tcp_rcv_state_process+0x2ff/0x2cf0 tcp_v6_do_rcv+0x326/0xc30 tcp_v6_rcv+0x1e07/0x1e90 ... Freed by task 0: slab_free_after_rcu_debug+0xc5/0x200 rcu_core+0x4dc/0xd20 ... Last potentially related work creation: kmem_cache_free+0x11d/0x5f0 tcp_v6_rcv+0xb30/0x1e90 ... The buggy address belongs to the object at ffff888010b7cb60 which belongs to the cache request_sock_TCPv6 of size 352 Refuse the conversion if inet_csk_reqsk_queue_len() is not zero. Nothing clears that counter when a socket stops listening or listens again, so it still accounts for the requests left in the ehash. A socket that never listened is not affected. Reading the counter once is not enough. inet_csk_reqsk_queue_hash_add() puts the request in the ehash first and bumps the counter second, so a setsockopt that lands in between misses a request that is already reachable. No new request is created once the socket stops listening, and a SYN that found it while it was still listening is handled inside the RCU read-side critical section the receive path holds. Waiting for one grace period before reading again therefore leaves no request that is reachable but not yet counted. Fixes: 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- Changes in v2: - Read inet_csk_reqsk_queue_len() again after synchronize_rcu(). A request is put in the ehash before the counter is bumped, so v1 could be raced. - Move the check below the TCP_ESTABLISHED and v4-mapped checks. In v1 a listener returned -EBUSY or -ENOTCONN depending on whether a peer had a half-open connection at that moment. - Add the trigger sequence and the KASAN log to the commit message. - v1: https://lore.kernel.org/all/20260817090319.3897799-2-imv4bel@gmail.co= m/ --- net/ipv6/ipv6_sockglue.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index b4c977434c2e0a..6d2dd9ae46a964 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -587,6 +587,21 @@ int do_ipv6_setsockopt(struct sock *sk, int level, int= optname, break; } =20 + if (sk->sk_protocol =3D=3D IPPROTO_TCP) { + if (inet_csk_reqsk_queue_len(sk)) { + retv =3D -EBUSY; + break; + } + /* A SYN that found this socket while it was + * still listening may not be counted yet. + */ + synchronize_rcu(); + if (inet_csk_reqsk_queue_len(sk)) { + retv =3D -EBUSY; + break; + } + } + __ipv6_sock_mc_close(sk); __ipv6_sock_ac_close(sk); =20 --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pg1-f180.google.com (mail-pg1-f180.google.com [209.85.215.180]) (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 6ECAF3203B6 for ; Mon, 24 Aug 2026 03:34:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542472; cv=none; b=ex+zTnNo+mV2Rk8p+L4s4bMp1shMlEUHGSdrlwICEyUZraUxcLDr5rSIEv2BowvLpUNf+hccakSDvsc7BXswjDRRQ6cqDhZBB3hIcd3b3uu+DiZb8S1QfdRw4e/XnUNZZxLDmMGiNAdYX+9RWfmxMCkZQPhx1lPZMTEEnLB/4DI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542472; c=relaxed/simple; bh=Dek4I5uP0FMYW8XeEuoDo68UhqlHR47NiFV4NvSaHmM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=je0IplUmxMERiMuhiW5DzGsbkl8FTXUNMIuXFc2GrnVaafY2oqoENAEWtMe5fvtJ5c5TSJ/SwdnS/0YcUhMYtKML5Db+UzrKWsgDjAfFVkXzurkf9AHJ3KZrx/j55CnKONpzjov+iPRPGT+UOwaqhCtHQ1Y0pfOAqXQzDbGraKc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Dd6xpXHf; arc=none smtp.client-ip=209.85.215.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Dd6xpXHf" Received: by mail-pg1-f180.google.com with SMTP id 41be03b00d2f7-c9d1fff21edso2371991a12.1 for ; Sun, 23 Aug 2026 20:34:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542471; x=1788147271; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=pLRrcZ+wu3rYCbjfRuOSR4inkFMDxN07CSBT+LJEscY=; b=Dd6xpXHfnoqITo1VCu+q7/YLjre9bdSGlyeCIV2I3FuF+KCb7kukR5QVuoJaX/ca8W M15Qu9p+bHIJ6YhJZMsn/JXmpXUHzXWbwh7LVlWIdLbyW2KVc9CycOUVGkefRbO4BIr6 +2pER9tmVPXACVAcEsCnAopnXTOsMtv3hf/1/66zdDdd5YkrcOVDL9Ie/zN8dYYlLljo vNMPpsVXrXC9TK3PfJlj4yw7vlqcE32PecmBmzJ3bTBEcNFxC4I9ugbcqfTSE4t3Ma/v WYt1UBBMvJYUvWHh0nm8kyjAisrwrksNlR/eFsrfpoq9ZttmzNV/i44lJhUQYuXk/kSW tPAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542471; x=1788147271; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=pLRrcZ+wu3rYCbjfRuOSR4inkFMDxN07CSBT+LJEscY=; b=tY1MV9NQe7+Tcn9BOMt3aZxbBRCXwYo3TOk1S9YZv5qFmikvXlnu/+aNsEbnOom8Ck EAxatf2Lgdn/SDof5hTYGOJsKehTbeQcBSulFCX+vVPQ94da+MqYhKLXi//u8dJStn39 UJ4Jia7DjxqZsYzcdNDizVeFrjF/w0qpmzJuMZWZilTIu0kpqsMLAo3a4WIxdqodEUvq wWt54wDm/pCWffQVA8aVvtw6wKmHQJtZ+z/4Fn4qpQgfEm/ZuJPTHyvNx6N/FvXmE6g9 dlTJsuxxjPYsld5eJw8qRC7zd4MDpQ47Fxu5BoohqShprQjpNJZ3KPuKdiyL1/gEeTHZ Bqmg== X-Forwarded-Encrypted: i=1; AHgh+RqXpx7z1p6scAcKhBBb+QRks425NdZF65InaCgu+xJBMRtUH5bgk1QKmnFPETIzDYtLLjHgu4rFl46j+lQ=@vger.kernel.org X-Gm-Message-State: AFuF++m2cfvRVRyGiE4WekgKfO1MFm7aGdn/7bZ6g24kOJ0PR03COgt+ 4yq3HSs1kwwYea5DZRzVK8Oa1oNjWikxXY3f0NMifaxlUlSRz6NuSc0c X-Gm-Gg: AR+sD126L856LVphJ5GjCj0E2wvNzw5akMUZxdxu1ngmpHScwwkVLTjL9498+s0/a6D 3/07eDrb61ef+EgpqOCRfJ1agoQQqLJpOhRTiwv/GS5S9m+nbwLW4LIEpmtudY18+aKOWxeoS1Q n7Y7OOhqDvTHlxzhxGOA++7aKZJzqTGx0e8FY2XeZN09RhIGwigP3oHHLY4HGNsuZeKMB2tiCmi HmB7ryUPLjDdAipV9qcV6odybtDc/XtL430jqPiU8fGIEPD41dLQk7J3pKhWZ6EipAIjGJtLEEV YtjWSPmSZFWqNjNGFw1AClbEtQotZB+G/ROOBvC+yJcaxXRnVDms06qTaWZZ5AjzBm9ELNJWOQN BN38A4j7hF9CA6nok05tHb6R76F6yEbq0IO7bXH0+r3GyC1lxxu3RSJHLf7BSxHyRPNtsgPLoaT 9XuU7MU5esXJFPHqX1cYyYFTcsugKR9HlH+1YuWx8sb9NPf1iXs+L57NXZFXQHUUx80tAksaQAO /aPKEgvzuA= X-Received: by 2002:a17:90b:164e:b0:38f:2168:b9cb with SMTP id 98e67ed59e1d1-395c352fa60mr33931547a91.9.1787542470791; Sun, 23 Aug 2026 20:34:30 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:30 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 4/8] net: fix out-of-bounds write in sk_clone() racing with IPV6_ADDRFORM Date: Mon, 24 Aug 2026 12:32:48 +0900 Message-ID: <20260824033331.1084971-5-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" sk_clone() allocates the child from sk->sk_prot, and IPV6_ADDRFORM can change sk_prot under it. The conversion requires the socket to be established, and a listener gets there with connect(AF_UNSPEC) followed by connect(). tcp_check_req() completes a request without the listener lock, so it can run while the conversion is in progress. IPV6_ADDRFORM stores sk_prot before icsk_af_ops, so tcp_check_req() can still call tcp_v6_syn_recv_sock() once sk_prot is tcp_prot. The child then comes from tcp_prot's slab while the AF_INET6 code treats it as a tcp6_sock. tcp_inet6_sk() is a fixed offset into tcp6_sock, and in a child sized by tcp_prot that offset is the end of the object. The ipv6_pinfo copy is therefore a slab out-of-bounds write of sizeof(struct ipv6_pinfo) bytes past the child. The out-of-bounds address is also stored in the child's pinet6, so everything that reaches the socket through inet6_sk() keeps writing there. A request that arrived over IPv4 takes the same copy in tcp_v6_mapped_child_init(). In short: client the socket owner socket(AF_INET6) setsockopt(TCP_DEFER_ACCEPT, 30) bind(), listen() connect(::1) // bare ACK deferred, request stays send() // tcp_check_req() -> // picks tcp_v6_syn_recv_sock() connect(AF_UNSPEC) connect(::ffff:127.0.0.1) setsockopt(IPV6_ADDRFORM, PF_INET) // sk_prot =3D tcp_prot // sk_clone() -> child from the TCP slab // tcp_v6_syn_recv_sock() -> memcpy(ipv6_pinfo) // out-of-bounds write of 128 bytes KASAN log: BUG: KASAN: slab-out-of-bounds in tcp_v6_syn_recv_sock+0x297/0xce0 Write of size 128 at addr ffff888015b5f480 by task repro/161 ... Call Trace: __asan_memcpy+0x3c/0x60 tcp_v6_syn_recv_sock+0x297/0xce0 tcp_check_req+0x374/0xff0 tcp_v6_rcv+0xb9f/0x1e90 ip6_protocol_deliver_rcu+0x1aa/0x870 ip6_input_finish+0xac/0x1a0 ip6_input+0xe5/0x490 ipv6_rcv+0x2a0/0x3d0 ... Allocated by task 161: sk_prot_alloc+0x45/0x170 sk_clone+0x49/0x960 inet_csk_clone_lock+0x29/0x2c0 tcp_create_openreq_child+0x2a/0xf20 tcp_v6_syn_recv_sock+0x14e/0xce0 tcp_check_req+0x374/0xff0 tcp_v6_rcv+0xb9f/0x1e90 ... The buggy address belongs to the object at ffff888015b5e800 which belongs to the cache TCP of size 3200 The buggy address is located 0 bytes to the right of allocated 3200-byte region [ffff888015b5e800, ffff888015b5f480) Checking sk_prot before the clone does not help. It can change between that check and the read inside sk_clone(). Use sk_prot_creator instead. It is set once in sk_alloc() and never changes, and the socket is already freed back through it. No caller that replaces sk_prot installs a proto with a larger obj_size than the creator, so the child gets the size the parent object actually has. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- Changes in v2: - Add the trigger sequence and the KASAN log to the commit message. - v1: https://lore.kernel.org/all/20260817090319.3897799-3-imv4bel@gmail.co= m/ --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index 1ad41904db25b4..098e58b40f304b 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2479,7 +2479,7 @@ static void sk_init_common(struct sock *sk) struct sock *sk_clone(const struct sock *sk, const gfp_t priority, bool lock) { - struct proto *prot =3D READ_ONCE(sk->sk_prot); + struct proto *prot =3D sk->sk_prot_creator; struct sk_filter *filter; bool is_charged =3D true; struct sock *newsk; --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pj1-f49.google.com (mail-pj1-f49.google.com [209.85.216.49]) (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 E25AF2D1907 for ; Mon, 24 Aug 2026 03:34:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.49 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542478; cv=none; b=QjrZuzHWZ40oh+Qs/FTuP9ePBogGo5gg1Vfqun3ivTD/Q8duuk+ZJwXwiMdPIjGn7FyrD05lwiImCbMZaNYPqo6RBWdOuLJlj++KWRenJlG6DIRoJJMjddOs3o4sp8kVHXoiKGECSm3F7JTh47BLwqOf90QSdofsewpMTrgblfs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542478; c=relaxed/simple; bh=iKlmSYal/we//DbFxdnR+qq4NS2r621URuMIi6uUWaE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IGxJrMgnP2jUxZzYH+o6ifpDIVpsmKhgDSMQSxWdoXfxONglzpkcrLiXEMIT99kSmsVlVKzeNUCU9kadXgJD8BS2zjUf968OpUH7sCCQtQ0Rbkqa8PeyjIva1j5W1deKh6kJ501Eyskas8zdJOvgH99DQPGgYMua4gy/EhLCLMw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=GKaJC2df; arc=none smtp.client-ip=209.85.216.49 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GKaJC2df" Received: by mail-pj1-f49.google.com with SMTP id 98e67ed59e1d1-38101f85591so3251563a91.1 for ; Sun, 23 Aug 2026 20:34:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542476; x=1788147276; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=F7loPKjk85S1XKwGILHvPGhD2hPmSAD1/re7dQ/3iUc=; b=GKaJC2dfS09SwGoGo9Dsv4oZdaaydJdk03fu2ZJHwxCbiq5r2AFDDf4vfFcRodeArt smuEfj49loWgVB1I44xGBQ0f3sG/D2gxJ3ASBx/x8ixrSdxZODdIS2lJDQttR9COhqMb CU7yeHkEtpSnqIhUHU8jXBImS1csD2JFjewXwFyhAezWtMeafmp5loNPEqTvBy1QSVCe 9Isq10WjIIHnx0c8jL/roME67dAE+eMmRSc4TNkkCetV33pKHv3aiiUdQ3+Y9/+vHlYB FmjHidnAj+1z+UzDyI+M0w6z/qTfHJuROq9mDti2q4tCj8xDxn/SXB0bo84UehD/bfU2 diyw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542476; x=1788147276; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=F7loPKjk85S1XKwGILHvPGhD2hPmSAD1/re7dQ/3iUc=; b=C/lTREX5xCF0c3zyACFYHWzMvvthfC87myC8zzmDBRMYTY+z+Uy8jgbMOkNushk7GO 7NLaQaaxk7JE6TNFCm0hfeK3bcuFvD8bBMBhgKzOVwln8fA23uvGgs5Yzml+uqxb4LBR UyyW3W6hPHrKYAnXYJeJRqtDzJ6BQILuVgJyeXg80Or69a417x3FJ2qTrntl/8vfbSrp aZ8evIYPDxAk7WEi9qmnpwTCnnTkY8Qvjn3bPRfaZCi/L+5TxJgtlI+QRdTfP+vNXDk0 B7CkWF51oXKwZ5BXN6zHEDuvSSvWGzMxw99Q1YFHabC2jE09GcUCJPzti6Jq/Z9yYy17 /K4g== X-Forwarded-Encrypted: i=1; AHgh+RolLDeuFgTYa8CacaDWnP3/LlStQoxd2e3XRfBfG+DvmziesaU/WgG5Je1lVwtDLRpWVouNDIsdjwLUCkY=@vger.kernel.org X-Gm-Message-State: AFuF++lfxVS+JP9cwcsjMq7F9/n2Ri4xpZcFsVBb1RKc5/0csIY8sWaq tf9BPKsQHPg+hckz573bopXho9VKriDtSU/4En5fJ/jVJEOYu0xU3qBn X-Gm-Gg: AR+sD12lryFGgA+5aq84sZcBmevQvuw29jRkpO1jnOmv7goPQGgu1LzsJolLrWPxuFe BzrfMroslwM7f0mr2qlWySKY/pEXclE58llrKGf0uEU202VVcb0xGB/nwXbW5LFVsmCnacYVNI2 SThr0n1IGmYHByTz2t+d9x1LhVE0SX+JFNPVCtMU46PVj9qkVTOWsXV6AspIdeEc8Z6PhmJYVy3 5W1suiED1bdvCiMDnFXOfDM6k1SwK1hQiCIxKNC7mHE6yWjecWaX5XWeVUQCYYZoxIlWsIDuehj aReHX4Kt3W2N625OwABKSSRGpzdR+3nU+X3+rgBtwA0aY55C88ZWin871u99KwGeYzsqQEVkv7S 0IcqyVGqwcGcl9iWEJ38zkuSI7vOiQe7LbA+evWinYYZZ4QH7wo7cOSrEx6NL1Te1kDe5B97LAf 62Ww1F83j0YGi3JfCUxV2Sw0YmNjBBIJzHBUz0YdAR+0ni+1263Nhj2rLkHNqbcN7XLBO1oc/Gh 0EPZbAwJG4= X-Received: by 2002:a17:90b:3e8d:b0:38e:9ca8:e99 with SMTP id 98e67ed59e1d1-395c4fa444bmr13960149a91.5.1787542476163; Sun, 23 Aug 2026 20:34:36 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:35 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 5/8] tcp: do not inherit out_of_order_queue from parent Date: Mon, 24 Aug 2026 12:32:49 +0900 Message-ID: <20260824033331.1084971-6-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A child gets a copy of the parent's out_of_order_queue, which can be non empty when/if parent morphs from listener to active session. Parent and child then point at the same rbtree. The parent is no longer a listener, so inet_csk_reqsk_queue_add() forgets the child immediately, and tcp_disconnect() frees the skbs the parent still owns. The parent's own root and ooo_last_skb are left alone, so it keeps using those skbs. That is a use-after-free, and the parent frees them a second time when it closes. In short: peers the socket owner socket(AF_INET6) setsockopt(TCP_DEFER_ACCEPT, 30) bind(), listen() connect(the listener) // bare ACK deferred, the request stays connect(AF_UNSPEC) connect(the new peer) send(the new connection) // it starts one byte past rcv_nxt, so it lands out of order tcp_data_queue() tcp_data_queue_ofo() // the parent's queue fills up send(the old connection) tcp_check_req() tcp_v6_syn_recv_sock() tcp_create_openreq_child() // the child gets the same rbtree inet_csk_complete_hashdance() inet_csk_reqsk_queue_add() inet_child_forget() tcp_disconnect() skb_rbtree_purge() // the parent's skbs are freed send(the new connection) tcp_data_queue() tcp_data_queue_ofo() rb_link_node() // use-after-free write KASAN log: BUG: KASAN: slab-use-after-free in tcp_data_queue+0x1708/0x1df0 Write of size 8 at addr ffff888012ad5408 by task repro/135 ... Call Trace: tcp_data_queue+0x1708/0x1df0 tcp_rcv_established+0x441/0x1830 tcp_v4_do_rcv+0x47e/0x730 tcp_v4_rcv+0x171c/0x2040 ip_protocol_deliver_rcu+0x5c/0x280 ip_local_deliver_finish+0x15a/0x2e0 ip_local_deliver+0x107/0x370 ip_rcv+0x3b1/0x3d0 ... Allocated by task 135: __alloc_skb+0xd0/0x370 alloc_skb_with_frags+0x7d/0x330 sock_alloc_send_pskb+0x490/0x4e0 raw_sendmsg+0xd52/0x1850 ... Freed by task 133: kmem_cache_free+0x26f/0x5f0 skb_rbtree_purge+0x73/0x90 tcp_disconnect+0x1be/0xd60 inet_child_forget+0x41/0x140 inet_csk_complete_hashdance+0x4d0/0x520 tcp_check_req+0x9f9/0xff0 tcp_v6_rcv+0xb9f/0x1e90 ... The buggy address belongs to the object at ffff888012ad5400 which belongs to the cache skbuff_head_cache of size 232 The buggy address is located 8 bytes inside of freed 232-byte region [ffff888012ad5400, ffff888012ad54e8) We need to make sure this can not happen, by initializing the queue after socket cloning. Very similar to commit 8b485ce69876 ("tcp: do not inherit fastopen_req from parent") Fixes: 9f5afeae5152 ("tcp: use an RB tree for ooo receive queue") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- Changes in v2: - Add the trigger sequence and the KASAN log to the commit message. - v1: https://lore.kernel.org/all/20260817090319.3897799-4-imv4bel@gmail.co= m/ --- net/ipv4/tcp_minisocks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 0c3b35a381e327..7fe318d9e0aed2 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -591,6 +591,7 @@ struct sock *tcp_create_openreq_child(const struct sock= *sk, newtp->total_retrans =3D req->num_retrans; =20 tcp_init_xmit_timers(newsk); + newtp->out_of_order_queue =3D RB_ROOT; WRITE_ONCE(newtp->write_seq, newtp->pushed_seq =3D treq->snt_isn + 1); =20 if (sock_flag(newsk, SOCK_KEEPOPEN)) --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (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 47B5A372B57 for ; Mon, 24 Aug 2026 03:34:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542483; cv=none; b=pTGoRSaAt+vABuRlY4SnbdjkeR75RKldbSkaOiWuRxP9ZY8IcT7X3wLA7eQcYtFMQZWU+oPCJIvvldDlpaA/enjsCWIBHmCwAB3sa+3wzBWkxzrqqqXADqHRRiQwvKHwcf4CEdTi2tXQUlzpalWkp0lREFKiwanz1ZlDOzIsnys= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542483; c=relaxed/simple; bh=1Rvyp0xy3Ragc0E9ZWd9WCRPxmJ4/WJmfFVSVWG1dfc=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=l8R8IJUeW13e5juYClTDc5bily4ddH3Xg8w1mIFk5QGTE470Jlj7J0zeeG8lLkZWOg2XvCuYVmM6BfDAYd/ciduISXP4NzIBxbHmy8rtpJ4RWxl13mGcpcJXJAeIlVQDhUB4GG4t4N1Ejk0bYrKYlTvS+kBi/qmmW06h3s+l5Lg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=qPG3jJv5; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="qPG3jJv5" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-2caed617615so29817405ad.3 for ; Sun, 23 Aug 2026 20:34:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542481; x=1788147281; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=aOYu1j3wk0HoiBBxP9GSyUREhQRtNv0dyeHn1pEGiXc=; b=qPG3jJv5/RrWQmUQZeL6Sc8NbZjMvCCRfGdqxQNwwNUyhoQFiDJb0DLWJY2u9SPXxp RTWrrm7JNcke0mM7P2SblSsY/FByFDFgGCqd3BmOb8+I095nAlh/gk1iq4QW9c8RrZTm pCo5ibQ5GsWBbnyBU+f/EdXx1loPKKp/ns45Nprmfkbp1oHehOukYsEbmDJrqM5zYv/9 5IeO6woME+I0LGOIJy8kKJ0+kjEMwjFbKxbpg6KWdSbr69Ai0J0ikEcXDJVopK62UUbo rzqcCBQxWK5XF4w5SvRRK9Gw6vyEXdNO2GCLj0X+i6f5oRZdLZziK4aoGyEL2fuTRXoU DSZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542481; x=1788147281; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=aOYu1j3wk0HoiBBxP9GSyUREhQRtNv0dyeHn1pEGiXc=; b=pQtrN94CabSpuz2ijdLPr0pQd+pPrjioT12qosPfod4s/mwSarQDSeO/HfWiJK3VgG pOK5qOVAHAJ5P0Ry0+W60g7d8omkxTvaZgLa0zSNdhqKb+aZW0Qpt9preuwdH/MaxKdu 2il96qv33f08r8SM1tHJitOcQKc9K7dARcGMQEsQRnbE7kfv5HQBgayV2gcu8bD3gEZe vFXdBUZhYmWYUBY4/c3mLSLkwHgfUpn53tVhwbKKaQgooBWOrEGZQ1dF8yQBNKtYEWgb jAIkwYbNcRKZ06V1Oei0jgy83bb+PY8LTyPbOEgFD42v/IM8fJtsXRQsWgQ8vcl7WK6z T+Ng== X-Forwarded-Encrypted: i=1; AHgh+RrMAQsz45183d5TCgy9Qxr0cruO7H5Yl6w0vw1i8iaOweAqUJUZ5UR5ijUfUCZNGL9SNX0ADuvJRTLRBNk=@vger.kernel.org X-Gm-Message-State: AFuF++kJj/h5bxNWRfp+ha1k+VDVjL6fDfI6F2q+7j0c/OHY+K8ck1GM mSbvDFxq9HJOht1jRf2dfWFr8Q2eGno07PwsaMWPUaKar2UlcKZKyiUn X-Gm-Gg: AR+sD12lqbLpnxq1/hIoOVGhZlFkjtjG2lRGWHpemOr3MaDIfxc/cGFzJGAFXezMxcz tUxWeDWOBDNAZhWeqK1XZAT9a/cWtWiVR6VuBdxLpjeC3HWCuu5YdEToGh1GYSEEgLtD+ygnMg4 i0roHRXx0wMV7mBQz/PDgYCCTR7s5s2w12686Mm7nRm4MBMAR/nqTjln7vR2zFYElZEWVgEtfb1 0dgi+B5pQyaI8+gCPQsTi9+0sj3/GpgGpefyIWfH5xqb178nQEYDsxWGN4wRd96ZoMOe9qRHdnE nScdkh4LJhZ7H+cIM/2vU/s7RQfq6wI1ohir7BK91iSoIiWemaApIzcvdGgtpKKK3GB65PqlFqV EP89x8kgsISDWLA7RXOBfWRiCfFCrbNZJ3gDZaPxdPgQPNs8mNtCc8xOiRQ+7gBrnnXSpDlak5b ygibwit41zf1h4fc73z/s3xAaCLNO9IcLKDRys8uXDHc83WFsy7/0gEUF7YRZXfNYp7HERWnEut rHDc/L2cUY= X-Received: by 2002:a17:90b:28c5:b0:38e:75f3:ad4d with SMTP id 98e67ed59e1d1-395df11a0damr28694326a91.7.1787542481551; Sun, 23 Aug 2026 20:34:41 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:41 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 6/8] tcp: fix use-after-free in the lockless listener path Date: Mon, 24 Aug 2026 12:32:50 +0900 Message-ID: <20260824033331.1084971-7-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" tcp_v{4,6}_rcv() calls tcp_v{4,6}_do_rcv() without holding the socket lock when sk->sk_state is TCP_LISTEN. Every other path into tcp_v{4,6}_do_rcv() holds it. tcp_v{4,6}_do_rcv() and tcp_rcv_state_process() below it read sk->sk_state again. A listener can leave TCP_LISTEN through connect(AF_UNSPEC), and if that happens in between, the second read returns a different state. tcp_rcv_established() or tcp_rcv_state_process() then runs without the lock. If the second read returns TCP_SYN_SENT, the incoming SYN is treated as a crossed SYN and reaches tcp_send_synack(). When the SYN skb at the head of the retransmit queue is skb_cloned(), that function replaces it with a copy and releases the original with tcp_rtx_queue_unlink_and_free(). The original is the skb that a thread on another CPU is transmitting right now in __tcp_transmit_skb(). skb_cloned() is true because the clone made for that transmit is still alive. Once the transmit returns, tcp_update_skb_after_send() calls list_move_tail() on the skb's tcp_tsorted_anchor. In short: socket(AF_INET) -> bind() -> listen() // the socket that changes state socket(AF_INET) -> bind() -> listen() // the peer Several threads keep opening new sockets and connecting to the first socket's address. Another thread repeats this on the first socket: connect(AF_UNSPEC) // TCP_LISTEN -> TCP_CLOSE connect(peer address) // TCP_CLOSE -> TCP_SYN_SENT // another CPU still sees a listener, handles // one of those SYNs without the lock and // releases the SYN skb that this connect() // is transmitting // -> use-after-free connect(AF_UNSPEC) listen() // TCP_LISTEN again KASAN log: BUG: KASAN: slab-use-after-free in __list_del_entry_valid_or_report+0x14/= 0x140 Read of size 8 at addr ffff88800a5d1460 by task poc/125 ... Call Trace: __list_del_entry_valid_or_report+0x14/0x140 tcp_update_skb_after_send+0x62/0x170 __tcp_transmit_skb+0xe33/0x1e40 tcp_connect+0x1b67/0x2490 tcp_v4_connect+0x998/0xab0 __inet_stream_connect+0x22c/0x700 inet_stream_connect+0x48/0x70 __sys_connect+0x101/0x130 ... Allocated by task 125: __alloc_skb+0xd1/0x370 tcp_stream_alloc_skb+0x2d/0x2b0 tcp_connect+0x72d/0x2490 tcp_v4_connect+0x998/0xab0 __inet_stream_connect+0x22c/0x700 inet_stream_connect+0x48/0x70 __sys_connect+0x101/0x130 ... The buggy address belongs to the object at ffff88800a5d1400 which belongs to the cache skbuff_fclone_cache of size 472 Instead of taking the lock, keep the lockless path from reading sk->sk_state again to decide how to process the packet. Move the TCP_LISTEN handling out of tcp_rcv_state_process() into tcp_rcv_listen_state_process(), and let the TCP_LISTEN branch of tcp_v{4,6}_rcv() call a new tcp_v{4,6}_rcv_listen(). Listener processing does not change. The TCP_LISTEN arm of tcp_v{4,6}_do_rcv() is left alone, because a socket can finish listen() after the state check and a backlogged skb is then processed there. Fixes: e994b2f0fb92 ("tcp: do not lock listener to process SYN packets") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- include/net/tcp.h | 2 ++ net/ipv4/tcp_input.c | 64 +++++++++++++++++++++++++------------------- net/ipv4/tcp_ipv4.c | 44 ++++++++++++++++++++++++++++-- net/ipv6/tcp_ipv6.c | 44 ++++++++++++++++++++++++++++-- 4 files changed, 123 insertions(+), 31 deletions(-) diff --git a/include/net/tcp.h b/include/net/tcp.h index 2c5b889530b556..add438d6561be5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -392,6 +392,8 @@ void tcp_write_timer_handler(struct sock *sk); void tcp_delack_timer_handler(struct sock *sk); int tcp_ioctl(struct sock *sk, int cmd, int *karg); enum skb_drop_reason tcp_rcv_state_process(struct sock *sk, struct sk_buff= *skb); +enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk, + struct sk_buff *skb); void tcp_rcv_established(struct sock *sk, struct sk_buff *skb); void tcp_rcvbuf_grow(struct sock *sk, u32 newval); void tcp_rcv_space_adjust(struct sock *sk); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0f60a1dbf92746..77af18fba66b4d 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -7141,6 +7141,42 @@ static void tcp_rcv_synrecv_state_fastopen(struct so= ck *sk) tcp_rearm_rto(sk); } =20 +enum skb_drop_reason tcp_rcv_listen_state_process(struct sock *sk, + struct sk_buff *skb) +{ + const struct tcphdr *th =3D tcp_hdr(skb); + SKB_DR(reason); + + if (th->ack) + return SKB_DROP_REASON_TCP_FLAGS; + + if (th->rst) { + SKB_DR_SET(reason, TCP_RESET); + goto discard; + } + if (th->syn) { + if (th->fin) { + SKB_DR_SET(reason, TCP_FLAGS); + goto discard; + } + /* It is possible that we process SYN packets from backlog, + * so we need to make sure to disable BH and RCU right there. + */ + rcu_read_lock(); + local_bh_disable(); + inet_csk(sk)->icsk_af_ops->conn_request(sk, skb); + local_bh_enable(); + rcu_read_unlock(); + + consume_skb(skb); + return 0; + } + SKB_DR_SET(reason, TCP_FLAGS); +discard: + tcp_drop_reason(sk, skb, reason); + return 0; +} + /* * This function implements the receiving procedure of RFC 793 for * all states except ESTABLISHED and TIME_WAIT. @@ -7152,7 +7188,6 @@ enum skb_drop_reason tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb) { struct tcp_sock *tp =3D tcp_sk(sk); - struct inet_connection_sock *icsk =3D inet_csk(sk); const struct tcphdr *th =3D tcp_hdr(skb); struct request_sock *req; int queued =3D 0; @@ -7164,32 +7199,7 @@ tcp_rcv_state_process(struct sock *sk, struct sk_buf= f *skb) goto discard; =20 case TCP_LISTEN: - if (th->ack) - return SKB_DROP_REASON_TCP_FLAGS; - - if (th->rst) { - SKB_DR_SET(reason, TCP_RESET); - goto discard; - } - if (th->syn) { - if (th->fin) { - SKB_DR_SET(reason, TCP_FLAGS); - goto discard; - } - /* It is possible that we process SYN packets from backlog, - * so we need to make sure to disable BH and RCU right there. - */ - rcu_read_lock(); - local_bh_disable(); - icsk->icsk_af_ops->conn_request(sk, skb); - local_bh_enable(); - rcu_read_unlock(); - - consume_skb(skb); - return 0; - } - SKB_DR_SET(reason, TCP_FLAGS); - goto discard; + return tcp_rcv_listen_state_process(sk, skb); =20 case TCP_SYN_SENT: tp->rx_opt.saw_tstamp =3D 0; diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 302afe8ebcbcc3..2fa8958380a5b9 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -1828,7 +1828,7 @@ u16 tcp_v4_get_syncookie(struct sock *sk, struct iphd= r *iph, INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entr= y *, u32)); /* The socket must have it's spinlock held when we get - * here, unless it is a TCP_LISTEN socket. + * here. * * We have a potential double-lock case here, so even when * doing backlog processing we use the BH locking scheme. @@ -1906,6 +1906,46 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *s= kb) goto discard; } =20 +/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. = */ +static noinline int tcp_v4_rcv_listen(struct sock *sk, struct sk_buff *skb) +{ + enum skb_drop_reason reason; + struct sock *nsk; + + reason =3D psp_sk_rx_policy_check(sk, skb); + if (reason) + goto err_discard; + + if (tcp_checksum_complete(skb)) + goto csum_err; + + nsk =3D tcp_v4_cookie_check(sk, skb); + if (!nsk) + return 0; + + if (nsk !=3D sk) { + reason =3D tcp_child_process(sk, nsk, skb); + sock_put(nsk); + } else { + reason =3D tcp_rcv_listen_state_process(sk, skb); + } + if (!reason) + return 0; + + tcp_v4_send_reset(sk, skb, sk_rst_convert_drop_reason(reason)); +discard: + sk_skb_reason_drop(sk, skb, reason); + return 0; + +csum_err: + reason =3D SKB_DROP_REASON_TCP_CSUM; + trace_tcp_bad_csum(skb); + TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); +err_discard: + TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); + goto discard; +} + enum skb_drop_reason tcp_add_backlog(struct sock *sk, struct sk_buff *skb) { u32 tail_gso_size, tail_gso_segs; @@ -2243,7 +2283,7 @@ int tcp_v4_rcv(struct sk_buff *skb) skb->dev =3D NULL; =20 if (sk->sk_state =3D=3D TCP_LISTEN) { - ret =3D tcp_v4_do_rcv(sk, skb); + ret =3D tcp_v4_rcv_listen(sk, skb); goto put_and_return; } =20 diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 9e9155b1b3aa75..a2deda9a4258bc 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1556,7 +1556,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct= sock *sk, struct sk_buff * INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entr= y *, u32)); /* The socket must have it's spinlock held when we get - * here, unless it is a TCP_LISTEN socket. + * here. * * We have a potential double-lock case here, so even when * doing backlog processing we use the BH locking scheme. @@ -1704,6 +1704,46 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *s= kb) return 0; } =20 +/* @sk is not locked here and can leave TCP_LISTEN; do not test sk_state. = */ +static noinline int tcp_v6_rcv_listen(struct sock *sk, struct sk_buff *skb) +{ + enum skb_drop_reason reason; + struct sock *nsk; + + reason =3D psp_sk_rx_policy_check(sk, skb); + if (reason) + goto err_discard; + + if (tcp_checksum_complete(skb)) + goto csum_err; + + nsk =3D tcp_v6_cookie_check(sk, skb); + if (!nsk) + return 0; + + if (nsk !=3D sk) { + reason =3D tcp_child_process(sk, nsk, skb); + sock_put(nsk); + } else { + reason =3D tcp_rcv_listen_state_process(sk, skb); + } + if (!reason) + return 0; + + tcp_v6_send_reset(sk, skb, sk_rst_convert_drop_reason(reason)); +discard: + sk_skb_reason_drop(sk, skb, reason); + return 0; + +csum_err: + reason =3D SKB_DROP_REASON_TCP_CSUM; + trace_tcp_bad_csum(skb); + TCP_INC_STATS(sock_net(sk), TCP_MIB_CSUMERRORS); +err_discard: + TCP_INC_STATS(sock_net(sk), TCP_MIB_INERRS); + goto discard; +} + static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, const struct tcphdr *th) { @@ -1891,7 +1931,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff= *skb) skb->dev =3D NULL; =20 if (sk->sk_state =3D=3D TCP_LISTEN) { - ret =3D tcp_v6_do_rcv(sk, skb); + ret =3D tcp_v6_rcv_listen(sk, skb); goto put_and_return; } =20 --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 B76B4374A12 for ; Mon, 24 Aug 2026 03:34:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542489; cv=none; b=TPYhNFtTjceJqXI+croAkSmlGg90hsJPpy4sprVzIc/hukky3KSzU/5qBz3DKWFyX1Fs1oCkD1BYV/3LVO6sxtDxghmR2q4SStpjFJnxfmpINTvZCPXfTb0EhGRt/5mh8aqJdZxpkdRjq1Gf5NHdEH0zkVeOE169HmDM18XDMOw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542489; c=relaxed/simple; bh=sz4I1sq4K0b/4zGjd0FzYdICKmLEOx+P2s0EyxNw1ck=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UsExpWf9OT5TVYPUKtJ31HrdpJX2ThevCo5GmrQNSY7roML6soZUHb8r0xcyXGzr2eXYMqPFKnn8AmlOUGw0Xk/2GdKgTCZJs3cmBID5gfRzSjuDXrdk8TLKZ9D26KGsImMYcXfhf9VfZY6uiXKizBRpL/lkrKXEsWjiyeDvTAg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=UD75Iysx; arc=none smtp.client-ip=209.85.216.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="UD75Iysx" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-38e42560ebcso2205304a91.1 for ; Sun, 23 Aug 2026 20:34:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542487; x=1788147287; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=h3czPEGgc8kYZ51pcfr/0w7zOEtrgQWrgOFC5Loyaz4=; b=UD75Iysx8wdyY58cFjzUVXdFvohgn4QrSvPOepcBrVuUaLz8D+ip2mLntd5qFPE2Fr lEZzPZqcny2Ny6mYcbHK6j8vjnQNplMDE4sW9vUH5s/2xn0RIEI9X/FzQDMApEmfCYow Cs4bo0vlGl1Do3QCubUmrZBaQDo0ojeod82X2JrVhpkI48pZxgMXyH9Hspah+vnHWSO7 r8So9mIeFEscjcV2qFT6lUpsIGrIqy/2cShFPckUz4fpabmhGctpyEFlNeXuy52JgWAE ZoXtRc44mNiGBHPoq5gjWN8nT2tNCA5JhwDV8A+cWsboX59fhoBx8CBYUDFBxbpqWR86 i0qA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542487; x=1788147287; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=h3czPEGgc8kYZ51pcfr/0w7zOEtrgQWrgOFC5Loyaz4=; b=Vd18fMdV4tv3nSQ35ACM9sf0p+koJG+pssHr4caKQo5WYO3u2/c9iTgLWffV6xjhGW sFhBgLsMK40obOkyddnlC7MVuLHjDa2t5EJUTieAmZ5bTizIQJTtY1K1Ev1ChYTALdj3 hqxjUwkHwCQvZWtG2Ipi7todHBI/MKiV68I60TL2H2h2iq9jPL2CnQr3qpcE8j1EU+uC Mx0itL4T4rOCuHj3XPMsQV8af9C8o+u0rs5sui58iGtw5mAGSLImCg5quxQdia2JOmow 5cMcYpUAn+/A/PqJpH8bbrUpDXevS44KFpxlND3nUgGtxrdSHFvkB3zugf6dIb50no5s 2UOA== X-Forwarded-Encrypted: i=1; AHgh+RrSRc+nGvO/dap1VdbX5R7wJ7V8Sv9dAKouutQKwqhmGic/G5ID60KLn22cRXNhuePN5iMgHY6eZ3xp2M0=@vger.kernel.org X-Gm-Message-State: AFuF++lN43PdKseXtbEg3GbkOKkjL2ndiGhSox6ItBMX8yA1ZOc1dTF0 LEu2z+ILeAwC4TZ9QQtXHJIxYvvabDupS1VC9VTrESlGvyNGKDK9/dyx X-Gm-Gg: AR+sD12lq7+EPRSFtOjIOspe7II63DZqn+DfAhZoEhV2jiMsDB15uCBKnnph7mdiscS Zpd5eKoCsMDumkN1uqMcYG1sTnunP6r4+rLipZ3Z+hssXf7BThBMp37kfuSWZsT83yCuSBvmZ3T OjPrfVp4VLF56fNXtLe2d7q3T0q4WxFINeAfQGLh9EDeFMZW+XAJq9x7clWVDQ+1aMFxegdECmx oZKa2u5uqmwcmkZIPDkwiwge1DYO8Tf3+h7IOB5unWIm5qPMHUsJsIAWVgIAoiUokoTFoGFpjMX Q9xyE+3g1xhdmOEGjm99HgWL2KTqkK5Z+8Achdbdze1XMLSVXaXaCUoksFohMTHwF0d6gFsOqpS iRmDsDj3GZZlzOP7TnFFQYjs4nRoef1YooCtWeHBU/4CCOQ6TcXW5SlAQjFdcwq3gnI3FhFWMUG +/lufgGzzLv7GSo7Pm54z4FwhqGA1yEMK29WiUXwHZ1Us6v/6JdRM1jPen4fv7WcdFTxCMEd0YY Fv4x/Htq0PrgWVhIh2BkQ== X-Received: by 2002:a17:90b:5805:b0:38e:485c:ebd3 with SMTP id 98e67ed59e1d1-395c3a514a5mr42206353a91.15.1787542486850; Sun, 23 Aug 2026 20:34:46 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:46 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 7/8] net: clear sk_tsq_flags in sk_clone() Date: Mon, 24 Aug 2026 12:32:51 +0900 Message-ID: <20260824033331.1084971-8-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A socket returned by accept() can be freed while its fd is still open. A setsockopt() on that fd then hits a use-after-free. TCP_TSQ_DEFERRED owns a socket reference. tcp_tsq_handler() sets the bit and calls sock_hold() when the socket is owned by user, and tcp_release_cb() clears the bit and calls __sock_put(). sock_copy() gives the child the bit but not the reference, so the __sock_put() that runs when accept() locks and unlocks the child has nothing to pair with. The socket is freed by the next put, which in the log below came from a timer. A listener can be holding this bit. An established socket becomes a listener again through connect(AF_UNSPEC) and listen(), and tcp_clear_xmit_timers() only calls hrtimer_try_to_cancel(), so a pacing callback that is already running survives. That callback sets the bit while accept() holds the socket lock, and in the same window the child is created in the TCP_NEW_SYN_RECV branch of tcp_v4_rcv(), which does not take the listener lock. All seven bits in sk_tsq_flags describe work pending on the parent, and four of them own a reference. They are set in four different places, so clear the whole word in sk_clone(). In short: socket(AF_INET) -> setsockopt(SO_MAX_PACING_RATE, 100000) -> setsockopt(TCP_MAXSEG, 1200) -> bind -> connect(peer) send(64KB) // arms the pacing timer, sock_hold() connect(AF_UNSPEC) // stop being connected listen() // become a listener again setsockopt(TCP_DEFER_ACCEPT) // another socket connects, and with TCP_DEFER_ACCEPT there is no // child yet accept() // the child is created when one byte // arrives. while accept() holds the // lock the pacing callback sets the // bit, and the child is cloned by // the receive path, which does not // take the listener lock // a timer on the child does the last put and the socket is freed setsockopt(accepted, TCP_NODELAY) // use-after-free KASAN log: BUG: KASAN: slab-use-after-free in sock_common_setsockopt+0x44/0x80 Read of size 8 at addr ffff88800e2ab668 by task repro/94 ... Call Trace: sock_common_setsockopt+0x44/0x80 do_sock_setsockopt+0x15e/0x2b0 __sys_setsockopt+0x9e/0xe0 __x64_sys_setsockopt+0x64/0x80 ... Allocated by task 95: sk_prot_alloc+0x45/0x170 sk_clone+0x49/0x960 inet_csk_clone_lock+0x29/0x2c0 tcp_create_openreq_child+0x2a/0xf20 tcp_v4_syn_recv_sock+0xd3/0x7e0 tcp_check_req+0x374/0xff0 tcp_v4_rcv+0xc2d/0x2040 ... Freed by task 0: slab_free_after_rcu_debug+0xc5/0x200 rcu_core+0x4de/0xd30 ... Last potentially related work creation: kmem_cache_free+0x11d/0x5f0 __sk_destruct+0x29a/0x3d0 call_timer_fn+0x12f/0x3f0 __run_timers+0x4a4/0x5e0 ... The buggy address belongs to the object at ffff88800e2ab640 which belongs to the cache TCP of size 3200 Fixes: 73a6bab5aa2a ("tcp: switch pacing timer to softirq based hrtimer") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- net/core/sock.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/core/sock.c b/net/core/sock.c index 098e58b40f304b..06fbb19824e267 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2533,6 +2533,7 @@ struct sock *sk_clone(const struct sock *sk, const gf= p_t priority, newsk->sk_reserved_mem =3D 0; DEBUG_NET_WARN_ON_ONCE(newsk->sk_drop_counters); sk_drops_reset(newsk); + newsk->sk_tsq_flags =3D 0; newsk->sk_send_head =3D NULL; newsk->sk_userlocks =3D sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; atomic_set(&newsk->sk_zckey, 0); --=20 2.43.0 From nobody Mon Sep 28 09:58:19 2026 Received: from mail-pl1-f181.google.com (mail-pl1-f181.google.com [209.85.214.181]) (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 D5A7136894D for ; Mon, 24 Aug 2026 03:34:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542494; cv=none; b=W+DNTAJzrUYY+buR9pEzWc6+D1B3l72hqM03ct4BTiw1pzqBZ5SJ3YiAQwPktUmMjaJ0p6OWkpF5cOWiPlk6tBFspZLv2tm3u+6wc8vvMyW8VYUw1s7392ivOa8oRXZF3gSnSgfu/FLSCYQtaoqv3eWuHtKEjQLJIP3SZ3Etbx0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787542494; c=relaxed/simple; bh=tXbprwIsw4+TnWQEjWhGgnauvC05A6g8kXeB1lZBCK0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qNLHj7hAQIerGYgqk3kDxmPRIkEQjKa+j40Cbm6b1Ud/sWi6V7JM4kyMfNGjI8Xk/YNIDOsUMczIyUOz5IOaC3KTScpXU4JSdnAQQTqwabAHSZ09+udQWytqX5KpRrz9DhTSIcmPOwQK+z1riAqKQishOOQkJC4pLwWUis88/vY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G5rp0jFo; arc=none smtp.client-ip=209.85.214.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G5rp0jFo" Received: by mail-pl1-f181.google.com with SMTP id d9443c01a7336-2cc891373e0so32406185ad.2 for ; Sun, 23 Aug 2026 20:34:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787542492; x=1788147292; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=1ZjZkSQf+Zktufc09rNjCOpfzvoTH5+6Bb0FnK3Vps4=; b=G5rp0jFoCjnG4bg8/dOC+KBVRCWYOQxDWcKFKxH5EWfeg4ji9GHoKUNNNE07W/LluB qD+MvkprQQmp083+qbwWLN51UAwGVaqXaQmw5rMa+LkI9E9Op1CETnumK1pOopshgyuf wROyb0ZdZzzBwGNxvAKpFJqLwD4yy0STfJalC1eNYOpwPeYn4Vbq3gVjt3R8SNSJsCox wgmTfY4lpPhenREZIJTCTBfJRqRb/xDVKKA5lzPs2iBtbXf2RgL/fb6VEdJhIeWDznWk lF85YvoIlfPjs4BVLHB7bvNICwpLeWEQstmdtzsVU71wvzyRdIvyjEoUOP7yt8A3Iqq1 HybA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787542492; x=1788147292; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=1ZjZkSQf+Zktufc09rNjCOpfzvoTH5+6Bb0FnK3Vps4=; b=RrkTRUoAd09dW2sf10+DnjcBI6ppbF6BC8EDIv9LbJOK3hgnHelY+sH7/vxTmGk6rR UE+RtRETboGJ1N6MZI63gf61bVO1acaBZN4/dIZ6RukRdkPoumbWKsVBIeDWrFtZNI8P 97s9Yv1WlOmum6oKHQpkF0DXQr/KWTwqNrsT3hNus5nbPEzSbGxTcTjbRecEwfKUYHwW 9ayrjeB0e0Rcm3UCGogjuMtJZnoHXZiWtbVUp9piCp/TRB0yzevb8SXpqNTrfaJcP3T7 P5KM5RYsjqYZh7m+XvPi3CTMw/gfeBfOzKgTA7ZJaKoyh7R3BXAFUvfo5KxQcxiKJk/c 1rEg== X-Forwarded-Encrypted: i=1; AHgh+RoXKuYSfLEYpstT6nUby4i24oLfaPbDXlzgFu4TSKMG4WMOGM8Og++O7J/fji+QFkWDuwaB+mxZeT7amTI=@vger.kernel.org X-Gm-Message-State: AFuF++lh9K1JthBvJwXmmKdSouStJlkC0E8bYW026DlJ6t+lFBdbNsGj N+S3TXzm3AjCfdzpOM9SpYheXDmrqIbD151w01B2lBmMZvfE/mnPReqS X-Gm-Gg: AR+sD12iHx/GV2lHdhV65tzLObH68pucZyHk8IQmI3xJjSKdaCwctnvlQIpDMG7rL76 CKpv6oo9FjUGfH5VyXxRJlMQ5eWNRySWVjVVOQ2uPbP2eERkSpOpku6BVVCt7uXV/YpFqjGESRM fBAg3oavFbxWT3UjD7Ep7qhXgu+xW+ViXrbAE9Ez+SS1lSX1HPCEjSqafVz0IO3R9KHqqe85KhW swGiHw4PJ/BPYqnnPWuw7Z0eSdzyJ4athi2KgIdljvcoW/2v8J9tz5IAfHBoQGFtwIG1AbAN7ns ndYFjWjiEpPXwS5Zg4m6yMFUTk5JhMSmNJGMvEKDBpeUMuF/bk6YYbb7EOhxdFFsD/Jd191Mk2f fTWUSsXoHhydJZtvsTVSd2F+Dln7Co0t2bqmYY8NI7b9Ja33NAZPm74Dl471Wrbof3iA2unCFFp GouRC24PawRkJQAe9XBVOP+kuC85gM6mrNfNOu36eKRy2vR6bH3JlR2KWhe4LDm47B74kViBHcc Q+1URCFpac= X-Received: by 2002:a17:90b:4ac6:b0:38f:18f9:785 with SMTP id 98e67ed59e1d1-395df13ced5mr26345382a91.8.1787542492202; Sun, 23 Aug 2026 20:34:52 -0700 (PDT) Received: from v4bel.. ([58.123.110.97]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-395c8fd34d9sm4227256a91.1.2026.08.23.20.34.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 23 Aug 2026 20:34:51 -0700 (PDT) From: Hyunwoo Kim To: davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, ncardwell@google.com, dsahern@kernel.org, idosch@nvidia.com, kuniyu@google.com, horms@kernel.org, willemb@google.com, andrew+netdev@lunn.ch, kees@kernel.org, jiayuan.chen@linux.dev Cc: kerneljasonxing@gmail.com, ij@kernel.org, martin.lau@kernel.org, shakeel.butt@linux.dev, matttbe@kernel.org, martineau@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, imv4bel@gmail.com, stable@vger.kernel.org Subject: [PATCH net v2 8/8] tcp: do not inherit retransmit state from parent Date: Mon, 24 Aug 2026 12:32:52 +0900 Message-ID: <20260824033331.1084971-9-imv4bel@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260824033331.1084971-1-imv4bel@gmail.com> References: <20260824033331.1084971-1-imv4bel@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A child gets a copy of the parent's retransmit state when it is cloned. On a listener it is all zero, which is why commit eb2c80ca87b1 ("tcp: do not clear packets_out in tcp_create_openreq_child()") and commit 5c701549c9a6 ("tcp: move retrans_out, sacked_out, tlp_high_seq, last_oow_ack_time init to tcp_disconnect()") dropped the initialization of packets_out, retrans_out and sacked_out here. lost_out, retransmit_skb_hint and highest_sack have never been cleared here. The parent can morph from listener to active session while a request is still being processed, and connect(AF_UNSPEC) followed by connect() gets it there. tcp_check_req() does not hold the listener lock, so nothing pins the parent's state between the TCP_LISTEN test and the clone. The child then copies the counters and the two pointers into the parent's retransmit queue. sk_clone() sets sk_send_head to NULL, and tcp_rtx_queue is unioned with it, so the child's retransmit queue is empty. That does not help. packets_out is set again as soon as the child sends anything, and tcp_xmit_retransmit_queue() picks the copied hint over the queue head. When the parent disconnects, tcp_write_queue_purge() frees those skbs, but the pointers the child copied are left alone. The child then gets an ACK, enters the retransmit path and writes into a freed skb. In short: socket(AF_INET) -> setsockopt(TCP_DEFER_ACCEPT, 30) -> bind -> listen // a client connects and sends one byte. the kernel processes // that segment while the steps below run connect(AF_UNSPEC) // stop listening connect(peer) // become an active session send() repeatedly // lower IP_TTL so the peer's IP_MINTTL // drops most of them, and let one // through to get a SACK // parent: packets_out 6, sacked_out 1, lost_out 5, retrans_out 1 // retransmit_skb_hint points at an skb in the parent's queue // the leftover request completes and copies this state connect(AF_UNSPEC) // those skbs are freed listen() // or the child is dropped accept() // the child sends data, one segment is lost, and the ACK that // comes back takes the retransmit path to the copied hint KASAN log: BUG: KASAN: slab-use-after-free in __pskb_trim_head+0x66b/0x900 Write of size 16 at addr ffff888008141530 by task repro/76 ... Call Trace: __pskb_trim_head+0x66b/0x900 tcp_trim_head+0x69/0x540 __tcp_retransmit_skb+0x14e/0x26b0 tcp_retransmit_skb+0x1b/0x250 tcp_xmit_retransmit_queue.part.0+0x3b1/0x970 tcp_ack+0x3382/0x7430 tcp_rcv_established+0x631/0x3a00 tcp_v4_do_rcv+0x449/0x960 __release_sock+0x1f2/0x2a0 release_sock+0x176/0x1d0 tcp_sendmsg+0x30/0x40 __sys_sendto+0x316/0x380 __x64_sys_sendto+0xdb/0x1b0 ... Allocated by task 76: __alloc_skb+0x11e/0x890 tcp_stream_alloc_skb+0x2c/0x5c0 tcp_sendmsg_locked+0x1377/0x3df0 tcp_sendmsg+0x26/0x40 __sys_sendto+0x316/0x380 ... Freed by task 80: skb_release_data+0x554/0x810 __kfree_skb+0x42/0x60 tcp_write_queue_purge+0x6ef/0xf40 tcp_disconnect+0x2fc/0x1e10 __inet_stream_connect+0x6d0/0xdf0 inet_stream_connect+0x52/0xa0 __sys_connect+0xfc/0x130 ... The buggy address belongs to the object at ffff888008141380 which belongs to the cache skbuff_small_head of size 704 We need to make sure this can not happen, by clearing them after socket cloning. A listener always has them zero, so an ordinary passive open is not affected. Clearing only the pointers is not enough: the counters would then describe a retransmit queue the child does not have, and tcp_fastretrans_alert() and tcp_retransmit_timer() warn. Very similar to commit 8b485ce69876 ("tcp: do not inherit fastopen_req from parent") Fixes: 079096f103fa ("tcp/dccp: install syn_recv requests into ehash table") Cc: stable@vger.kernel.org Signed-off-by: Hyunwoo Kim --- net/ipv4/tcp_minisocks.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 7fe318d9e0aed2..2fde196dd302f5 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -660,6 +660,12 @@ struct sock *tcp_create_openreq_child(const struct soc= k *sk, tcp_ecn_openreq_child(newsk, req, skb); newtp->fastopen_req =3D NULL; RCU_INIT_POINTER(newtp->fastopen_rsk, NULL); + newtp->packets_out =3D 0; + newtp->retrans_out =3D 0; + newtp->sacked_out =3D 0; + newtp->lost_out =3D 0; + newtp->retransmit_skb_hint =3D NULL; + newtp->highest_sack =3D NULL; =20 newtp->bpf_chg_cc_inprogress =3D 0; tcp_bpf_clone(sk, newsk); --=20 2.43.0