Commit e98cda76 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files
Florian Westphal says:

====================
netfilter: updates for net

1) its not possible to attach conntrack labels via ctnetlink
   unless one creates a dummy 'ct labels set' rule in nftables.
   This is an oversight, the 'ruleset tests presence, userspace
   (netlink) sets' use-case is valid and should 'just work'.
   Always broken since this got added in Linux 4.7.

2) nft_connlimit reads count value without holding the relevant
   lock, add a READ_ONCE annotation.  From Fernando Fernandez Mancera.

3) There is a long-standing bug (since 4.12) in nftables helper infra
   when NAT is in use: if the helper gets assigned after the nat binding
   was set up, we fail to initialise the 'seqadj' extension, which is
   needed in case NAT payload rewrites need to add (or remove) from the
   packet payload.  Fix from Andrii Melnychenko.

* tag 'nf-25-10-29' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
  netfilter: nft_ct: add seqadj extension for natted connections
  netfilter: nft_connlimit: fix possible data race on connection count
  netfilter: nft_ct: enable labels for get case too
====================

Link: https://patch.msgid.link/20251029135617.18274-1-fw@strlen.de


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 29857493 90918e3b
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ static inline void nft_connlimit_do_eval(struct nft_connlimit *priv,
		return;
	}

	count = priv->list->count;
	count = READ_ONCE(priv->list->count);

	if ((count > priv->limit) ^ priv->invert) {
		regs->verdict.code = NFT_BREAK;
+27 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@
#include <net/netfilter/nf_conntrack_timeout.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_seqadj.h>

struct nft_ct_helper_obj  {
	struct nf_conntrack_helper *helper4;
@@ -379,6 +380,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 +422,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 +507,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 +516,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 +528,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 +643,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);
}

@@ -1173,6 +1193,10 @@ static void nft_ct_helper_obj_eval(struct nft_object *obj,
	if (help) {
		rcu_assign_pointer(help->helper, to_assign);
		set_bit(IPS_HELPER_BIT, &ct->status);

		if ((ct->status & IPS_NAT_MASK) && !nfct_seqadj(ct))
			if (!nfct_seqadj_ext_add(ct))
				regs->verdict.code = NF_DROP;
	}
}