Skip to content

Commit 514f1dc

Browse files
author
Florian Westphal
committed
netfilter: nft_ct: enable labels for get case too
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: 1ad8f48 ("netfilter: nftables: add connlabel set support") Reported-by: Antonio Ojea <[email protected]> Closes: https://lore.kernel.org/netfilter-devel/[email protected]/ Signed-off-by: Florian Westphal <[email protected]>
1 parent 8df206f commit 514f1dc

1 file changed

Lines changed: 22 additions & 3 deletions

File tree

net/netfilter/nft_ct.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,14 @@ static bool nft_ct_tmpl_alloc_pcpu(void)
379379
}
380380
#endif
381381

382+
static void __nft_ct_get_destroy(const struct nft_ctx *ctx, struct nft_ct *priv)
383+
{
384+
#ifdef CONFIG_NF_CONNTRACK_LABELS
385+
if (priv->key == NFT_CT_LABELS)
386+
nf_connlabels_put(ctx->net);
387+
#endif
388+
}
389+
382390
static int nft_ct_get_init(const struct nft_ctx *ctx,
383391
const struct nft_expr *expr,
384392
const struct nlattr * const tb[])
@@ -413,6 +421,10 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
413421
if (tb[NFTA_CT_DIRECTION] != NULL)
414422
return -EINVAL;
415423
len = NF_CT_LABELS_MAX_SIZE;
424+
425+
err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1);
426+
if (err)
427+
return err;
416428
break;
417429
#endif
418430
case NFT_CT_HELPER:
@@ -494,26 +506,30 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
494506
case IP_CT_DIR_REPLY:
495507
break;
496508
default:
497-
return -EINVAL;
509+
err = -EINVAL;
510+
goto err;
498511
}
499512
}
500513

501514
priv->len = len;
502515
err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL,
503516
NFT_DATA_VALUE, len);
504517
if (err < 0)
505-
return err;
518+
goto err;
506519

507520
err = nf_ct_netns_get(ctx->net, ctx->family);
508521
if (err < 0)
509-
return err;
522+
goto err;
510523

511524
if (priv->key == NFT_CT_BYTES ||
512525
priv->key == NFT_CT_PKTS ||
513526
priv->key == NFT_CT_AVGPKT)
514527
nf_ct_set_acct(ctx->net, true);
515528

516529
return 0;
530+
err:
531+
__nft_ct_get_destroy(ctx, priv);
532+
return err;
517533
}
518534

519535
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,
626642
static void nft_ct_get_destroy(const struct nft_ctx *ctx,
627643
const struct nft_expr *expr)
628644
{
645+
struct nft_ct *priv = nft_expr_priv(expr);
646+
647+
__nft_ct_get_destroy(ctx, priv);
629648
nf_ct_netns_put(ctx->net, ctx->family);
630649
}
631650

0 commit comments

Comments
 (0)