Commit 9c42bc9d authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso
Browse files

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: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent fafdd92b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ struct nf_conntrack_expect {
			 struct nf_conntrack_expect *this);

	/* Helper to assign to new connection */
	struct nf_conntrack_helper *helper;
	struct nf_conntrack_helper __rcu *helper;

	/* The conntrack of the master connection */
	struct nf_conn *master;
+1 −1
Original line number Diff line number Diff line
@@ -70,7 +70,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb,
	exp->expectfn             = NULL;
	exp->flags                = NF_CT_EXPECT_PERMANENT;
	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_put(exp);
+13 −1
Original line number Diff line number Diff line
@@ -309,12 +309,19 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
}
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,
		       u_int8_t family,
		       const union nf_inet_addr *saddr,
		       const union nf_inet_addr *daddr,
		       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;

	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->class = class;
	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.dst.protonum = proto;

+6 −6
Original line number Diff line number Diff line
@@ -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.dst.u3,
			  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);
	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),
			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
			  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);
	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.dst.u3,
			  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 */

	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),
			  &ct->tuplehash[!dir].tuple.src.u3, &addr,
			  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) {
		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,
			  IPPROTO_TCP, NULL, &port);
	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) {
		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,
			  IPPROTO_TCP, NULL, &port);
	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) {
		pr_debug("nf_ct_ras: expect Q.931 ");
+6 −1
Original line number Diff line number Diff line
@@ -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 *this;

	if (exp->helper == me)
	if (rcu_access_pointer(exp->helper) == me)
		return true;

	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_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);

Loading