inet: stop leaking jiffies on the wire
authorEric Dumazet <edumazet@google.com>
Fri, 1 Nov 2019 17:32:19 +0000 (10:32 -0700)
committerBen Hutchings <ben@decadent.org.uk>
Thu, 19 Dec 2019 15:58:53 +0000 (15:58 +0000)
commit a904a0693c189691eeee64f6c6b188bd7dc244e9 upstream.

Historically linux tried to stick to RFC 791, 1122, 2003
for IPv4 ID field generation.

RFC 6864 made clear that no matter how hard we try,
we can not ensure unicity of IP ID within maximum
lifetime for all datagrams with a given source
address/destination address/protocol tuple.

Linux uses a per socket inet generator (inet_id), initialized
at connection startup with a XOR of 'jiffies' and other
fields that appear clear on the wire.

Thiemo Nagel pointed that this strategy is a privacy
concern as this provides 16 bits of entropy to fingerprint
devices.

Let's switch to a random starting point, this is just as
good as far as RFC 6864 is concerned and does not leak
anything critical.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Thiemo Nagel <tnagel@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: drop changes in chelsio]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
net/dccp/ipv4.c
net/ipv4/datagram.c
net/ipv4/tcp_ipv4.c
net/sctp/socket.c

index 755cf1459e936d863180d09020283372973e27d6..8f4cffecd61b4a29e1a37249dd81b4d20cad0e5c 100644 (file)
@@ -122,7 +122,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                    inet->inet_daddr,
                                                    inet->inet_sport,
                                                    inet->inet_dport);
-       inet->inet_id = dp->dccps_iss ^ jiffies;
+       inet->inet_id = prandom_u32();
 
        err = dccp_connect(sk);
        rt = NULL;
index f0c307cb61963ba00276673d606e844c99769e71..eaddffcbe654b0a24b465d5c4484881e7d08b413 100644 (file)
@@ -74,7 +74,7 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
        inet->inet_daddr = fl4->daddr;
        inet->inet_dport = usin->sin_port;
        sk->sk_state = TCP_ESTABLISHED;
-       inet->inet_id = jiffies;
+       inet->inet_id = prandom_u32();
 
        sk_dst_set(sk, &rt->dst);
        err = 0;
index 201a2d9aebd775fcf7e6292804ed8f698073a735..d3a4cb33f5f0a677bfccf395d8e4152b78b0f71e 100644 (file)
@@ -241,7 +241,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                           inet->inet_sport,
                                                           usin->sin_port);
 
-       inet->inet_id = tp->write_seq ^ jiffies;
+       inet->inet_id = prandom_u32();
 
        err = tcp_connect(sk);
 
@@ -1449,7 +1449,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        inet_csk(newsk)->icsk_ext_hdr_len = 0;
        if (inet_opt)
                inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
-       newinet->inet_id = newtp->write_seq ^ jiffies;
+       newinet->inet_id = prandom_u32();
 
        if (!dst) {
                dst = inet_csk_route_child_sock(sk, newsk, req);
index b506cd9c1b82268e248d5202722b97669dbcfe98..b3ddb62e58d1cbfbaca42693c46e239b0d0d844d 100644 (file)
@@ -7006,7 +7006,7 @@ void sctp_copy_sock(struct sock *newsk, struct sock *sk,
        newinet->inet_rcv_saddr = inet->inet_rcv_saddr;
        newinet->inet_dport = htons(asoc->peer.port);
        newinet->pmtudisc = inet->pmtudisc;
-       newinet->inet_id = asoc->next_tsn ^ jiffies;
+       newinet->inet_id = prandom_u32();
 
        newinet->uc_ttl = inet->uc_ttl;
        newinet->mc_loop = 1;