Message ID | 20220126200518.990670-3-eric.dumazet@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | ipv4: less uses of shared IP generator | expand |
On 1/26/22 1:05 PM, Eric Dumazet wrote: > From: Eric Dumazet <edumazet@google.com> > > ip_select_ident_segs() has been very conservative about using > the connected socket private generator only for packets with IP_DF > set, claiming it was needed for some VJ compression implementations. > > As mentioned in this referenced document, this can be abused. > (Ref: Off-Path TCP Exploits of the Mixed IPID Assignment) > > Before switching to pure random IPID generation and possibly hurt > some workloads, lets use the private inet socket generator. > > Not only this will remove one vulnerability, this will also > improve performance of TCP flows using pmtudisc==IP_PMTUDISC_DONT > > Fixes: 73f156a6e8c1 ("inetpeer: get rid of ip_id_count") > Signed-off-by: Eric Dumazet <edumazet@google.com> > Reported-by: Ray Che <xijiache@gmail.com> > Cc: Willy Tarreau <w@1wt.eu> > --- > include/net/ip.h | 21 ++++++++++----------- > 1 file changed, 10 insertions(+), 11 deletions(-) > Reviewed-by: David Ahern <dsahern@kernel.org>
diff --git a/include/net/ip.h b/include/net/ip.h index 81e23a102a0d5edec859b78239b81e6dcd82c54d..b51bae43b0ddb00735a09718530aa3fff4a04872 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -525,19 +525,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb, { struct iphdr *iph = ip_hdr(skb); + /* We had many attacks based on IPID, use the private + * generator as much as we can. + */ + if (sk && inet_sk(sk)->inet_daddr) { + iph->id = htons(inet_sk(sk)->inet_id); + inet_sk(sk)->inet_id += segs; + return; + } if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) { - /* This is only to work around buggy Windows95/2000 - * VJ compression implementations. If the ID field - * does not change, they drop every other packet in - * a TCP stream using header compression. - */ - if (sk && inet_sk(sk)->inet_daddr) { - iph->id = htons(inet_sk(sk)->inet_id); - inet_sk(sk)->inet_id += segs; - } else { - iph->id = 0; - } + iph->id = 0; } else { + /* Unfortunately we need the big hammer to get a suitable IPID */ __ip_select_ident(net, iph, segs); } }