From: Kuniyuki Iwashima <kuniyu@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>,
Neal Cardwell <ncardwell@google.com>,
Willem de Bruijn <willemb@google.com>,
David Ahern <dsahern@kernel.org>,
Ido Schimmel <idosch@nvidia.com>
Cc: Simon Horman <horms@kernel.org>,
Kuniyuki Iwashima <kuniyu@google.com>,
Kuniyuki Iwashima <kuni1840@gmail.com>,
netdev@vger.kernel.org, Kyle Zeng <kylebot@openai.com>,
Michal Luczaj <mhal@rbox.co>, Hyunwoo Kim <imv4bel@gmail.com>
Subject: [PATCH v1 net-next 1/2] tcp: Do not allow buggy transitions between ehash and lhash2.
Date: Fri, 4 Sep 2026 03:35:28 +0000 [thread overview]
Message-ID: <20260904033543.2635540-2-kuniyu@google.com> (raw)
In-Reply-To: <20260904033543.2635540-1-kuniyu@google.com>
The following state transitions have long been a playground for
syzbot, and recently AI joined in, reporting a lot more bugs.
* listen() + shutdown() + connect()
* connect() + connect(AF_UNSPEC) + listen()
All the fix attempts would add more code to the fast path, which
is not worth it.
Instead of playing whack-a-mole with these edge-case bugs,
let's disallow these transitions.
Note that unhashed_state is placed in the 4-byte hole after
icsk_pmtu_cookie.
$ pahole -C inet_connection_sock vmlinux
struct inet_connection_sock {
...
__u32 icsk_pmtu_cookie; /* 1208 4 */
unsigned char unhashed_state; /* 1212 1 */
/* XXX 3 bytes hole, try to pack */
Reported-by: Kyle Zeng <kylebot@openai.com>
Closes: https://lore.kernel.org/netdev/20260731140512.566464-1-david.lee@trailofbits.com/
Reported-by: Michal Luczaj <mhal@rbox.co>
Closes: https://lore.kernel.org/netdev/20260803-sockmap-lookup-tcp-leak-v2-0-306e025bfe66@rbox.co/
Reported-by: Hyunwoo Kim <imv4bel@gmail.com>
Closes: https://lore.kernel.org/netdev/20260824033331.1084971-1-imv4bel@gmail.com/
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
include/net/inet_connection_sock.h | 1 +
net/ipv4/inet_connection_sock.c | 1 +
net/ipv4/inet_hashtables.c | 11 +++++++++++
3 files changed, 13 insertions(+)
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 433c2df23076..903499581db7 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -94,6 +94,7 @@ struct inet_connection_sock {
u32 icsk_rto_max;
__u32 icsk_delack_max;
__u32 icsk_pmtu_cookie;
+ unsigned char unhashed_state;
const struct tcp_congestion_ops *icsk_ca_ops;
const struct inet_connection_sock_af_ops *icsk_af_ops;
const struct tcp_ulp_ops *icsk_ulp_ops;
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 6257459bcee2..560ca861b6d0 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -1253,6 +1253,7 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
memset(&newicsk->icsk_accept_queue, 0,
sizeof(newicsk->icsk_accept_queue));
+ newicsk->unhashed_state = 0;
inet_sk_set_state(newsk, TCP_SYN_RECV);
inet_clone_ulp(req, newsk, priority);
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ba0faa9ae2bb..5abcb0debb27 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -803,6 +803,11 @@ int inet_hash(struct sock *sk)
inet_init_ehash_secret();
WARN_ON(!sk_unhashed(sk));
+
+ if (unlikely(inet_csk(sk)->unhashed_state &&
+ inet_csk(sk)->unhashed_state != TCP_LISTEN))
+ return -EINVAL;
+
ilb2 = inet_lhash2_bucket_sk(hashinfo, sk);
spin_lock(&ilb2->lock);
@@ -832,6 +837,9 @@ void inet_unhash(struct sock *sk)
return;
sock_rps_delete_flow(sk);
+
+ inet_csk(sk)->unhashed_state = sk->sk_state;
+
if (sk->sk_state == TCP_LISTEN) {
struct inet_listen_hashbucket *ilb2;
@@ -1058,6 +1066,9 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
int ret, i, low, high;
bool local_ports;
+ if (unlikely(inet_csk(sk)->unhashed_state == TCP_LISTEN))
+ return -EINVAL;
+
if (port) {
local_bh_disable();
ret = check_established(death_row, sk, port, NULL, false,
--
2.55.0.1003.g10538fe699-goog
next prev parent reply other threads:[~2026-09-04 3:36 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 3:35 [PATCH v1 net-next 0/2] net: Disallow buggy TCP transitions and IPV6_ADDRFORM Kuniyuki Iwashima
2026-09-04 3:35 ` Kuniyuki Iwashima [this message]
2026-09-04 11:32 ` [PATCH v1 net-next 1/2] tcp: Do not allow buggy transitions between ehash and lhash2 Jakub Sitnicki
2026-09-07 4:19 ` netdev-bot+sashiko
2026-09-04 3:35 ` [PATCH v1 net-next 2/2] ipv6: Remove IPV6_ADDRFORM Kuniyuki Iwashima
2026-09-04 9:10 ` Paolo Abeni
2026-09-07 4:19 ` netdev-bot+sashiko
2026-09-08 9:21 ` David Laight
2026-09-08 1:00 ` [PATCH v1 net-next 0/2] net: Disallow buggy TCP transitions and IPV6_ADDRFORM patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904033543.2635540-2-kuniyu@google.com \
--to=kuniyu@google.com \
--cc=davem@davemloft.net \
--cc=dsahern@kernel.org \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=idosch@nvidia.com \
--cc=imv4bel@gmail.com \
--cc=kuba@kernel.org \
--cc=kuni1840@gmail.com \
--cc=kylebot@openai.com \
--cc=mhal@rbox.co \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=willemb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.