[PATCH] inet: update the IP ID generation algorithm to patch 355b98553789b646ed97ad801a619ff898471b92 standards.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Patch 355b98553789b646ed97ad801a619ff898471b92 makes net_hash_mix() return
true 32 bits of entropy. When used in the IP ID generation algorithm, this
has the effect of extending the IP ID generation key from 32 bits to 64
bits.
However, net_hash_mix() is only used for IP ID generation starting with
kernel version 4.1. Therefore, earlier kernels remain with 32-bit key.
The patch addresses this issue by explicitly extending the key to 64 bits
for kernels v<4.1.

Signed-off-by: Amit Klein <aksecurity@xxxxxxxxx>
---
 net/ipv4/route.c      | 4 +++-
 net/ipv6/ip6_output.c | 3 +++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index ede610a4abc8..446b6d202643 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -488,13 +488,15 @@ EXPORT_SYMBOL(ip_idents_reserve);
 void __ip_select_ident(struct iphdr *iph, int segs)
 {
 	static u32 ip_idents_hashrnd __read_mostly;
+	static u32 ip_idents_hashrnd_extra __read_mostly;
 	u32 hash, id;
 
 	net_get_random_once(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
+	net_get_random_once(&ip_idents_hashrnd_extra, sizeof(ip_idents_hashrnd_extra));
 
 	hash = jhash_3words((__force u32)iph->daddr,
 			    (__force u32)iph->saddr,
-			    iph->protocol,
+			    iph->protocol^ip_idents_hashrnd_extra,
 			    ip_idents_hashrnd);
 	id = ip_idents_reserve(hash, segs);
 	iph->id = htons(id);
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 2b69a4b965ed..58e507a79cdd 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -546,12 +546,15 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from)
 static void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt)
 {
 	static u32 ip6_idents_hashrnd __read_mostly;
+	static u32 ip6_idents_hashrnd_extra __read_mostly;
 	u32 hash, id;
 
 	net_get_random_once(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
+	net_get_random_once(&ip6_idents_hashrnd_extra, sizeof(ip6_idents_hashrnd_extra));
 
 	hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd);
 	hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash);
+	hash = jhash_1word(hash,ip6_idents_hashrnd_extra);
 
 	id = ip_idents_reserve(hash, 1);
 	fhdr->identification = htonl(id);
-- 
2.17.1




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux