linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Eric Dumazet <edumazet@google.com>,
	Jeffrey Knockel <jeffk@cs.unm.edu>,
	"Jedidiah R. Crandall" <crandall@cs.unm.edu>,
	Willy Tarreau <w@1wt.eu>,
	Hannes Frederic Sowa <hannes@redhat.com>,
	"David S. Miller" <davem@davemloft.net>
Subject: [PATCH 3.4 02/23] ip: make IP identifiers less predictable
Date: Fri,  8 Aug 2014 14:34:47 -0700	[thread overview]
Message-ID: <20140808213315.873879089@linuxfoundation.org> (raw)
In-Reply-To: <20140808213315.769217722@linuxfoundation.org>

3.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Eric Dumazet <edumazet@google.com>

[ Upstream commit 04ca6973f7c1a0d8537f2d9906a0cf8e69886d75 ]

In "Counting Packets Sent Between Arbitrary Internet Hosts", Jeffrey and
Jedidiah describe ways exploiting linux IP identifier generation to
infer whether two machines are exchanging packets.

With commit 73f156a6e8c1 ("inetpeer: get rid of ip_id_count"), we
changed IP id generation, but this does not really prevent this
side-channel technique.

This patch adds a random amount of perturbation so that IP identifiers
for a given destination [1] are no longer monotonically increasing after
an idle period.

Note that prandom_u32_max(1) returns 0, so if generator is used at most
once per jiffy, this patch inserts no hole in the ID suite and do not
increase collision probability.

This is jiffies based, so in the worst case (HZ=1000), the id can
rollover after ~65 seconds of idle time, which should be fine.

We also change the hash used in __ip_select_ident() to not only hash
on daddr, but also saddr and protocol, so that ICMP probes can not be
used to infer information for other protocols.

For IPv6, adds saddr into the hash as well, but not nexthdr.

If I ping the patched target, we can see ID are now hard to predict.

21:57:11.008086 IP (...)
    A > target: ICMP echo request, seq 1, length 64
21:57:11.010752 IP (... id 2081 ...)
    target > A: ICMP echo reply, seq 1, length 64

21:57:12.013133 IP (...)
    A > target: ICMP echo request, seq 2, length 64
21:57:12.015737 IP (... id 3039 ...)
    target > A: ICMP echo reply, seq 2, length 64

21:57:13.016580 IP (...)
    A > target: ICMP echo request, seq 3, length 64
21:57:13.019251 IP (... id 3437 ...)
    target > A: ICMP echo reply, seq 3, length 64

[1] TCP sessions uses a per flow ID generator not changed by this patch.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: Jeffrey Knockel <jeffk@cs.unm.edu>
Reported-by: Jedidiah R. Crandall <crandall@cs.unm.edu>
Cc: Willy Tarreau <w@1wt.eu>
Cc: Hannes Frederic Sowa <hannes@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 include/net/ip.h      |   11 +----------
 net/ipv4/route.c      |   36 +++++++++++++++++++++++++++++++++---
 net/ipv6/ip6_output.c |    2 ++
 3 files changed, 36 insertions(+), 13 deletions(-)

--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -264,16 +264,7 @@ int ip_dont_fragment(struct sock *sk, st
 		 !(dst_metric_locked(dst, RTAX_MTU)));
 }
 
-#define IP_IDENTS_SZ 2048u
-extern atomic_t *ip_idents;
-
-static inline u32 ip_idents_reserve(u32 hash, int segs)
-{
-	atomic_t *id_ptr = ip_idents + hash % IP_IDENTS_SZ;
-
-	return atomic_add_return(segs, id_ptr) - segs;
-}
-
+u32 ip_idents_reserve(u32 hash, int segs);
 void __ip_select_ident(struct iphdr *iph, int segs);
 
 static inline void ip_select_ident_segs(struct sk_buff *skb, struct sock *sk, int segs)
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1341,8 +1341,35 @@ void rt_bind_peer(struct rtable *rt, __b
 		rt->rt_peer_genid = rt_peer_genid();
 }
 
-atomic_t *ip_idents __read_mostly;
-EXPORT_SYMBOL(ip_idents);
+#define IP_IDENTS_SZ 2048u
+struct ip_ident_bucket {
+	atomic_t	id;
+	u32		stamp32;
+};
+
+static struct ip_ident_bucket *ip_idents __read_mostly;
+
+/* In order to protect privacy, we add a perturbation to identifiers
+ * if one generator is seldom used. This makes hard for an attacker
+ * to infer how many packets were sent between two points in time.
+ */
+u32 ip_idents_reserve(u32 hash, int segs)
+{
+	struct ip_ident_bucket *bucket = ip_idents + hash % IP_IDENTS_SZ;
+	u32 old = ACCESS_ONCE(bucket->stamp32);
+	u32 now = (u32)jiffies;
+	u32 delta = 0;
+
+	if (old != now && cmpxchg(&bucket->stamp32, old, now) == old) {
+		u64 x = random32();
+
+		x *= (now - old);
+		delta = (u32)(x >> 32);
+	}
+
+	return atomic_add_return(segs + delta, &bucket->id) - segs;
+}
+EXPORT_SYMBOL(ip_idents_reserve);
 
 void __ip_select_ident(struct iphdr *iph, int segs)
 {
@@ -1355,7 +1382,10 @@ void __ip_select_ident(struct iphdr *iph
 		get_random_bytes(&ip_idents_hashrnd, sizeof(ip_idents_hashrnd));
 	}
 
-	hash = jhash_1word((__force u32)iph->daddr, ip_idents_hashrnd);
+	hash = jhash_3words((__force u32)iph->daddr,
+			    (__force u32)iph->saddr,
+			    iph->protocol,
+			    ip_idents_hashrnd);
 	id = ip_idents_reserve(hash, segs);
 	iph->id = htons(id);
 }
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -608,6 +608,8 @@ void ipv6_select_ident(struct frag_hdr *
 		get_random_bytes(&ip6_idents_hashrnd, sizeof(ip6_idents_hashrnd));
 	}
 	hash = __ipv6_addr_jhash(&rt->rt6i_dst.addr, ip6_idents_hashrnd);
+	hash = __ipv6_addr_jhash(&rt->rt6i_src.addr, hash);
+
 	id = ip_idents_reserve(hash, 1);
 	fhdr->identification = htonl(id);
 }



  parent reply	other threads:[~2014-08-08 22:16 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-08 21:34 [PATCH 3.4 00/23] 3.4.103-stable review Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 01/23] inetpeer: get rid of ip_id_count Greg Kroah-Hartman
2014-08-08 21:34 ` Greg Kroah-Hartman [this message]
2014-08-08 21:34 ` [PATCH 3.4 03/23] net: sendmsg: fix NULL pointer dereference Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 04/23] tcp: Fix integer-overflows in TCP veno Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 05/23] tcp: Fix integer-overflow in TCP vegas Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 06/23] net: sctp: inherit auth_capable on INIT collisions Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 07/23] macvlan: Initialize vlan_features to turn on offload support Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 08/23] net: Correctly set segment mac_len in skb_segment() Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 09/23] iovec: make sure the caller actually wants anything in memcpy_fromiovecend Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 10/23] sctp: fix possible seqlock seadlock in sctp_packet_transmit() Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 11/23] sparc64: Fix argument sign extension for compat_sys_futex() Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 12/23] sparc64: Make itc_sync_lock raw Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 13/23] sparc64: Handle 32-bit tasks properly in compute_effective_address() Greg Kroah-Hartman
2014-08-08 21:34 ` [PATCH 3.4 14/23] sparc64: Fix top-level fault handling bugs Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 15/23] sparc64: Dont bark so loudly about 32-bit tasks generating 64-bit fault addresses Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 16/23] sparc64: Fix huge TSB mapping on pre-UltraSPARC-III cpus Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 17/23] sparc64: Add membar to Niagara2 memcpy code Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 18/23] sparc64: Do not insert non-valid PTEs into the TSB hash table Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 19/23] sparc64: Guard against flushing openfirmware mappings Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 20/23] bbc-i2c: Fix BBC I2C envctrl on SunBlade 2000 Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 21/23] sunsab: Fix detection of BREAK on sunsab serial console Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 22/23] sparc64: ldc_connect() should not return EINVAL when handshake is in progress Greg Kroah-Hartman
2014-08-08 21:35 ` [PATCH 3.4 23/23] arch/sparc/math-emu/math_32.c: drop stray break operator Greg Kroah-Hartman
2014-08-09  1:01 ` [PATCH 3.4 00/23] 3.4.103-stable review Guenter Roeck
2014-08-09 14:40 ` Shuah Khan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140808213315.873879089@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=crandall@cs.unm.edu \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=hannes@redhat.com \
    --cc=jeffk@cs.unm.edu \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=w@1wt.eu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).