ipv6: hash net ptr into fragmentation bucket selection

commit 5a352dd0a3aac03b443c94828dfd7144261c8636 upstream.

As namespaces are sometimes used with overlapping ip address ranges,
we should also use the namespace as input to the hash to select the ip
fragmentation counter bucket.

Cc: Eric Dumazet <edumazet@google.com>
Cc: Flavio Leitner <fbl@redhat.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
Change-Id: I4cd053112b178ddb0e0efbd1282478075dd064cb
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 387c5eb..91235b9 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -601,7 +601,7 @@
 	return -EINVAL;
 }
 
-void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
+void ipv6_select_ident(struct net *net, struct frag_hdr *fhdr, struct rt6_info *rt)
 {
 	static u32 ip6_idents_hashrnd __read_mostly;
 	static bool hashrnd_initialized = false;
@@ -613,6 +613,7 @@
 	}
 	hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd);
 	hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash);
+	hash ^= net_hash_mix(net);
 
 	id = ip_idents_reserve(hash, 1);
 	fhdr->identification = htonl(id);
@@ -708,7 +709,7 @@
 		skb_reset_network_header(skb);
 		memcpy(skb_network_header(skb), tmp_hdr, hlen);
 
-		ipv6_select_ident(fh, rt);
+		ipv6_select_ident(net, fh, rt);
 		fh->nexthdr = nexthdr;
 		fh->reserved = 0;
 		fh->frag_off = htons(IP6_MF);
@@ -857,7 +858,7 @@
 		fh->nexthdr = nexthdr;
 		fh->reserved = 0;
 		if (!frag_id) {
-			ipv6_select_ident(fh, rt);
+			ipv6_select_ident(net, fh, rt);
 			frag_id = fh->identification;
 		} else
 			fh->identification = frag_id;
@@ -1158,7 +1159,7 @@
 		skb_shinfo(skb)->gso_size = (mtu - fragheaderlen -
 					     sizeof(struct frag_hdr)) & ~7;
 		skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
-		ipv6_select_ident(&fhdr, rt);
+		ipv6_select_ident(sock_net(sk), &fhdr, rt);
 		skb_shinfo(skb)->ip6_frag_id = fhdr.identification;
 		__skb_queue_tail(&sk->sk_write_queue, skb);
 	}
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index a6126c6..59c0b56 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -9,7 +9,7 @@
  * This is similar to ipv6_select_ident() but we use an independent hash
  * seed to limit information leakage.
  */
-void ipv6_proxy_select_ident(struct sk_buff *skb)
+void ipv6_proxy_select_ident(struct net *net, struct sk_buff *skb)
 {
 	static u32 ip6_proxy_idents_hashrnd __read_mostly;
 	static bool hashrnd_initialized = false;
@@ -31,6 +31,7 @@
 	}
 	hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
 	hash = __ipv6_addr_jhash(&addrs[0], hash);
+	hash ^= net_hash_mix(net);
 
 	id = ip_idents_reserve(hash, 1);
 	skb_shinfo(skb)->ip6_frag_id = htonl(id);