Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6b48a7d0 authored by Patrick McHardy's avatar Patrick McHardy Committed by David S. Miller
Browse files

[NETFILTER]: ip_conntrack: properly use RCU for ip_conntrack_destroyed callback

parent c0e912d7
Loading
Loading
Loading
Loading
+6 −3
Original line number Original line Diff line number Diff line
@@ -303,6 +303,7 @@ destroy_conntrack(struct nf_conntrack *nfct)
	struct ip_conntrack *ct = (struct ip_conntrack *)nfct;
	struct ip_conntrack *ct = (struct ip_conntrack *)nfct;
	struct ip_conntrack_protocol *proto;
	struct ip_conntrack_protocol *proto;
	struct ip_conntrack_helper *helper;
	struct ip_conntrack_helper *helper;
	typeof(ip_conntrack_destroyed) destroyed;


	DEBUGP("destroy_conntrack(%p)\n", ct);
	DEBUGP("destroy_conntrack(%p)\n", ct);
	IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
	IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
@@ -322,10 +323,12 @@ destroy_conntrack(struct nf_conntrack *nfct)
	proto = __ip_conntrack_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
	proto = __ip_conntrack_proto_find(ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.protonum);
	if (proto && proto->destroy)
	if (proto && proto->destroy)
		proto->destroy(ct);
		proto->destroy(ct);
	rcu_read_unlock();


	if (ip_conntrack_destroyed)
	destroyed = rcu_dereference(ip_conntrack_destroyed);
		ip_conntrack_destroyed(ct);
	if (destroyed)
		destroyed(ct);

	rcu_read_unlock();


	write_lock_bh(&ip_conntrack_lock);
	write_lock_bh(&ip_conntrack_lock);
	/* Expectations will have been removed in clean_from_lists,
	/* Expectations will have been removed in clean_from_lists,
+4 −3
Original line number Original line Diff line number Diff line
@@ -604,8 +604,8 @@ static int __init ip_nat_init(void)
	}
	}


	/* FIXME: Man, this is a hack.  <SIGH> */
	/* FIXME: Man, this is a hack.  <SIGH> */
	IP_NF_ASSERT(ip_conntrack_destroyed == NULL);
	IP_NF_ASSERT(rcu_dereference(ip_conntrack_destroyed) == NULL);
	ip_conntrack_destroyed = &ip_nat_cleanup_conntrack;
	rcu_assign_pointer(ip_conntrack_destroyed, ip_nat_cleanup_conntrack);


	/* Initialize fake conntrack so that NAT will skip it */
	/* Initialize fake conntrack so that NAT will skip it */
	ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
	ip_conntrack_untracked.status |= IPS_NAT_DONE_MASK;
@@ -623,7 +623,8 @@ static int clean_nat(struct ip_conntrack *i, void *data)
static void __exit ip_nat_cleanup(void)
static void __exit ip_nat_cleanup(void)
{
{
	ip_ct_iterate_cleanup(&clean_nat, NULL);
	ip_ct_iterate_cleanup(&clean_nat, NULL);
	ip_conntrack_destroyed = NULL;
	rcu_assign_pointer(ip_conntrack_destroyed, NULL);
	synchronize_rcu();
	vfree(bysource);
	vfree(bysource);
}
}