Skip to content

Commit 02a3231

Browse files
committed
netfilter: nf_conntrack_expect: store netns and zone in expectation
__nf_ct_expect_find() and nf_ct_expect_find_get() are called under rcu_read_lock() but they dereference the master conntrack via exp->master. Since the expectation does not hold a reference on the master conntrack, this could be dying conntrack or different recycled conntrack than the real master due to SLAB_TYPESAFE_RCU. Store the netns, the master_tuple and the zone in struct nf_conntrack_expect as a safety measure. This patch is required by the follow up fix not to dump expectations that do not belong to this netns. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent bffcaad commit 02a3231

4 files changed

Lines changed: 34 additions & 4 deletions

File tree

include/net/netfilter/nf_conntrack_expect.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,16 @@ struct nf_conntrack_expect {
2222
/* Hash member */
2323
struct hlist_node hnode;
2424

25+
/* Network namespace */
26+
possible_net_t net;
27+
2528
/* We expect this tuple, with the following mask */
2629
struct nf_conntrack_tuple tuple;
2730
struct nf_conntrack_tuple_mask mask;
2831

32+
#ifdef CONFIG_NF_CONNTRACK_ZONES
33+
struct nf_conntrack_zone zone;
34+
#endif
2935
/* Usage count. */
3036
refcount_t use;
3137

@@ -62,7 +68,17 @@ struct nf_conntrack_expect {
6268

6369
static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
6470
{
65-
return nf_ct_net(exp->master);
71+
return read_pnet(&exp->net);
72+
}
73+
74+
static inline bool nf_ct_exp_zone_equal_any(const struct nf_conntrack_expect *a,
75+
const struct nf_conntrack_zone *b)
76+
{
77+
#ifdef CONFIG_NF_CONNTRACK_ZONES
78+
return a->zone.id == b->id;
79+
#else
80+
return true;
81+
#endif
6682
}
6783

6884
#define NF_CT_EXP_POLICY_NAME_LEN 16

net/netfilter/nf_conntrack_broadcast.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
2121
unsigned int timeout)
2222
{
2323
const struct nf_conntrack_helper *helper;
24+
struct net *net = read_pnet(&ct->ct_net);
2425
struct nf_conntrack_expect *exp;
2526
struct iphdr *iph = ip_hdr(skb);
2627
struct rtable *rt = skb_rtable(skb);
@@ -71,7 +72,10 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
7172
exp->flags = NF_CT_EXPECT_PERMANENT;
7273
exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
7374
rcu_assign_pointer(exp->helper, helper);
74-
75+
write_pnet(&exp->net, net);
76+
#ifdef CONFIG_NF_CONNTRACK_ZONES
77+
exp->zone = ct->zone;
78+
#endif
7579
nf_ct_expect_related(exp, 0);
7680
nf_ct_expect_put(exp);
7781

net/netfilter/nf_conntrack_expect.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ nf_ct_exp_equal(const struct nf_conntrack_tuple *tuple,
113113
const struct net *net)
114114
{
115115
return nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
116-
net_eq(net, nf_ct_net(i->master)) &&
117-
nf_ct_zone_equal_any(i->master, zone);
116+
net_eq(net, read_pnet(&i->net)) &&
117+
nf_ct_exp_zone_equal_any(i, zone);
118118
}
119119

120120
bool nf_ct_remove_expect(struct nf_conntrack_expect *exp)
@@ -326,6 +326,7 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
326326
{
327327
struct nf_conntrack_helper *helper = NULL;
328328
struct nf_conn *ct = exp->master;
329+
struct net *net = read_pnet(&ct->ct_net);
329330
struct nf_conn_help *help;
330331
int len;
331332

@@ -343,6 +344,10 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
343344
helper = rcu_dereference(help->helper);
344345

345346
rcu_assign_pointer(exp->helper, helper);
347+
write_pnet(&exp->net, net);
348+
#ifdef CONFIG_NF_CONNTRACK_ZONES
349+
exp->zone = ct->zone;
350+
#endif
346351
exp->tuple.src.l3num = family;
347352
exp->tuple.dst.protonum = proto;
348353

net/netfilter/nf_conntrack_netlink.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3538,6 +3538,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
35383538
struct nf_conntrack_tuple *tuple,
35393539
struct nf_conntrack_tuple *mask)
35403540
{
3541+
struct net *net = read_pnet(&ct->ct_net);
35413542
struct nf_conntrack_expect *exp;
35423543
struct nf_conn_help *help;
35433544
u32 class = 0;
@@ -3577,6 +3578,10 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
35773578

35783579
exp->class = class;
35793580
exp->master = ct;
3581+
write_pnet(&exp->net, net);
3582+
#ifdef CONFIG_NF_CONNTRACK_ZONES
3583+
exp->zone = ct->zone;
3584+
#endif
35803585
if (!helper)
35813586
helper = rcu_dereference(help->helper);
35823587
rcu_assign_pointer(exp->helper, helper);

0 commit comments

Comments
 (0)