lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20250714-connect-port-search-harder-v3-1-b1a41f249865@cloudflare.com>
Date: Mon, 14 Jul 2025 18:03:04 +0200
From: Jakub Sitnicki <jakub@...udflare.com>
To: Eric Dumazet <edumazet@...gle.com>, Paolo Abeni <pabeni@...hat.com>, 
 "David S. Miller" <davem@...emloft.net>, Jakub Kicinski <kuba@...nel.org>, 
 Neal Cardwell <ncardwell@...gle.com>, Kuniyuki Iwashima <kuniyu@...gle.com>
Cc: netdev@...r.kernel.org, kernel-team@...udflare.com
Subject: [PATCH net-next v3 1/3] tcp: Add RCU management to
 inet_bind2_bucket

Add RCU protection to inet_bind2_bucket structure akin to commit
d186f405fdf4 ("tcp: add RCU management to inet_bind_bucket").

This prepares us for walking (struct inet_bind_bucket *)->bhash2 list
without holding inet_bind_hashbucket spinlock.

Signed-off-by: Jakub Sitnicki <jakub@...udflare.com>
---
 include/net/inet_hashtables.h    |  4 ++--
 include/net/inet_timewait_sock.h |  3 +--
 net/ipv4/inet_connection_sock.c  |  2 +-
 net/ipv4/inet_hashtables.c       | 16 ++++++++--------
 net/ipv4/inet_timewait_sock.c    |  8 +++-----
 5 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h
index 19dbd9081d5a..a2ff18eea990 100644
--- a/include/net/inet_hashtables.h
+++ b/include/net/inet_hashtables.h
@@ -108,6 +108,7 @@ struct inet_bind2_bucket {
 	struct hlist_node	bhash_node;
 	/* List of sockets hashed to this bucket */
 	struct hlist_head	owners;
+	struct rcu_head         rcu;
 };
 
 static inline struct net *ib_net(const struct inet_bind_bucket *ib)
@@ -228,8 +229,7 @@ inet_bind2_bucket_create(struct kmem_cache *cachep, struct net *net,
 			 struct inet_bind_bucket *tb,
 			 const struct sock *sk);
 
-void inet_bind2_bucket_destroy(struct kmem_cache *cachep,
-			       struct inet_bind2_bucket *tb);
+void inet_bind2_bucket_destroy(struct inet_bind2_bucket *tb);
 
 struct inet_bind2_bucket *
 inet_bind2_bucket_find(const struct inet_bind_hashbucket *head,
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index 67a313575780..4f4e96b10cf3 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -92,8 +92,7 @@ static inline struct inet_timewait_sock *inet_twsk(const struct sock *sk)
 void inet_twsk_free(struct inet_timewait_sock *tw);
 void inet_twsk_put(struct inet_timewait_sock *tw);
 
-void inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
-			   struct inet_hashinfo *hashinfo);
+void inet_twsk_bind_unhash(struct inet_timewait_sock *tw);
 
 struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
 					   struct inet_timewait_death_row *dr,
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 1e2df51427fe..f58b93d3fa0e 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -593,7 +593,7 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
 fail_unlock:
 	if (ret) {
 		if (bhash2_created)
-			inet_bind2_bucket_destroy(hinfo->bind2_bucket_cachep, tb2);
+			inet_bind2_bucket_destroy(tb2);
 		if (bhash_created)
 			inet_bind_bucket_destroy(tb);
 	}
diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c
index ceeeec9b7290..d3ce6d0a514e 100644
--- a/net/ipv4/inet_hashtables.c
+++ b/net/ipv4/inet_hashtables.c
@@ -123,7 +123,7 @@ static void inet_bind2_bucket_init(struct inet_bind2_bucket *tb2,
 #endif
 	INIT_HLIST_HEAD(&tb2->owners);
 	hlist_add_head(&tb2->node, &head->chain);
-	hlist_add_head(&tb2->bhash_node, &tb->bhash2);
+	hlist_add_head_rcu(&tb2->bhash_node, &tb->bhash2);
 }
 
 struct inet_bind2_bucket *inet_bind2_bucket_create(struct kmem_cache *cachep,
@@ -141,12 +141,12 @@ struct inet_bind2_bucket *inet_bind2_bucket_create(struct kmem_cache *cachep,
 }
 
 /* Caller must hold hashbucket lock for this tb with local BH disabled */
-void inet_bind2_bucket_destroy(struct kmem_cache *cachep, struct inet_bind2_bucket *tb)
+void inet_bind2_bucket_destroy(struct inet_bind2_bucket *tb)
 {
 	if (hlist_empty(&tb->owners)) {
 		__hlist_del(&tb->node);
-		__hlist_del(&tb->bhash_node);
-		kmem_cache_free(cachep, tb);
+		hlist_del_rcu(&tb->bhash_node);
+		kfree_rcu(tb, rcu);
 	}
 }
 
@@ -198,7 +198,7 @@ static void __inet_put_port(struct sock *sk)
 
 		__sk_del_bind_node(sk);
 		inet_csk(sk)->icsk_bind2_hash = NULL;
-		inet_bind2_bucket_destroy(hashinfo->bind2_bucket_cachep, tb2);
+		inet_bind2_bucket_destroy(tb2);
 	}
 	spin_unlock(&head2->lock);
 
@@ -951,7 +951,7 @@ static int __inet_bhash2_update_saddr(struct sock *sk, void *saddr, int family,
 
 	spin_lock(&head2->lock);
 	__sk_del_bind_node(sk);
-	inet_bind2_bucket_destroy(hinfo->bind2_bucket_cachep, inet_csk(sk)->icsk_bind2_hash);
+	inet_bind2_bucket_destroy(inet_csk(sk)->icsk_bind2_hash);
 	spin_unlock(&head2->lock);
 
 	if (reset)
@@ -1154,7 +1154,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
 		inet_ehash_nolisten(sk, (struct sock *)tw, NULL);
 	}
 	if (tw)
-		inet_twsk_bind_unhash(tw, hinfo);
+		inet_twsk_bind_unhash(tw);
 
 	spin_unlock(&head2->lock);
 	spin_unlock(&head->lock);
@@ -1179,7 +1179,7 @@ int __inet_hash_connect(struct inet_timewait_death_row *death_row,
 		inet_sk(sk)->inet_num = 0;
 
 		if (tw)
-			inet_twsk_bind_unhash(tw, hinfo);
+			inet_twsk_bind_unhash(tw);
 	}
 
 	spin_unlock(&head2->lock);
diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
index 875ff923a8ed..ff286b179f4a 100644
--- a/net/ipv4/inet_timewait_sock.c
+++ b/net/ipv4/inet_timewait_sock.c
@@ -20,14 +20,12 @@
 /**
  *	inet_twsk_bind_unhash - unhash a timewait socket from bind hash
  *	@tw: timewait socket
- *	@hashinfo: hashinfo pointer
  *
  *	unhash a timewait socket from bind hash, if hashed.
  *	bind hash lock must be held by caller.
  *	Returns 1 if caller should call inet_twsk_put() after lock release.
  */
-void inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
-			  struct inet_hashinfo *hashinfo)
+void inet_twsk_bind_unhash(struct inet_timewait_sock *tw)
 {
 	struct inet_bind2_bucket *tb2 = tw->tw_tb2;
 	struct inet_bind_bucket *tb = tw->tw_tb;
@@ -38,7 +36,7 @@ void inet_twsk_bind_unhash(struct inet_timewait_sock *tw,
 	__sk_del_bind_node((struct sock *)tw);
 	tw->tw_tb = NULL;
 	tw->tw_tb2 = NULL;
-	inet_bind2_bucket_destroy(hashinfo->bind2_bucket_cachep, tb2);
+	inet_bind2_bucket_destroy(tb2);
 	inet_bind_bucket_destroy(tb);
 
 	__sock_put((struct sock *)tw);
@@ -63,7 +61,7 @@ static void inet_twsk_kill(struct inet_timewait_sock *tw)
 
 	spin_lock(&bhead->lock);
 	spin_lock(&bhead2->lock);
-	inet_twsk_bind_unhash(tw, hashinfo);
+	inet_twsk_bind_unhash(tw);
 	spin_unlock(&bhead2->lock);
 	spin_unlock(&bhead->lock);
 

-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ