Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'nf-25-10-29' of https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

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: Jakub Kicinski <kuba@kernel.org>

+28 -4
+1 -1
net/netfilter/nft_connlimit.c
··· 48 48 return; 49 49 } 50 50 51 - count = priv->list->count; 51 + count = READ_ONCE(priv->list->count); 52 52 53 53 if ((count > priv->limit) ^ priv->invert) { 54 54 regs->verdict.code = NFT_BREAK;
+27 -3
net/netfilter/nft_ct.c
··· 22 22 #include <net/netfilter/nf_conntrack_timeout.h> 23 23 #include <net/netfilter/nf_conntrack_l4proto.h> 24 24 #include <net/netfilter/nf_conntrack_expect.h> 25 + #include <net/netfilter/nf_conntrack_seqadj.h> 25 26 26 27 struct nft_ct_helper_obj { 27 28 struct nf_conntrack_helper *helper4; ··· 380 379 } 381 380 #endif 382 381 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 + 383 390 static int nft_ct_get_init(const struct nft_ctx *ctx, 384 391 const struct nft_expr *expr, 385 392 const struct nlattr * const tb[]) ··· 422 413 if (tb[NFTA_CT_DIRECTION] != NULL) 423 414 return -EINVAL; 424 415 len = NF_CT_LABELS_MAX_SIZE; 416 + 417 + err = nf_connlabels_get(ctx->net, (len * BITS_PER_BYTE) - 1); 418 + if (err) 419 + return err; 425 420 break; 426 421 #endif 427 422 case NFT_CT_HELPER: ··· 507 494 case IP_CT_DIR_REPLY: 508 495 break; 509 496 default: 510 - return -EINVAL; 497 + err = -EINVAL; 498 + goto err; 511 499 } 512 500 } 513 501 ··· 516 502 err = nft_parse_register_store(ctx, tb[NFTA_CT_DREG], &priv->dreg, NULL, 517 503 NFT_DATA_VALUE, len); 518 504 if (err < 0) 519 - return err; 505 + goto err; 520 506 521 507 err = nf_ct_netns_get(ctx->net, ctx->family); 522 508 if (err < 0) 523 - return err; 509 + goto err; 524 510 525 511 if (priv->key == NFT_CT_BYTES || 526 512 priv->key == NFT_CT_PKTS || ··· 528 514 nf_ct_set_acct(ctx->net, true); 529 515 530 516 return 0; 517 + err: 518 + __nft_ct_get_destroy(ctx, priv); 519 + return err; 531 520 } 532 521 533 522 static void __nft_ct_set_destroy(const struct nft_ctx *ctx, struct nft_ct *priv) ··· 643 626 static void nft_ct_get_destroy(const struct nft_ctx *ctx, 644 627 const struct nft_expr *expr) 645 628 { 629 + struct nft_ct *priv = nft_expr_priv(expr); 630 + 631 + __nft_ct_get_destroy(ctx, priv); 646 632 nf_ct_netns_put(ctx->net, ctx->family); 647 633 } 648 634 ··· 1193 1173 if (help) { 1194 1174 rcu_assign_pointer(help->helper, to_assign); 1195 1175 set_bit(IPS_HELPER_BIT, &ct->status); 1176 + 1177 + if ((ct->status & IPS_NAT_MASK) && !nfct_seqadj(ct)) 1178 + if (!nfct_seqadj_ext_add(ct)) 1179 + regs->verdict.code = NF_DROP; 1196 1180 } 1197 1181 } 1198 1182