mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-10 07:10:27 +00:00
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>
This commit is contained in:
parent
0261ea1bd1
commit
3c79107631
@ -316,6 +316,8 @@ struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
|
||||
gfp_t flags);
|
||||
void nf_ct_tmpl_free(struct nf_conn *tmpl);
|
||||
|
||||
u32 nf_ct_get_id(const struct nf_conn *ct);
|
||||
|
||||
static inline void
|
||||
nf_ct_set(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info info)
|
||||
{
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/jhash.h>
|
||||
#include <linux/siphash.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/moduleparam.h>
|
||||
@ -449,6 +450,40 @@ nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_invert_tuple);
|
||||
|
||||
/* Generate a almost-unique pseudo-id for a given conntrack.
|
||||
*
|
||||
* intentionally doesn't re-use any of the seeds used for hash
|
||||
* table location, we assume id gets exposed to userspace.
|
||||
*
|
||||
* Following nf_conn items do not change throughout lifetime
|
||||
* of the nf_conn after it has been committed to main hash table:
|
||||
*
|
||||
* 1. nf_conn address
|
||||
* 2. nf_conn->ext address
|
||||
* 3. nf_conn->master address (normally NULL)
|
||||
* 4. tuple
|
||||
* 5. the associated net namespace
|
||||
*/
|
||||
u32 nf_ct_get_id(const struct nf_conn *ct)
|
||||
{
|
||||
static __read_mostly siphash_key_t ct_id_seed;
|
||||
unsigned long a, b, c, d;
|
||||
|
||||
net_get_random_once(&ct_id_seed, sizeof(ct_id_seed));
|
||||
|
||||
a = (unsigned long)ct;
|
||||
b = (unsigned long)ct->master ^ net_hash_mix(nf_ct_net(ct));
|
||||
c = (unsigned long)ct->ext;
|
||||
d = (unsigned long)siphash(&ct->tuplehash, sizeof(ct->tuplehash),
|
||||
&ct_id_seed);
|
||||
#ifdef CONFIG_64BIT
|
||||
return siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &ct_id_seed);
|
||||
#else
|
||||
return siphash_4u32((u32)a, (u32)b, (u32)c, (u32)d, &ct_id_seed);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_get_id);
|
||||
|
||||
static void
|
||||
clean_from_lists(struct nf_conn *ct)
|
||||
{
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/siphash.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <net/netlink.h>
|
||||
@ -485,7 +486,9 @@ nla_put_failure:
|
||||
|
||||
static int ctnetlink_dump_id(struct sk_buff *skb, const struct nf_conn *ct)
|
||||
{
|
||||
if (nla_put_be32(skb, CTA_ID, htonl((unsigned long)ct)))
|
||||
__be32 id = (__force __be32)nf_ct_get_id(ct);
|
||||
|
||||
if (nla_put_be32(skb, CTA_ID, id))
|
||||
goto nla_put_failure;
|
||||
return 0;
|
||||
|
||||
@ -1286,8 +1289,9 @@ static int ctnetlink_del_conntrack(struct net *net, struct sock *ctnl,
|
||||
}
|
||||
|
||||
if (cda[CTA_ID]) {
|
||||
u_int32_t id = ntohl(nla_get_be32(cda[CTA_ID]));
|
||||
if (id != (u32)(unsigned long)ct) {
|
||||
__be32 id = nla_get_be32(cda[CTA_ID]);
|
||||
|
||||
if (id != (__force __be32)nf_ct_get_id(ct)) {
|
||||
nf_ct_put(ct);
|
||||
return -ENOENT;
|
||||
}
|
||||
@ -2692,6 +2696,25 @@ nla_put_failure:
|
||||
|
||||
static const union nf_inet_addr any_addr;
|
||||
|
||||
static __be32 nf_expect_get_id(const struct nf_conntrack_expect *exp)
|
||||
{
|
||||
static __read_mostly siphash_key_t exp_id_seed;
|
||||
unsigned long a, b, c, d;
|
||||
|
||||
net_get_random_once(&exp_id_seed, sizeof(exp_id_seed));
|
||||
|
||||
a = (unsigned long)exp;
|
||||
b = (unsigned long)exp->helper;
|
||||
c = (unsigned long)exp->master;
|
||||
d = (unsigned long)siphash(&exp->tuple, sizeof(exp->tuple), &exp_id_seed);
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
return (__force __be32)siphash_4u64((u64)a, (u64)b, (u64)c, (u64)d, &exp_id_seed);
|
||||
#else
|
||||
return (__force __be32)siphash_4u32((u32)a, (u32)b, (u32)c, (u32)d, &exp_id_seed);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||
const struct nf_conntrack_expect *exp)
|
||||
@ -2739,7 +2762,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||
}
|
||||
#endif
|
||||
if (nla_put_be32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)) ||
|
||||
nla_put_be32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)) ||
|
||||
nla_put_be32(skb, CTA_EXPECT_ID, nf_expect_get_id(exp)) ||
|
||||
nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) ||
|
||||
nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class)))
|
||||
goto nla_put_failure;
|
||||
@ -3044,7 +3067,8 @@ static int ctnetlink_get_expect(struct net *net, struct sock *ctnl,
|
||||
|
||||
if (cda[CTA_EXPECT_ID]) {
|
||||
__be32 id = nla_get_be32(cda[CTA_EXPECT_ID]);
|
||||
if (ntohl(id) != (u32)(unsigned long)exp) {
|
||||
|
||||
if (id != nf_expect_get_id(exp)) {
|
||||
nf_ct_expect_put(exp);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user