summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2019-04-01 07:08:54 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2019-04-15 01:31:44 -0400
commit3c79107631db1f7fd32cf3f7368e4672004a3010 (patch)
treee8eb82a458ef088d823e96d66d6ee2ff40e70774 /net
parent0261ea1bd1eb0da5c0792a9119b8655cf33c80a3 (diff)
netfilter: ctnetlink: don't use conntrack/expect object addresses as id
else, we leak the addresses to userspace via ctnetlink events and dumps. Compute an ID on demand based on the immutable parts of nf_conn struct. Another advantage compared to using an address is that there is no immediate re-use of the same ID in case the conntrack entry is freed and reallocated again immediately. Fixes: 3583240249ef ("[NETFILTER]: nf_conntrack_expect: kill unique ID") Fixes: 7f85f914721f ("[NETFILTER]: nf_conntrack: kill unique ID") Signed-off-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_core.c35
-rw-r--r--net/netfilter/nf_conntrack_netlink.c34
2 files changed, 64 insertions, 5 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index a137d4e7f218..3c48d44d6fff 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -25,6 +25,7 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/random.h> 26#include <linux/random.h>
27#include <linux/jhash.h> 27#include <linux/jhash.h>
28#include <linux/siphash.h>
28#include <linux/err.h> 29#include <linux/err.h>
29#include <linux/percpu.h> 30#include <linux/percpu.h>
30#include <linux/moduleparam.h> 31#include <linux/moduleparam.h>
@@ -449,6 +450,40 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
449} 450}
450EXPORT_SYMBOL_GPL(nf_ct_invert_tuple); 451EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
451 452
453/* Generate a almost-unique pseudo-id for a given conntrack.
454 *
455 * intentionally doesn't re-use any of the seeds used for hash
456 * table location, we assume id gets exposed to userspace.
457 *
458 * Following nf_conn items do not change throughout lifetime
459 * of the nf_conn after it has been committed to main hash table:
460 *
461 * 1. nf_conn address
462 * 2. nf_conn->ext address
463 * 3. nf_conn->master address (normally NULL)
464 * 4. tuple
465 * 5. the associated net namespace
466 */
467u32 nf_ct_get_id(const struct nf_conn *ct)
468{
469 static __read_mostly siphash_key_t ct_id_seed;
470 unsigned long a, b, c, d;
471
472 net_get_random_once(&ct_id_seed, sizeof(ct_id_seed));
473
474 a = (unsigned long)ct;
475 b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct));
476 c = (unsigned long)ct->ext;
477 d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash),
478 &ct_id_seed);
479#ifdef CONFIG_64BIT
480 return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed);
481#else
482 return siphash_4u32((u32)a, (u32)b, (u32)c, (u32)d, &ct_id_seed);
483#endif
484}
485EXPORT_SYMBOL_GPL(nf_ct_get_id);
486
452static void 487static void
453clean_from_lists(struct nf_conn *ct) 488clean_from_lists(struct nf_conn *ct)
454{ 489{
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 66c596d287a5..d7f61b0547c6 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -29,6 +29,7 @@
29#include <linux/spinlock.h> 29#include <linux/spinlock.h>
30#include <linux/interrupt.h> 30#include <linux/interrupt.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/siphash.h>
32 33
33#include <linux/netfilter.h> 34#include <linux/netfilter.h>
34#include <net/netlink.h> 35#include <net/netlink.h>
@@ -485,7 +486,9 @@ nla_put_failure:
485 486
486static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct) 487static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
487{ 488{
488 if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct))) 489 __be32 id = (__force __be32)nf_ct_get_id(ct);
490
491 if (nla_put_be32(skb, CTA_ID, id))
489 goto nla_put_failure; 492 goto nla_put_failure;
490 return 0; 493 return 0;
491 494
@@ -1286,8 +1289,9 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
1286 } 1289 }
1287 1290
1288 if (cda[CTA_ID]) { 1291 if (cda[CTA_ID]) {
1289 u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID])); 1292 __be32 id = nla_get_be32(cda[CTA_ID]);
1290 if (id != (u32)(unsigned long)ct) { 1293
1294 if (id != (__force __be32)nf_ct_get_id(ct)) {
1291 nf_ct_put(ct); 1295 nf_ct_put(ct);
1292 return -ENOENT; 1296 return -ENOENT;
1293 } 1297 }
@@ -2692,6 +2696,25 @@ nla_put_failure:
2692 2696
2693static const union nf_inet_addr any_addr; 2697static const union nf_inet_addr any_addr;
2694 2698
2699static __be32 nf_expect_get_id(const struct nf_conntrack_expect *exp)
2700{
2701 static __read_mostly siphash_key_t exp_id_seed;
2702 unsigned long a, b, c, d;
2703
2704 net_get_random_once(&exp_id_seed, sizeof(exp_id_seed));
2705
2706 a = (unsigned long)exp;
2707 b = (unsigned long)exp->helper;
2708 c = (unsigned long)exp->master;
2709 d = (unsigned long)siphash(&exp->tuple, sizeof(exp->tuple), &exp_id_seed);
2710
2711#ifdef CONFIG_64BIT
2712 return (__force __be32)siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &exp_id_seed);
2713#else
2714 return (__force __be32)siphash_4u32((u32)a, (u32)b, (u32)c, (u32)d, &exp_id_seed);
2715#endif
2716}
2717
2695static int 2718static int
2696ctnetlink_exp_dump_expect(struct sk_buff *skb, 2719ctnetlink_exp_dump_expect(struct sk_buff *skb,
2697 const struct nf_conntrack_expect *exp) 2720 const struct nf_conntrack_expect *exp)
@@ -2739,7 +2762,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
2739 } 2762 }
2740#endif 2763#endif
2741 if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) || 2764 if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) ||
2742 nla_put_be32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)) || 2765 nla_put_be32(skb, CTA_EXPECT_ID, nf_expect_get_id(exp)) ||
2743 nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) || 2766 nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) ||
2744 nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class))) 2767 nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class)))
2745 goto nla_put_failure; 2768 goto nla_put_failure;
@@ -3044,7 +3067,8 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
3044 3067
3045 if (cda[CTA_EXPECT_ID]) { 3068 if (cda[CTA_EXPECT_ID]) {
3046 __be32 id = nla_get_be32(cda[CTA_EXPECT_ID]); 3069 __be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
3047 if (ntohl(id) != (u32)(unsigned long)exp) { 3070
3071 if (id != nf_expect_get_id(exp)) {
3048 nf_ct_expect_put(exp); 3072 nf_ct_expect_put(exp);
3049 return -ENOENT; 3073 return -ENOENT;
3050 } 3074 }