Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

netfilter: nf_conntrack_expect: honor expectation helper field

The expectation helper field is mostly unused. As a result, the
netfilter codebase relies on accessing the helper through exp->master.

Always set on the expectation helper field so it can be used to reach
the helper.

nf_ct_expect_init() is called from packet path where the skb owns
the ct object, therefore accessing exp->master for the newly created
expectation is safe. This saves a lot of updates in all callsites
to pass the ct object as parameter to nf_ct_expect_init().

This is a preparation patches for follow up fixes.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

+29 -12
+1 -1
include/net/netfilter/nf_conntrack_expect.h
··· 40 40 struct nf_conntrack_expect *this); 41 41 42 42 /* Helper to assign to new connection */ 43 - struct nf_conntrack_helper *helper; 43 + struct nf_conntrack_helper __rcu *helper; 44 44 45 45 /* The conntrack of the master connection */ 46 46 struct nf_conn *master;
+1 -1
net/netfilter/nf_conntrack_broadcast.c
··· 70 70 exp->expectfn = NULL; 71 71 exp->flags = NF_CT_EXPECT_PERMANENT; 72 72 exp->class = NF_CT_EXPECT_CLASS_DEFAULT; 73 - exp->helper = NULL; 73 + rcu_assign_pointer(exp->helper, helper); 74 74 75 75 nf_ct_expect_related(exp, 0); 76 76 nf_ct_expect_put(exp);
+13 -1
net/netfilter/nf_conntrack_expect.c
··· 309 309 } 310 310 EXPORT_SYMBOL_GPL(nf_ct_expect_alloc); 311 311 312 + /* This function can only be used from packet path, where accessing 313 + * master's helper is safe, because the packet holds a reference on 314 + * the conntrack object. Never use it from control plane. 315 + */ 312 316 void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class, 313 317 u_int8_t family, 314 318 const union nf_inet_addr *saddr, 315 319 const union nf_inet_addr *daddr, 316 320 u_int8_t proto, const __be16 *src, const __be16 *dst) 317 321 { 322 + struct nf_conntrack_helper *helper = NULL; 323 + struct nf_conn *ct = exp->master; 324 + struct nf_conn_help *help; 318 325 int len; 319 326 320 327 if (family == AF_INET) ··· 332 325 exp->flags = 0; 333 326 exp->class = class; 334 327 exp->expectfn = NULL; 335 - exp->helper = NULL; 328 + 329 + help = nfct_help(ct); 330 + if (help) 331 + helper = rcu_dereference(help->helper); 332 + 333 + rcu_assign_pointer(exp->helper, helper); 336 334 exp->tuple.src.l3num = family; 337 335 exp->tuple.dst.protonum = proto; 338 336
+6 -6
net/netfilter/nf_conntrack_h323_main.c
··· 643 643 &ct->tuplehash[!dir].tuple.src.u3, 644 644 &ct->tuplehash[!dir].tuple.dst.u3, 645 645 IPPROTO_TCP, NULL, &port); 646 - exp->helper = &nf_conntrack_helper_h245; 646 + rcu_assign_pointer(exp->helper, &nf_conntrack_helper_h245); 647 647 648 648 nathook = rcu_dereference(nfct_h323_nat_hook); 649 649 if (memcmp(&ct->tuplehash[dir].tuple.src.u3, ··· 767 767 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct), 768 768 &ct->tuplehash[!dir].tuple.src.u3, &addr, 769 769 IPPROTO_TCP, NULL, &port); 770 - exp->helper = nf_conntrack_helper_q931; 770 + rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931); 771 771 772 772 nathook = rcu_dereference(nfct_h323_nat_hook); 773 773 if (memcmp(&ct->tuplehash[dir].tuple.src.u3, ··· 1234 1234 &ct->tuplehash[!dir].tuple.src.u3 : NULL, 1235 1235 &ct->tuplehash[!dir].tuple.dst.u3, 1236 1236 IPPROTO_TCP, NULL, &port); 1237 - exp->helper = nf_conntrack_helper_q931; 1237 + rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931); 1238 1238 exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ 1239 1239 1240 1240 nathook = rcu_dereference(nfct_h323_nat_hook); ··· 1306 1306 nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct), 1307 1307 &ct->tuplehash[!dir].tuple.src.u3, &addr, 1308 1308 IPPROTO_UDP, NULL, &port); 1309 - exp->helper = nf_conntrack_helper_ras; 1309 + rcu_assign_pointer(exp->helper, nf_conntrack_helper_ras); 1310 1310 1311 1311 if (nf_ct_expect_related(exp, 0) == 0) { 1312 1312 pr_debug("nf_ct_ras: expect RAS "); ··· 1523 1523 &ct->tuplehash[!dir].tuple.src.u3, &addr, 1524 1524 IPPROTO_TCP, NULL, &port); 1525 1525 exp->flags = NF_CT_EXPECT_PERMANENT; 1526 - exp->helper = nf_conntrack_helper_q931; 1526 + rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931); 1527 1527 1528 1528 if (nf_ct_expect_related(exp, 0) == 0) { 1529 1529 pr_debug("nf_ct_ras: expect Q.931 "); ··· 1577 1577 &ct->tuplehash[!dir].tuple.src.u3, &addr, 1578 1578 IPPROTO_TCP, NULL, &port); 1579 1579 exp->flags = NF_CT_EXPECT_PERMANENT; 1580 - exp->helper = nf_conntrack_helper_q931; 1580 + rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931); 1581 1581 1582 1582 if (nf_ct_expect_related(exp, 0) == 0) { 1583 1583 pr_debug("nf_ct_ras: expect Q.931 ");
+6 -1
net/netfilter/nf_conntrack_helper.c
··· 399 399 const struct nf_conntrack_helper *me = data; 400 400 const struct nf_conntrack_helper *this; 401 401 402 - if (exp->helper == me) 402 + if (rcu_access_pointer(exp->helper) == me) 403 403 return true; 404 404 405 405 this = rcu_dereference_protected(help->helper, ··· 421 421 422 422 nf_ct_expect_iterate_destroy(expect_iter_me, NULL); 423 423 nf_ct_iterate_destroy(unhelp, me); 424 + 425 + /* nf_ct_iterate_destroy() does an unconditional synchronize_rcu() as 426 + * last step, this ensures rcu readers of exp->helper are done. 427 + * No need for another synchronize_rcu() here. 428 + */ 424 429 } 425 430 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); 426 431
+1 -1
net/netfilter/nf_conntrack_netlink.c
··· 3573 3573 3574 3574 exp->class = class; 3575 3575 exp->master = ct; 3576 - exp->helper = helper; 3576 + rcu_assign_pointer(exp->helper, helper); 3577 3577 exp->tuple = *tuple; 3578 3578 exp->mask.src.u3 = mask->src.u3; 3579 3579 exp->mask.src.u.all = mask->src.u.all;
+1 -1
net/netfilter/nf_conntrack_sip.c
··· 1297 1297 nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct), 1298 1298 saddr, &daddr, proto, NULL, &port); 1299 1299 exp->timeout.expires = sip_timeout * HZ; 1300 - exp->helper = helper; 1300 + rcu_assign_pointer(exp->helper, helper); 1301 1301 exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE; 1302 1302 1303 1303 hooks = rcu_dereference(nf_nat_sip_hooks);