]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
net: fix off-by-one in udp_flow_src_port() / psp_write_headers()
authorEric Dumazet <edumazet@google.com>
Mon, 2 Mar 2026 16:39:33 +0000 (16:39 +0000)
committerJakub Kicinski <kuba@kernel.org>
Thu, 5 Mar 2026 00:51:10 +0000 (16:51 -0800)
udp_flow_src_port() and psp_write_headers() use ip_local_port_range.

ip_local_port_range is inclusive : all ports between min and max
can be used.

Before this patch, if ip_local_port_range was set to 40000-40001
40001 would not be used as a source port.

Use reciprocal_scale() to help code readability.

Not tagged for stable trees, as this change could break user
expectations.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Willem de Bruijn <willemb@google.com>
Link: https://patch.msgid.link/20260302163933.1754393-1-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
include/net/udp.h
net/psp/psp_main.c

index da68702ddf6edc6a28440490be07be7eef2d1a4e..b648003e5792a167822f28aeb728c3d64a2141f4 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/seq_file.h>
 #include <linux/poll.h>
 #include <linux/indirect_call_wrapper.h>
+#include <linux/math.h>
 
 /**
  *     struct udp_skb_cb  -  UDP(-Lite) private variables
@@ -376,7 +377,7 @@ static inline __be16 udp_flow_src_port(struct net *net, struct sk_buff *skb,
         */
        hash ^= hash << 16;
 
-       return htons((((u64) hash * (max - min)) >> 32) + min);
+       return htons(reciprocal_scale(hash, max - min + 1) + min);
 }
 
 static inline int udp_rqueue_get(struct sock *sk)
index d4c04c923c5ac6aead8b5bac41c54ae1143f4110..9508b6c380038b311a9b778933789b5c4cb61007 100644 (file)
@@ -202,7 +202,7 @@ static void psp_write_headers(struct net *net, struct sk_buff *skb, __be32 spi,
                 * reciprocal divide.
                 */
                hash ^= hash << 16;
-               uh->source = htons((((u64)hash * (max - min)) >> 32) + min);
+               uh->source = htons(reciprocal_scale(hash, max - min + 1) + min);
        } else {
                uh->source = udp_flow_src_port(net, skb, 0, 0, false);
        }