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

Commit 4bd60443 authored by Florian Westphal's avatar Florian Westphal Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_queue: move device refcount bump to extra function



required by future patch that will need to duplicate the
nf_queue_entry, bumping refcounts of the copy.

Signed-off-by: default avatarFlorian Westphal <fw@strlen.de>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 6e01781d
Loading
Loading
Loading
Loading
+28 −21
Original line number Diff line number Diff line
@@ -66,6 +66,33 @@ static void nf_queue_entry_release_refs(struct nf_queue_entry *entry)
	module_put(entry->elem->owner);
}

/* Bump dev refs so they don't vanish while packet is out */
static bool nf_queue_entry_get_refs(struct nf_queue_entry *entry)
{
	if (!try_module_get(entry->elem->owner))
		return false;

	if (entry->indev)
		dev_hold(entry->indev);
	if (entry->outdev)
		dev_hold(entry->outdev);
#ifdef CONFIG_BRIDGE_NETFILTER
	if (entry->skb->nf_bridge) {
		struct nf_bridge_info *nf_bridge = entry->skb->nf_bridge;
		struct net_device *physdev;

		physdev = nf_bridge->physindev;
		if (physdev)
			dev_hold(physdev);
		physdev = nf_bridge->physoutdev;
		if (physdev)
			dev_hold(physdev);
	}
#endif

	return true;
}

/*
 * Any packet that leaves via this function must come back
 * through nf_reinject().
@@ -80,10 +107,6 @@ static int __nf_queue(struct sk_buff *skb,
{
	int status = -ENOENT;
	struct nf_queue_entry *entry = NULL;
#ifdef CONFIG_BRIDGE_NETFILTER
	struct net_device *physindev;
	struct net_device *physoutdev;
#endif
	const struct nf_afinfo *afinfo;
	const struct nf_queue_handler *qh;

@@ -116,26 +139,10 @@ static int __nf_queue(struct sk_buff *skb,
		.okfn	= okfn,
	};

	/* If it's going away, ignore hook. */
	if (!try_module_get(entry->elem->owner)) {
	if (!nf_queue_entry_get_refs(entry)) {
		status = -ECANCELED;
		goto err_unlock;
	}
	/* Bump dev refs so they don't vanish while packet is out */
	if (indev)
		dev_hold(indev);
	if (outdev)
		dev_hold(outdev);
#ifdef CONFIG_BRIDGE_NETFILTER
	if (skb->nf_bridge) {
		physindev = skb->nf_bridge->physindev;
		if (physindev)
			dev_hold(physindev);
		physoutdev = skb->nf_bridge->physoutdev;
		if (physoutdev)
			dev_hold(physoutdev);
	}
#endif
	skb_dst_force(skb);
	afinfo->saveroute(skb, entry);
	status = qh->outfn(entry, queuenum);