All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pablo Neira Ayuso <pablo@netfilter.org>
To: Phil Sutter <phil@nwl.cc>
Cc: Florian Westphal <fw@strlen.de>, netfilter-devel@vger.kernel.org
Subject: Re: [libnftnl PATCH] utils: Add helpers for interface name wildcards
Date: Tue, 22 Jul 2025 04:46:59 +0200	[thread overview]
Message-ID: <aH77oyMqwmO3x3V9@calendula> (raw)
In-Reply-To: <20250716132209.20372-1-phil@nwl.cc>

Hi Phil,

On Wed, Jul 16, 2025 at 03:22:06PM +0200, Phil Sutter wrote:
> Support simple (suffix) wildcards in NFTNL_CHAIN_DEV(ICES) and
> NFTA_FLOWTABLE_HOOK_DEVS identified by non-NUL-terminated strings. Add
> helpers converting to and from the human-readable asterisk-suffix
> notation.

We spent some time discussing scenarios where host and container could
use different userspace versions (older vs. newer).

In this case, newer version will send a string without the trailing
null character to the kernel. Then, the older version will just
_crash_ when parsing the netlink message from the kernel because it
expects a string that is nul-terminated (and we cannot fix an old
libnftnl library... it is not possible to fix the past, but it is
better if you can just deal with it).

I suggest you maybe pass the * at the end of the string to the kernel
so nft_netdev_hook_alloc() can just handle this special case and we
always have a nul-terminated string? There is ifnamelen which does in
the kernel what you need to compare the strings, while ifname can
still contain the *.

Worth a fix? Not much time ahead, but we are still in -rc7.

> Signed-off-by: Phil Sutter <phil@nwl.cc>
> ---
> Changes since v3:
> - Use uint16_t for 'attr' parameter and size_t for internal 'len'
>   variable
> - nftnl_attr_get_ifname to return allocated buffer, 'attr' parameter may
>   be const
> 
> Changes since v2:
> - Use 'nftnl' prefix for introduced helpers
> - Forward-declare struct nlattr to avoid extra include in utils.h
> - Sanity-check array indexes to avoid out-of-bounds access
> ---
>  include/utils.h |  6 ++++++
>  src/chain.c     |  8 +++++---
>  src/flowtable.c |  2 +-
>  src/str_array.c |  2 +-
>  src/utils.c     | 31 +++++++++++++++++++++++++++++++
>  5 files changed, 44 insertions(+), 5 deletions(-)
> 
> diff --git a/include/utils.h b/include/utils.h
> index 247d99d19dd7f..f232e7e2f3dd7 100644
> --- a/include/utils.h
> +++ b/include/utils.h
> @@ -83,4 +83,10 @@ int nftnl_fprintf(FILE *fpconst, const void *obj, uint32_t cmd, uint32_t type,
>  int nftnl_set_str_attr(const char **dptr, uint32_t *flags,
>  		       uint16_t attr, const void *data, uint32_t data_len);
>  
> +struct nlattr;
> +
> +void nftnl_attr_put_ifname(struct nlmsghdr *nlh,
> +			   uint16_t attr, const char *ifname);
> +char *nftnl_attr_get_ifname(const struct nlattr *attr);
> +
>  #endif
> diff --git a/src/chain.c b/src/chain.c
> index 895108cddad51..b401526c367fb 100644
> --- a/src/chain.c
> +++ b/src/chain.c
> @@ -457,14 +457,14 @@ void nftnl_chain_nlmsg_build_payload(struct nlmsghdr *nlh, const struct nftnl_ch
>  		mnl_attr_put_u32(nlh, NFTA_HOOK_PRIORITY, htonl(c->prio));
>  
>  	if (c->flags & (1 << NFTNL_CHAIN_DEV))
> -		mnl_attr_put_strz(nlh, NFTA_HOOK_DEV, c->dev);
> +		nftnl_attr_put_ifname(nlh, NFTA_HOOK_DEV, c->dev);
>  	else if (c->flags & (1 << NFTNL_CHAIN_DEVICES)) {
>  		struct nlattr *nest_dev;
>  		const char *dev;
>  
>  		nest_dev = mnl_attr_nest_start(nlh, NFTA_HOOK_DEVS);
>  		nftnl_str_array_foreach(dev, &c->dev_array, i)
> -			mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev);
> +			nftnl_attr_put_ifname(nlh, NFTA_DEVICE_NAME, dev);
>  		mnl_attr_nest_end(nlh, nest_dev);
>  	}
>  
> @@ -648,7 +648,9 @@ static int nftnl_chain_parse_hook(struct nlattr *attr, struct nftnl_chain *c)
>  		c->flags |= (1 << NFTNL_CHAIN_PRIO);
>  	}
>  	if (tb[NFTA_HOOK_DEV]) {
> -		c->dev = strdup(mnl_attr_get_str(tb[NFTA_HOOK_DEV]));
> +		if (c->flags & (1 << NFTNL_CHAIN_DEV))
> +			xfree(c->dev);
> +		c->dev = nftnl_attr_get_ifname(tb[NFTA_HOOK_DEV]);
>  		if (!c->dev)
>  			return -1;
>  		c->flags |= (1 << NFTNL_CHAIN_DEV);
> diff --git a/src/flowtable.c b/src/flowtable.c
> index fbbe0a866368d..006d50743e78a 100644
> --- a/src/flowtable.c
> +++ b/src/flowtable.c
> @@ -299,7 +299,7 @@ void nftnl_flowtable_nlmsg_build_payload(struct nlmsghdr *nlh,
>  
>  		nest_dev = mnl_attr_nest_start(nlh, NFTA_FLOWTABLE_HOOK_DEVS);
>  		nftnl_str_array_foreach(dev, &c->dev_array, i)
> -			mnl_attr_put_strz(nlh, NFTA_DEVICE_NAME, dev);
> +			nftnl_attr_put_ifname(nlh, NFTA_DEVICE_NAME, dev);
>  		mnl_attr_nest_end(nlh, nest_dev);
>  	}
>  
> diff --git a/src/str_array.c b/src/str_array.c
> index 5669c6154d394..02501c0cbdd79 100644
> --- a/src/str_array.c
> +++ b/src/str_array.c
> @@ -56,7 +56,7 @@ int nftnl_parse_devs(struct nftnl_str_array *sa, const struct nlattr *nest)
>  		return -1;
>  
>  	mnl_attr_for_each_nested(attr, nest) {
> -		sa->array[sa->len] = strdup(mnl_attr_get_str(attr));
> +		sa->array[sa->len] = nftnl_attr_get_ifname(attr);
>  		if (!sa->array[sa->len]) {
>  			nftnl_str_array_clear(sa);
>  			return -1;
> diff --git a/src/utils.c b/src/utils.c
> index 5f2c5bff7c650..2a8669c6242b7 100644
> --- a/src/utils.c
> +++ b/src/utils.c
> @@ -13,8 +13,11 @@
>  #include <errno.h>
>  #include <inttypes.h>
>  
> +#include <libmnl/libmnl.h>
> +
>  #include <libnftnl/common.h>
>  
> +#include <linux/if.h>
>  #include <linux/netfilter.h>
>  #include <linux/netfilter/nf_tables.h>
>  
> @@ -146,3 +149,31 @@ int nftnl_set_str_attr(const char **dptr, uint32_t *flags,
>  	*flags |= (1 << attr);
>  	return 0;
>  }
> +
> +void nftnl_attr_put_ifname(struct nlmsghdr *nlh,
> +			   uint16_t attr, const char *ifname)
> +{
> +	size_t len = strlen(ifname) + 1;
> +
> +	if (len >= 2 && ifname[len - 2] == '*')
> +		len -= 2;
> +
> +	mnl_attr_put(nlh, attr, len, ifname);
> +}
> +
> +char *nftnl_attr_get_ifname(const struct nlattr *attr)
> +{
> +	size_t slen = mnl_attr_get_payload_len(attr);
> +	const char *dev = mnl_attr_get_str(attr);
> +	char buf[IFNAMSIZ];
> +
> +	if (slen > 0 && dev[slen - 1] == '\0')
> +		return strdup(dev);
> +
> +	if (slen > IFNAMSIZ - 2)
> +		slen = IFNAMSIZ - 2;
> +
> +	memcpy(buf, dev, slen);
> +	memcpy(buf + slen, "*\0", 2);
> +	return strdup(buf);
> +}
> -- 
> 2.49.0
> 

  reply	other threads:[~2025-07-22  2:47 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-16 13:22 [libnftnl PATCH] utils: Add helpers for interface name wildcards Phil Sutter
2025-07-22  2:46 ` Pablo Neira Ayuso [this message]
2025-07-22 13:43   ` Phil Sutter
2025-07-22 23:33     ` Pablo Neira Ayuso
2025-07-23  0:07       ` Pablo Neira Ayuso
2025-07-23 11:49       ` Phil Sutter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aH77oyMqwmO3x3V9@calendula \
    --to=pablo@netfilter.org \
    --cc=fw@strlen.de \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=phil@nwl.cc \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.