Skip to content

Commit 3ede646

Browse files
committed
Merge branch 'ipv4-less-uses-of-shared-ip-generator'
Eric Dumazet says: ==================== ipv4: less uses of shared IP generator From: Eric Dumazet <[email protected]> We keep receiving research reports based on linux IPID generation. Before breaking part of the Internet by switching to pure random generator, this series reduces the need for the shared IP generator for TCP sockets. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 153a0d1 + 23f5740 commit 3ede646

File tree

2 files changed

+19
-13
lines changed

2 files changed

+19
-13
lines changed

include/net/ip.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -525,19 +525,18 @@ static inline void ip_select_ident_segs(struct net *net, struct sk_buff *skb,
525525
{
526526
struct iphdr *iph = ip_hdr(skb);
527527

528+
/* We had many attacks based on IPID, use the private
529+
* generator as much as we can.
530+
*/
531+
if (sk && inet_sk(sk)->inet_daddr) {
532+
iph->id = htons(inet_sk(sk)->inet_id);
533+
inet_sk(sk)->inet_id += segs;
534+
return;
535+
}
528536
if ((iph->frag_off & htons(IP_DF)) && !skb->ignore_df) {
529-
/* This is only to work around buggy Windows95/2000
530-
* VJ compression implementations. If the ID field
531-
* does not change, they drop every other packet in
532-
* a TCP stream using header compression.
533-
*/
534-
if (sk && inet_sk(sk)->inet_daddr) {
535-
iph->id = htons(inet_sk(sk)->inet_id);
536-
inet_sk(sk)->inet_id += segs;
537-
} else {
538-
iph->id = 0;
539-
}
537+
iph->id = 0;
540538
} else {
539+
/* Unfortunately we need the big hammer to get a suitable IPID */
541540
__ip_select_ident(net, iph, segs);
542541
}
543542
}

net/ipv4/ip_output.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,12 +162,19 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
162162
iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr);
163163
iph->saddr = saddr;
164164
iph->protocol = sk->sk_protocol;
165-
if (ip_dont_fragment(sk, &rt->dst)) {
165+
/* Do not bother generating IPID for small packets (eg SYNACK) */
166+
if (skb->len <= IPV4_MIN_MTU || ip_dont_fragment(sk, &rt->dst)) {
166167
iph->frag_off = htons(IP_DF);
167168
iph->id = 0;
168169
} else {
169170
iph->frag_off = 0;
170-
__ip_select_ident(net, iph, 1);
171+
/* TCP packets here are SYNACK with fat IPv4/TCP options.
172+
* Avoid using the hashed IP ident generator.
173+
*/
174+
if (sk->sk_protocol == IPPROTO_TCP)
175+
iph->id = (__force __be16)prandom_u32();
176+
else
177+
__ip_select_ident(net, iph, 1);
171178
}
172179

173180
if (opt && opt->opt.optlen) {

0 commit comments

Comments
 (0)