[nf-next RFC] netfilter: nf_tables: Introduce NFTA_DEVICE_WILDCARD

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On netlink receive side, this attribute is just another name for
NFTA_DEVICE_NAME and handled equally. It enables user space to detect
lack of wildcard interface spec support as older kernels will reject it.

On netlink send side, it is used for wildcard interface specs to avoid
confusing or even crashing old user space with non NUL-terminated
strings in attributes which are expected to be NUL-terminated.

Fixes: 6d07a289504a ("netfilter: nf_tables: Support wildcard netdev hook specs")
Signed-off-by: Phil Sutter <phil@xxxxxx>
---
While this works, I wonder if it should be named NFTA_DEVICE_PREFIX
instead and contain NUL-terminated strings just like NFTA_DEVICE_NAME.
Kernel-internally I would continue using strncmp() and hook->ifnamelen,
but handling in user space might be simpler.

A downside of this approach is that we mix NFTA_DEVICE_NAME and
NFTA_DEVICE_WILDCARD attributes in NFTA_FLOWTABLE_HOOK_DEVS and
NFTA_HOOK_DEVS nested attributes, even though old user space will reject
the whole thing and not just take the known attributes and ignore the
rest.
---
 include/uapi/linux/netfilter/nf_tables.h |  1 +
 net/netfilter/nf_tables_api.c            | 16 +++++++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index 2beb30be2c5f..ed85b61afcd8 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -1788,6 +1788,7 @@ enum nft_synproxy_attributes {
 enum nft_devices_attributes {
 	NFTA_DEVICE_UNSPEC,
 	NFTA_DEVICE_NAME,
+	NFTA_DEVICE_WILDCARD,
 	__NFTA_DEVICE_MAX
 };
 #define NFTA_DEVICE_MAX		(__NFTA_DEVICE_MAX - 1)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 04795af6e586..f65b4fba5225 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1959,6 +1959,14 @@ static int nft_dump_stats(struct sk_buff *skb, struct nft_stats __percpu *stats)
 	return -ENOSPC;
 }
 
+static int hook_device_attr(struct nft_hook *hook)
+{
+	if (hook->ifname[hook->ifnamelen - 1] == '\0')
+		return NFTA_DEVICE_NAME;
+
+	return NFTA_DEVICE_WILDCARD;
+}
+
 static int nft_dump_basechain_hook(struct sk_buff *skb,
 				   const struct net *net, int family,
 				   const struct nft_base_chain *basechain,
@@ -1990,7 +1998,7 @@ static int nft_dump_basechain_hook(struct sk_buff *skb,
 			if (!first)
 				first = hook;
 
-			if (nla_put(skb, NFTA_DEVICE_NAME,
+			if (nla_put(skb, hook_device_attr(hook),
 				    hook->ifnamelen, hook->ifname))
 				goto nla_put_failure;
 			n++;
@@ -1998,6 +2006,7 @@ static int nft_dump_basechain_hook(struct sk_buff *skb,
 		nla_nest_end(skb, nest_devs);
 
 		if (n == 1 &&
+		    hook_device_attr(first) != NFTA_DEVICE_WILDCARD &&
 		    nla_put(skb, NFTA_HOOK_DEV,
 			    first->ifnamelen, first->ifname))
 			goto nla_put_failure;
@@ -2376,7 +2385,8 @@ static int nf_tables_parse_netdev_hooks(struct net *net,
 	int rem, n = 0, err;
 
 	nla_for_each_nested(tmp, attr, rem) {
-		if (nla_type(tmp) != NFTA_DEVICE_NAME) {
+		if (nla_type(tmp) != NFTA_DEVICE_NAME &&
+		    nla_type(tmp) != NFTA_DEVICE_WILDCARD) {
 			err = -EINVAL;
 			goto err_hook;
 		}
@@ -9427,7 +9437,7 @@ static int nf_tables_fill_flowtable_info(struct sk_buff *skb, struct net *net,
 
 	list_for_each_entry_rcu(hook, hook_list, list,
 				lockdep_commit_lock_is_held(net)) {
-		if (nla_put(skb, NFTA_DEVICE_NAME,
+		if (nla_put(skb, hook_device_attr(hook),
 			    hook->ifnamelen, hook->ifname))
 			goto nla_put_failure;
 	}
-- 
2.49.0





[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux