* [PATCH nf] netfilter: nft_ct: enable labels for get case too
@ 2025-10-23 12:09 Florian Westphal
2025-10-24 12:33 ` Antonio Ojea
0 siblings, 1 reply; 3+ messages in thread
From: Florian Westphal @ 2025-10-23 12:09 UTC (permalink / raw)
To: netfilter-devel; +Cc: Florian Westphal, Antonio Ojea
conntrack labels can only be set when the conntrack has been created
with the "ctlabel" extension.
For older iptables (connlabel match), adding an "-m connlabel" rule
turns on the ctlabel extension allocation for all future conntrack
entries.
For nftables, its only enabled for 'ct label set foo', but not for
'ct label foo' (i.e. check).
But users could have a ruleset that only checks for presence, and rely
on userspace to set a label bit via ctnetlink infrastructure.
This doesn't work without adding a dummy 'ct label set' rule.
We could also enable extension infra for the first (failing) ctnetlink
request, but unlike ruleset we would not be able to disable the
extension again.
Therefore turn on ctlabel extension allocation if an nftables ruleset
checks for a connlabel too.
Fixes: 1ad8f48df6f6 ("netfilter: nftables: add connlabel set support")
Reported-by: Antonio Ojea <aojea@google.com>
Closes: https://lore.kernel.org/netfilter-devel/aPi_VdZpVjWujZ29@strlen.de/
Signed-off-by: Florian Westphal <fw@strlen.de>
---
net/netfilter/nft_ct.c | 25 ++++++++++++++++++++++---
1 file changed, 22 insertions(+), 3 deletions(-)
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
index d526e69a2a2b..a418eb3d612b 100644
--- a/net/netfilter/nft_ct.c
+++ b/net/netfilter/nft_ct.c
@@ -379,6 +379,14 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
}
#endif
+static void __nft_ct_get_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
+{
+#ifdef CONFIG_NF_CONNTRACK_LABELS
+ if (priv->key == NFT_CT_LABELS)
+ nf_connlabels_put(ctx->net);
+#endif
+}
+
static int nft_ct_get_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
@@ -413,6 +421,10 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
if (tb[NFTA_CT_DIRECTION] != NULL)
return -EINVAL;
len = NF_CT_LABELS_MAX_SIZE;
+
+ err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
+ if (err)
+ return err;
break;
#endif
case NFT_CT_HELPER:
@@ -494,7 +506,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
case IP_CT_DIR_REPLY:
break;
default:
- return -EINVAL;
+ err = -EINVAL;
+ goto err;
}
}
@@ -502,11 +515,11 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
NFT_DATA_VALUE, len);
if (err < 0)
- return err;
+ goto err;
err = nf_ct_netns_get(ctx->net, ctx->family);
if (err < 0)
- return err;
+ goto err;
if (priv->key == NFT_CT_BYTES ||
priv->key == NFT_CT_PKTS ||
@@ -514,6 +527,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
nf_ct_set_acct(ctx->net, true);
return 0;
+err:
+ __nft_ct_get_destroy(ctx, priv);
+ return err;
}
static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
@@ -626,6 +642,9 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
static void nft_ct_get_destroy(const struct nft_ctx *ctx,
const struct nft_expr *expr)
{
+ struct nft_ct *priv = nft_expr_priv(expr);
+
+ __nft_ct_get_destroy(ctx, priv);
nf_ct_netns_put(ctx->net, ctx->family);
}
--
2.51.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH nf] netfilter: nft_ct: enable labels for get case too
2025-10-23 12:09 [PATCH nf] netfilter: nft_ct: enable labels for get case too Florian Westphal
@ 2025-10-24 12:33 ` Antonio Ojea
2025-10-24 12:55 ` Florian Westphal
0 siblings, 1 reply; 3+ messages in thread
From: Antonio Ojea @ 2025-10-24 12:33 UTC (permalink / raw)
To: Florian Westphal; +Cc: netfilter-devel
On Thu, Oct 23, 2025 at 2:09 PM Florian Westphal <fw@strlen.de> wrote:
>
> conntrack labels can only be set when the conntrack has been created
> with the "ctlabel" extension.
>
> For older iptables (connlabel match), adding an "-m connlabel" rule
> turns on the ctlabel extension allocation for all future conntrack
> entries.
>
> For nftables, its only enabled for 'ct label set foo', but not for
> 'ct label foo' (i.e. check).
> But users could have a ruleset that only checks for presence, and rely
> on userspace to set a label bit via ctnetlink infrastructure.
>
> This doesn't work without adding a dummy 'ct label set' rule.
> We could also enable extension infra for the first (failing) ctnetlink
> request, but unlike ruleset we would not be able to disable the
> extension again.
>
> Therefore turn on ctlabel extension allocation if an nftables ruleset
> checks for a connlabel too.
>
> Fixes: 1ad8f48df6f6 ("netfilter: nftables: add connlabel set support")
> Reported-by: Antonio Ojea <aojea@google.com>
> Closes: https://lore.kernel.org/netfilter-devel/aPi_VdZpVjWujZ29@strlen.de/
> Signed-off-by: Florian Westphal <fw@strlen.de>
> ---
> net/netfilter/nft_ct.c | 25 ++++++++++++++++++++++---
> 1 file changed, 22 insertions(+), 3 deletions(-)
>
> diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c
> index d526e69a2a2b..a418eb3d612b 100644
> --- a/net/netfilter/nft_ct.c
> +++ b/net/netfilter/nft_ct.c
> @@ -379,6 +379,14 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
> }
> #endif
>
> +static void __nft_ct_get_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
> +{
> +#ifdef CONFIG_NF_CONNTRACK_LABELS
> + if (priv->key == NFT_CT_LABELS)
> + nf_connlabels_put(ctx->net);
> +#endif
> +}
> +
> static int nft_ct_get_init(const struct nft_ctx *ctx,
> const struct nft_expr *expr,
> const struct nlattr * const tb[])
> @@ -413,6 +421,10 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
> if (tb[NFTA_CT_DIRECTION] != NULL)
> return -EINVAL;
> len = NF_CT_LABELS_MAX_SIZE;
> +
> + err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
> + if (err)
> + return err;
> break;
> #endif
> case NFT_CT_HELPER:
> @@ -494,7 +506,8 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
> case IP_CT_DIR_REPLY:
> break;
> default:
> - return -EINVAL;
> + err = -EINVAL;
> + goto err;
> }
> }
>
> @@ -502,11 +515,11 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
> err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
> NFT_DATA_VALUE, len);
> if (err < 0)
> - return err;
> + goto err;
>
> err = nf_ct_netns_get(ctx->net, ctx->family);
> if (err < 0)
> - return err;
> + goto err;
>
> if (priv->key == NFT_CT_BYTES ||
> priv->key == NFT_CT_PKTS ||
> @@ -514,6 +527,9 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
> nf_ct_set_acct(ctx->net, true);
>
> return 0;
> +err:
> + __nft_ct_get_destroy(ctx, priv);
> + return err;
> }
>
> static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
> @@ -626,6 +642,9 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
> static void nft_ct_get_destroy(const struct nft_ctx *ctx,
> const struct nft_expr *expr)
> {
> + struct nft_ct *priv = nft_expr_priv(expr);
> +
> + __nft_ct_get_destroy(ctx, priv);
> nf_ct_netns_put(ctx->net, ctx->family);
> }
>
> --
> 2.51.0
>
Hi Florian, I'm trying to add a kselftest but it seems the conntrack
tool fails to add the label if the /etc/xtables/connlabel.conf file
does not exist. This is the behavior I'm observing:
- conntrack -U:
- fails if the file does not exist
- works if the file exists, but if the entry does not exist in the
file the tool throws an error but the label is added
- conntrack -L -o label
- does not output the label if the file does not exist or is empty.
- if the file exists and the ct entry label exists in the file, then
it's correctly displayed in conntrack -L
- if the file exists but the label is not present in the file, the
output has a labels statement but is empty
Can you give me advice on how to proceed?
bind(3, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 0
getsockname(3, {sa_family=AF_NETLINK, nl_pid=16788,
nl_groups=00000000}, [12]) = 0
openat(AT_FDCWD, "/etc/xtables/connlabel.conf", O_RDONLY|O_CLOEXEC) =
-1 ENOENT (No such file or directory)
dup(2) = 4
fcntl(4, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
newfstatat(4, "", {st_mode=S_IFCHR|0620, st_rdev=makedev(0x88, 0x1),
...}, AT_EMPTY_PATH) = 0
write(4, "nfct_labelmap_new: No such file "..., 45nfct_labelmap_new:
No such file or directory
) = 45
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH nf] netfilter: nft_ct: enable labels for get case too
2025-10-24 12:33 ` Antonio Ojea
@ 2025-10-24 12:55 ` Florian Westphal
0 siblings, 0 replies; 3+ messages in thread
From: Florian Westphal @ 2025-10-24 12:55 UTC (permalink / raw)
To: Antonio Ojea; +Cc: netfilter-devel
Antonio Ojea <aojea@google.com> wrote:
> Hi Florian, I'm trying to add a kselftest
Thanks!
> but it seems the conntrack
> tool fails to add the label if the /etc/xtables/connlabel.conf file
> does not exist. This is the behavior I'm observing:
> - conntrack -U:
> - fails if the file does not exist
> - works if the file exists, but if the entry does not exist in the
> file the tool throws an error but the label is added
> - conntrack -L -o label
> - does not output the label if the file does not exist or is empty.
> - if the file exists and the ct entry label exists in the file, then
> it's correctly displayed in conntrack -L
> - if the file exists but the label is not present in the file, the
> output has a labels statement but is empty
Hmm, this isn't ideal, it should resort to a hexdump in that case
(on -L), needs a fix.
> Can you give me advice on how to proceed?
Best advice I can give is to check if conntrack tool supports
--labelmap option (not in any released version, added in June this
year).
And then add a custom temporary config file via 'mktemp' + feed that
file to conntrack.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-10-24 12:55 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-23 12:09 [PATCH nf] netfilter: nft_ct: enable labels for get case too Florian Westphal
2025-10-24 12:33 ` Antonio Ojea
2025-10-24 12:55 ` Florian Westphal
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.