Commit 6d07a289 authored by Phil Sutter's avatar Phil Sutter Committed by Pablo Neira Ayuso
Browse files

netfilter: nf_tables: Support wildcard netdev hook specs



User space may pass non-nul-terminated NFTA_DEVICE_NAME attribute values
to indicate a suffix wildcard.
Expect for multiple devices to match the given prefix in
nft_netdev_hook_alloc() and populate 'ops_list' with them all.
When checking for duplicate hooks, compare the shortest prefix so a
device may never match more than a single hook spec.
Finally respect the stored prefix length when hooking into new devices
from event handlers.

Signed-off-by: default avatarPhil Sutter <phil@nwl.cc>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent 6f670935
Loading
Loading
Loading
Loading
+14 −15
Original line number Diff line number Diff line
@@ -2330,11 +2330,9 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
	 * indirectly serializing all the other holders of the commit_mutex with
	 * the rtnl_mutex.
	 */
	dev = __dev_get_by_name(net, hook->ifname);
	if (!dev) {
		err = -ENOENT;
		goto err_hook_free;
	}
	for_each_netdev(net, dev) {
		if (strncmp(dev->name, hook->ifname, hook->ifnamelen))
			continue;

		ops = kzalloc(sizeof(struct nf_hook_ops), GFP_KERNEL_ACCOUNT);
		if (!ops) {
@@ -2343,11 +2341,11 @@ static struct nft_hook *nft_netdev_hook_alloc(struct net *net,
		}
		ops->dev = dev;
		list_add_tail(&ops->list, &hook->ops_list);

	}
	return hook;

err_hook_free:
	kfree(hook);
	nft_netdev_hook_free(hook);
	return ERR_PTR(err);
}

@@ -2357,7 +2355,8 @@ static struct nft_hook *nft_hook_list_find(struct list_head *hook_list,
	struct nft_hook *hook;

	list_for_each_entry(hook, hook_list, list) {
		if (!strcmp(hook->ifname, this->ifname))
		if (!strncmp(hook->ifname, this->ifname,
			     min(hook->ifnamelen, this->ifnamelen)))
			return hook;
	}

@@ -9696,7 +9695,7 @@ static int nft_flowtable_event(unsigned long event, struct net_device *dev,

	list_for_each_entry(hook, &flowtable->hook_list, list) {
		ops = nft_hook_find_ops(hook, dev);
		match = !strcmp(hook->ifname, dev->name);
		match = !strncmp(hook->ifname, dev->name, hook->ifnamelen);

		switch (event) {
		case NETDEV_UNREGISTER:
+1 −1
Original line number Diff line number Diff line
@@ -328,7 +328,7 @@ static int nft_netdev_event(unsigned long event, struct net_device *dev,

	list_for_each_entry(hook, &basechain->hook_list, list) {
		ops = nft_hook_find_ops(hook, dev);
		match = !strcmp(hook->ifname, dev->name);
		match = !strncmp(hook->ifname, dev->name, hook->ifnamelen);

		switch (event) {
		case NETDEV_UNREGISTER: