mirror of
https://github.com/torvalds/linux.git
synced 2026-05-28 09:04:39 +02:00
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>
This commit is contained in:
parent
fafdd92b9e
commit
9c42bc9db9
|
|
@ -40,7 +40,7 @@ struct nf_conntrack_expect {
|
||||||
struct nf_conntrack_expect *this);
|
struct nf_conntrack_expect *this);
|
||||||
|
|
||||||
/* Helper to assign to new connection */
|
/* Helper to assign to new connection */
|
||||||
struct nf_conntrack_helper *helper;
|
struct nf_conntrack_helper __rcu *helper;
|
||||||
|
|
||||||
/* The conntrack of the master connection */
|
/* The conntrack of the master connection */
|
||||||
struct nf_conn *master;
|
struct nf_conn *master;
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
|
||||||
exp->expectfn = NULL;
|
exp->expectfn = NULL;
|
||||||
exp->flags = NF_CT_EXPECT_PERMANENT;
|
exp->flags = NF_CT_EXPECT_PERMANENT;
|
||||||
exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
|
exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
|
||||||
exp->helper = NULL;
|
rcu_assign_pointer(exp->helper, helper);
|
||||||
|
|
||||||
nf_ct_expect_related(exp, 0);
|
nf_ct_expect_related(exp, 0);
|
||||||
nf_ct_expect_put(exp);
|
nf_ct_expect_put(exp);
|
||||||
|
|
|
||||||
|
|
@ -309,12 +309,19 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
|
EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
|
||||||
|
|
||||||
|
/* This function can only be used from packet path, where accessing
|
||||||
|
* master's helper is safe, because the packet holds a reference on
|
||||||
|
* the conntrack object. Never use it from control plane.
|
||||||
|
*/
|
||||||
void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
|
void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
|
||||||
u_int8_t family,
|
u_int8_t family,
|
||||||
const union nf_inet_addr *saddr,
|
const union nf_inet_addr *saddr,
|
||||||
const union nf_inet_addr *daddr,
|
const union nf_inet_addr *daddr,
|
||||||
u_int8_t proto, const __be16 *src, const __be16 *dst)
|
u_int8_t proto, const __be16 *src, const __be16 *dst)
|
||||||
{
|
{
|
||||||
|
struct nf_conntrack_helper *helper = NULL;
|
||||||
|
struct nf_conn *ct = exp->master;
|
||||||
|
struct nf_conn_help *help;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (family == AF_INET)
|
if (family == AF_INET)
|
||||||
|
|
@ -325,7 +332,12 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
|
||||||
exp->flags = 0;
|
exp->flags = 0;
|
||||||
exp->class = class;
|
exp->class = class;
|
||||||
exp->expectfn = NULL;
|
exp->expectfn = NULL;
|
||||||
exp->helper = NULL;
|
|
||||||
|
help = nfct_help(ct);
|
||||||
|
if (help)
|
||||||
|
helper = rcu_dereference(help->helper);
|
||||||
|
|
||||||
|
rcu_assign_pointer(exp->helper, helper);
|
||||||
exp->tuple.src.l3num = family;
|
exp->tuple.src.l3num = family;
|
||||||
exp->tuple.dst.protonum = proto;
|
exp->tuple.dst.protonum = proto;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -643,7 +643,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
&ct->tuplehash[!dir].tuple.src.u3,
|
&ct->tuplehash[!dir].tuple.src.u3,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
IPPROTO_TCP, NULL, &port);
|
IPPROTO_TCP, NULL, &port);
|
||||||
exp->helper = &nf_conntrack_helper_h245;
|
rcu_assign_pointer(exp->helper, &nf_conntrack_helper_h245);
|
||||||
|
|
||||||
nathook = rcu_dereference(nfct_h323_nat_hook);
|
nathook = rcu_dereference(nfct_h323_nat_hook);
|
||||||
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
|
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
|
||||||
|
|
@ -767,7 +767,7 @@ static int expect_callforwarding(struct sk_buff *skb,
|
||||||
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
|
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
|
||||||
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
||||||
IPPROTO_TCP, NULL, &port);
|
IPPROTO_TCP, NULL, &port);
|
||||||
exp->helper = nf_conntrack_helper_q931;
|
rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
|
||||||
|
|
||||||
nathook = rcu_dereference(nfct_h323_nat_hook);
|
nathook = rcu_dereference(nfct_h323_nat_hook);
|
||||||
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
|
if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
|
||||||
|
|
@ -1234,7 +1234,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
&ct->tuplehash[!dir].tuple.src.u3 : NULL,
|
&ct->tuplehash[!dir].tuple.src.u3 : NULL,
|
||||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||||
IPPROTO_TCP, NULL, &port);
|
IPPROTO_TCP, NULL, &port);
|
||||||
exp->helper = nf_conntrack_helper_q931;
|
rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
|
||||||
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
|
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
|
||||||
|
|
||||||
nathook = rcu_dereference(nfct_h323_nat_hook);
|
nathook = rcu_dereference(nfct_h323_nat_hook);
|
||||||
|
|
@ -1306,7 +1306,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
|
nf_ct_expect_init(exp, NF_CT_EXPECT_CLASS_DEFAULT, nf_ct_l3num(ct),
|
||||||
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
||||||
IPPROTO_UDP, NULL, &port);
|
IPPROTO_UDP, NULL, &port);
|
||||||
exp->helper = nf_conntrack_helper_ras;
|
rcu_assign_pointer(exp->helper, nf_conntrack_helper_ras);
|
||||||
|
|
||||||
if (nf_ct_expect_related(exp, 0) == 0) {
|
if (nf_ct_expect_related(exp, 0) == 0) {
|
||||||
pr_debug("nf_ct_ras: expect RAS ");
|
pr_debug("nf_ct_ras: expect RAS ");
|
||||||
|
|
@ -1523,7 +1523,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
||||||
IPPROTO_TCP, NULL, &port);
|
IPPROTO_TCP, NULL, &port);
|
||||||
exp->flags = NF_CT_EXPECT_PERMANENT;
|
exp->flags = NF_CT_EXPECT_PERMANENT;
|
||||||
exp->helper = nf_conntrack_helper_q931;
|
rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
|
||||||
|
|
||||||
if (nf_ct_expect_related(exp, 0) == 0) {
|
if (nf_ct_expect_related(exp, 0) == 0) {
|
||||||
pr_debug("nf_ct_ras: expect Q.931 ");
|
pr_debug("nf_ct_ras: expect Q.931 ");
|
||||||
|
|
@ -1577,7 +1577,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||||
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
&ct->tuplehash[!dir].tuple.src.u3, &addr,
|
||||||
IPPROTO_TCP, NULL, &port);
|
IPPROTO_TCP, NULL, &port);
|
||||||
exp->flags = NF_CT_EXPECT_PERMANENT;
|
exp->flags = NF_CT_EXPECT_PERMANENT;
|
||||||
exp->helper = nf_conntrack_helper_q931;
|
rcu_assign_pointer(exp->helper, nf_conntrack_helper_q931);
|
||||||
|
|
||||||
if (nf_ct_expect_related(exp, 0) == 0) {
|
if (nf_ct_expect_related(exp, 0) == 0) {
|
||||||
pr_debug("nf_ct_ras: expect Q.931 ");
|
pr_debug("nf_ct_ras: expect Q.931 ");
|
||||||
|
|
|
||||||
|
|
@ -399,7 +399,7 @@ static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data)
|
||||||
const struct nf_conntrack_helper *me = data;
|
const struct nf_conntrack_helper *me = data;
|
||||||
const struct nf_conntrack_helper *this;
|
const struct nf_conntrack_helper *this;
|
||||||
|
|
||||||
if (exp->helper == me)
|
if (rcu_access_pointer(exp->helper) == me)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
this = rcu_dereference_protected(help->helper,
|
this = rcu_dereference_protected(help->helper,
|
||||||
|
|
@ -421,6 +421,11 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me)
|
||||||
|
|
||||||
nf_ct_expect_iterate_destroy(expect_iter_me, NULL);
|
nf_ct_expect_iterate_destroy(expect_iter_me, NULL);
|
||||||
nf_ct_iterate_destroy(unhelp, me);
|
nf_ct_iterate_destroy(unhelp, me);
|
||||||
|
|
||||||
|
/* nf_ct_iterate_destroy() does an unconditional synchronize_rcu() as
|
||||||
|
* last step, this ensures rcu readers of exp->helper are done.
|
||||||
|
* No need for another synchronize_rcu() here.
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
|
EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3573,7 +3573,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
|
||||||
|
|
||||||
exp->class = class;
|
exp->class = class;
|
||||||
exp->master = ct;
|
exp->master = ct;
|
||||||
exp->helper = helper;
|
rcu_assign_pointer(exp->helper, helper);
|
||||||
exp->tuple = *tuple;
|
exp->tuple = *tuple;
|
||||||
exp->mask.src.u3 = mask->src.u3;
|
exp->mask.src.u3 = mask->src.u3;
|
||||||
exp->mask.src.u.all = mask->src.u.all;
|
exp->mask.src.u.all = mask->src.u.all;
|
||||||
|
|
|
||||||
|
|
@ -1297,7 +1297,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,
|
||||||
nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
|
nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
|
||||||
saddr, &daddr, proto, NULL, &port);
|
saddr, &daddr, proto, NULL, &port);
|
||||||
exp->timeout.expires = sip_timeout * HZ;
|
exp->timeout.expires = sip_timeout * HZ;
|
||||||
exp->helper = helper;
|
rcu_assign_pointer(exp->helper, helper);
|
||||||
exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
|
exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
|
||||||
|
|
||||||
hooks = rcu_dereference(nf_nat_sip_hooks);
|
hooks = rcu_dereference(nf_nat_sip_hooks);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user