Michal Kubecek df5e60
From: Eric Dumazet <edumazet@google.com>
Michal Kubecek df5e60
Date: Wed, 26 Jan 2022 17:10:22 -0800
Michal Kubecek df5e60
Subject: ipv4: avoid using shared IP generator for connected sockets
Michal Kubecek df5e60
Patch-mainline: v5.17-rc2
Michal Kubecek df5e60
Git-commit: 23f57406b82de51809d5812afd96f210f8b627f3
Michal Kubecek df5e60
References: CVE-2020-36516 bsc#1196616
Michal Kubecek df5e60
Michal Kubecek df5e60
ip_select_ident_segs() has been very conservative about using
Michal Kubecek df5e60
the connected socket private generator only for packets with IP_DF
Michal Kubecek df5e60
set, claiming it was needed for some VJ compression implementations.
Michal Kubecek df5e60
Michal Kubecek df5e60
As mentioned in this referenced document, this can be abused.
Michal Kubecek df5e60
(Ref: Off-Path TCP Exploits of the Mixed IPID Assignment)
Michal Kubecek df5e60
Michal Kubecek df5e60
Before switching to pure random IPID generation and possibly hurt
Michal Kubecek df5e60
some workloads, lets use the private inet socket generator.
Michal Kubecek df5e60
Michal Kubecek df5e60
Not only this will remove one vulnerability, this will also
Michal Kubecek df5e60
improve performance of TCP flows using pmtudisc==IP_PMTUDISC_DONT
Michal Kubecek df5e60
Michal Kubecek df5e60
Fixes: 73f156a6e8c1 ("inetpeer: get rid of ip_id_count")
Michal Kubecek df5e60
Signed-off-by: Eric Dumazet <edumazet@google.com>
Michal Kubecek df5e60
Reviewed-by: David Ahern <dsahern@kernel.org>
Michal Kubecek df5e60
Reported-by: Ray Che <xijiache@gmail.com>
Michal Kubecek df5e60
Cc: Willy Tarreau <w@1wt.eu>
Michal Kubecek df5e60
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Michal Kubecek df5e60
Acked-by: Michal Kubecek <mkubecek@suse.cz>
Michal Kubecek df5e60
Michal Kubecek df5e60
---
Michal Kubecek df5e60
 include/net/ip.h | 21 ++++++++++-----------
Michal Kubecek df5e60
 1 file changed, 10 insertions(+), 11 deletions(-)
Michal Kubecek df5e60
Michal Kubecek df5e60
--- a/include/net/ip.h
Michal Kubecek df5e60
+++ b/include/net/ip.h
Michal Kubecek df5e60
@@ -385,19 +385,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
Michal Kubecek df5e60
 {
Michal Kubecek df5e60
 	struct iphdr *iph = ip_hdr(skb);
Michal Kubecek df5e60
 
Michal Kubecek df5e60
+	/* We had many attacks based on IPID, use the private
Michal Kubecek df5e60
+	 * generator as much as we can.
Michal Kubecek df5e60
+	 */
Michal Kubecek df5e60
+	if (sk && inet_sk(sk)->inet_daddr) {
Michal Kubecek df5e60
+		iph->id = htons(inet_sk(sk)->inet_id);
Michal Kubecek df5e60
+		inet_sk(sk)->inet_id += segs;
Michal Kubecek df5e60
+		return;
Michal Kubecek df5e60
+	}
Michal Kubecek df5e60
 	if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
Michal Kubecek df5e60
-		/* This is only to work around buggy Windows95/2000
Michal Kubecek df5e60
-		 * VJ compression implementations.  If the ID field
Michal Kubecek df5e60
-		 * does not change, they drop every other packet in
Michal Kubecek df5e60
-		 * a TCP stream using header compression.
Michal Kubecek df5e60
-		 */
Michal Kubecek df5e60
-		if (sk && inet_sk(sk)->inet_daddr) {
Michal Kubecek df5e60
-			iph->id = htons(inet_sk(sk)->inet_id);
Michal Kubecek df5e60
-			inet_sk(sk)->inet_id += segs;
Michal Kubecek df5e60
-		} else {
Michal Kubecek df5e60
-			iph->id = 0;
Michal Kubecek df5e60
-		}
Michal Kubecek df5e60
+		iph->id = 0;
Michal Kubecek df5e60
 	} else {
Michal Kubecek df5e60
+		/* Unfortunately we need the big hammer to get a suitable IPID */
Michal Kubecek df5e60
 		__ip_select_ident(net, iph, segs);
Michal Kubecek df5e60
 	}
Michal Kubecek df5e60
 }