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 for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 10 Nov 2022 20:00:33 -0800
From:   Kuniyuki Iwashima <kuniyu@...zon.com>
To:     "David S. Miller" <davem@...emloft.net>,
        Eric Dumazet <edumazet@...gle.com>,
        Jakub Kicinski <kuba@...nel.org>,
        Paolo Abeni <pabeni@...hat.com>
CC:     Kuniyuki Iwashima <kuniyu@...zon.com>,
        Kuniyuki Iwashima <kuni1840@...il.com>,
        <netdev@...r.kernel.org>
Subject: [PATCH v2 net-next 5/6] udp: Add bitmap in udp_table.

We use a bitmap in udp_lib_get_port() to search for an available
port.  Currently, the bitmap size is fixed and has enough room for
UDP_HTABLE_SIZE_MIN.

The following patch adds the per-netns hash table for UDP, whose size
can be smaller than UDP_HTABLE_SIZE_MIN.  If we define a bitmap with
enough size on the stack, it will be over CONFIG_FRAME_WARN.  To avoid
that, we allocate bitmaps for each udp_table->hash[slot] in advance.

Signed-off-by: Kuniyuki Iwashima <kuniyu@...zon.com>
---
 include/linux/udp.h |  1 +
 include/net/udp.h   | 20 ++++++++++++++++++++
 net/ipv4/udp.c      | 12 +++++++++---
 3 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/include/linux/udp.h b/include/linux/udp.h
index dea57aa37df6..779a7c065a32 100644
--- a/include/linux/udp.h
+++ b/include/linux/udp.h
@@ -23,6 +23,7 @@ static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
 	return (struct udphdr *)skb_transport_header(skb);
 }
 
+#define UDP_MAX_PORT_LOG		16
 #define UDP_HTABLE_SIZE_MIN		(CONFIG_BASE_SMALL ? 128 : 256)
 
 static inline u32 udp_hashfn(const struct net *net, u32 num, u32 mask)
diff --git a/include/net/udp.h b/include/net/udp.h
index de4b528522bb..314dd51a2cc6 100644
--- a/include/net/udp.h
+++ b/include/net/udp.h
@@ -72,11 +72,31 @@ struct udp_hslot {
 struct udp_table {
 	struct udp_hslot	*hash;
 	struct udp_hslot	*hash2;
+	unsigned long		*bitmap;
 	unsigned int		mask;
 	unsigned int		log;
 };
 extern struct udp_table udp_table;
 void udp_table_init(struct udp_table *, const char *);
+
+static inline unsigned int udp_bitmap_size(struct udp_table *table)
+{
+	return 1 << (UDP_MAX_PORT_LOG - table->log);
+}
+
+static inline unsigned long *udp_hashbitmap(struct udp_table *table,
+					    struct net *net, unsigned int num)
+{
+	unsigned long *bitmap;
+	unsigned int size;
+
+	size = udp_bitmap_size(table);
+	bitmap = &table->bitmap[udp_hashfn(net, num, table->mask) * BITS_TO_LONGS(size)];
+	bitmap_zero(bitmap, size);
+
+	return bitmap;
+}
+
 static inline struct udp_hslot *udp_hashslot(struct udp_table *table,
 					     struct net *net, unsigned int num)
 {
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 37e79158d145..42d7b84a5f16 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -129,7 +129,6 @@ DEFINE_PER_CPU(int, udp_memory_per_cpu_fw_alloc);
 EXPORT_PER_CPU_SYMBOL_GPL(udp_memory_per_cpu_fw_alloc);
 
 #define MAX_UDP_PORTS 65536
-#define PORTS_PER_CHAIN (MAX_UDP_PORTS / UDP_HTABLE_SIZE_MIN)
 
 static struct udp_table *udp_get_table_prot(struct sock *sk)
 {
@@ -243,9 +242,9 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
 	int error = 1;
 
 	if (!snum) {
-		DECLARE_BITMAP(bitmap, PORTS_PER_CHAIN);
 		unsigned short first, last;
 		int low, high, remaining;
+		unsigned long *bitmap;
 		unsigned int rand;
 
 		inet_get_local_port_range(net, &low, &high);
@@ -260,8 +259,8 @@ int udp_lib_get_port(struct sock *sk, unsigned short snum,
 		last = first + udptable->mask + 1;
 		do {
 			hslot = udp_hashslot(udptable, net, first);
-			bitmap_zero(bitmap, PORTS_PER_CHAIN);
 			spin_lock_bh(&hslot->lock);
+			bitmap = udp_hashbitmap(udptable, net, first);
 			udp_lib_lport_inuse(net, snum, hslot, bitmap, sk,
 					    udptable->log);
 
@@ -3290,6 +3289,13 @@ void __init udp_table_init(struct udp_table *table, const char *name)
 		table->hash2[i].count = 0;
 		spin_lock_init(&table->hash2[i].lock);
 	}
+
+	table->bitmap = kmalloc_array(table->mask + 1,
+				      BITS_TO_LONGS(udp_bitmap_size(table)) *
+				      sizeof(unsigned long),
+				      GFP_KERNEL);
+	if (!table->bitmap)
+		panic("UDP: failed to alloc bitmap\n");
 }
 
 u32 udp_flow_hashrnd(void)
-- 
2.30.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ