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

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

Pablo Neira Ayuso says:

====================
Netfilter updates for net-next

The following batch contains Netfilter updates for net-next:

1) Replace msecs_to_jiffies() by secs_to_jiffies(), from Easwar Hariharan.

2) Allow to compile xt_cgroup with cgroupsv2 support only,
from Michal Koutny.

3) Prepare for sock_cgroup_classid() removal by wrapping it around
ifdef, also from Michal Koutny.

4) Remove redundant pointer fetch on conntrack template, from Xuanqiang Luo.

5) Re-format one block in the tproxy documentation for consistency,
from Chen Linxuan.

6) Expose set element count and type via netlink attributes,
from Florian Westphal.

* tag 'nf-next-25-04-29' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
netfilter: nf_tables: export set count and backend name to userspace
docs: tproxy: fix formatting for nft code block
netfilter: conntrack: Remove redundant NFCT_ALIGN call
net: cgroup: Guard users of sock_cgroup_classid()
netfilter: xt_cgroup: Make it independent from net_cls
netfilter: xt_IDLETIMER: convert timeouts to secs_to_jiffies()
====================

Link: https://patch.msgid.link/20250428221254.3853-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+67 -13
+2 -2
Documentation/networking/tproxy.rst
··· 69 69 # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ 70 70 --tproxy-mark 0x1/0x1 --on-port 50080 71 71 72 - Or the following rule to nft: 72 + Or the following rule to nft:: 73 73 74 - # nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept 74 + # nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept 75 75 76 76 Note that for this to work you'll have to modify the proxy to enable (SOL_IP, 77 77 IP_TRANSPARENT) for the listening socket.
+4
include/uapi/linux/netfilter/nf_tables.h
··· 394 394 * @NFTA_SET_HANDLE: set handle (NLA_U64) 395 395 * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes) 396 396 * @NFTA_SET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) 397 + * @NFTA_SET_TYPE: set backend type (NLA_STRING) 398 + * @NFTA_SET_COUNT: number of set elements (NLA_U32) 397 399 */ 398 400 enum nft_set_attributes { 399 401 NFTA_SET_UNSPEC, ··· 417 415 NFTA_SET_HANDLE, 418 416 NFTA_SET_EXPR, 419 417 NFTA_SET_EXPRESSIONS, 418 + NFTA_SET_TYPE, 419 + NFTA_SET_COUNT, 420 420 __NFTA_SET_MAX 421 421 }; 422 422 #define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
+1 -1
net/ipv4/inet_diag.c
··· 160 160 ext & (1 << (INET_DIAG_TCLASS - 1))) { 161 161 u32 classid = 0; 162 162 163 - #ifdef CONFIG_SOCK_CGROUP_DATA 163 + #ifdef CONFIG_CGROUP_NET_CLASSID 164 164 classid = sock_cgroup_classid(&sk->sk_cgrp_data); 165 165 #endif 166 166 /* Fallback to socket priority if class id isn't set.
+1 -1
net/netfilter/Kconfig
··· 1180 1180 tristate '"control group" match support' 1181 1181 depends on NETFILTER_ADVANCED 1182 1182 depends on CGROUPS 1183 - select CGROUP_NET_CLASSID 1183 + select SOCK_CGROUP_DATA 1184 1184 help 1185 1185 Socket/process control group matching allows you to match locally 1186 1186 generated packets based on which net_cls control group processes
+1 -3
net/netfilter/nf_conntrack_core.c
··· 531 531 532 532 p = tmpl; 533 533 tmpl = (struct nf_conn *)NFCT_ALIGN((unsigned long)p); 534 - if (tmpl != p) { 535 - tmpl = (struct nf_conn *)NFCT_ALIGN((unsigned long)p); 534 + if (tmpl != p) 536 535 tmpl->proto.tmpl_padto = (char *)tmpl - (char *)p; 537 - } 538 536 } else { 539 537 tmpl = kzalloc(sizeof(*tmpl), flags); 540 538 if (!tmpl)
+26
net/netfilter/nf_tables_api.c
··· 4569 4569 [NFTA_SET_HANDLE] = { .type = NLA_U64 }, 4570 4570 [NFTA_SET_EXPR] = { .type = NLA_NESTED }, 4571 4571 [NFTA_SET_EXPRESSIONS] = NLA_POLICY_NESTED_ARRAY(nft_expr_policy), 4572 + [NFTA_SET_TYPE] = { .type = NLA_REJECT }, 4573 + [NFTA_SET_COUNT] = { .type = NLA_REJECT }, 4572 4574 }; 4573 4575 4574 4576 static const struct nla_policy nft_concat_policy[NFTA_SET_FIELD_MAX + 1] = { ··· 4765 4763 return size; 4766 4764 } 4767 4765 4766 + static noinline_for_stack int 4767 + nf_tables_fill_set_info(struct sk_buff *skb, const struct nft_set *set) 4768 + { 4769 + unsigned int nelems; 4770 + char str[40]; 4771 + int ret; 4772 + 4773 + ret = snprintf(str, sizeof(str), "%ps", set->ops); 4774 + 4775 + /* Not expected to happen and harmless: NFTA_SET_TYPE is dumped 4776 + * to userspace purely for informational/debug purposes. 4777 + */ 4778 + DEBUG_NET_WARN_ON_ONCE(ret >= sizeof(str)); 4779 + 4780 + if (nla_put_string(skb, NFTA_SET_TYPE, str)) 4781 + return -EMSGSIZE; 4782 + 4783 + nelems = nft_set_userspace_size(set->ops, atomic_read(&set->nelems)); 4784 + return nla_put_be32(skb, NFTA_SET_COUNT, htonl(nelems)); 4785 + } 4786 + 4768 4787 static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx, 4769 4788 const struct nft_set *set, u16 event, u16 flags) 4770 4789 { ··· 4865 4842 goto nla_put_failure; 4866 4843 4867 4844 nla_nest_end(skb, nest); 4845 + 4846 + if (nf_tables_fill_set_info(skb, set)) 4847 + goto nla_put_failure; 4868 4848 4869 4849 if (set->num_exprs == 1) { 4870 4850 nest = nla_nest_start_noflag(skb, NFTA_SET_EXPR);
+6 -6
net/netfilter/xt_IDLETIMER.c
··· 168 168 INIT_WORK(&info->timer->work, idletimer_tg_work); 169 169 170 170 mod_timer(&info->timer->timer, 171 - msecs_to_jiffies(info->timeout * 1000) + jiffies); 171 + secs_to_jiffies(info->timeout) + jiffies); 172 172 173 173 return 0; 174 174 ··· 229 229 } else { 230 230 timer_setup(&info->timer->timer, idletimer_tg_expired, 0); 231 231 mod_timer(&info->timer->timer, 232 - msecs_to_jiffies(info->timeout * 1000) + jiffies); 232 + secs_to_jiffies(info->timeout) + jiffies); 233 233 } 234 234 235 235 return 0; ··· 254 254 info->label, info->timeout); 255 255 256 256 mod_timer(&info->timer->timer, 257 - msecs_to_jiffies(info->timeout * 1000) + jiffies); 257 + secs_to_jiffies(info->timeout) + jiffies); 258 258 259 259 return XT_CONTINUE; 260 260 } ··· 275 275 alarm_start_relative(&info->timer->alarm, tout); 276 276 } else { 277 277 mod_timer(&info->timer->timer, 278 - msecs_to_jiffies(info->timeout * 1000) + jiffies); 278 + secs_to_jiffies(info->timeout) + jiffies); 279 279 } 280 280 281 281 return XT_CONTINUE; ··· 320 320 if (info->timer) { 321 321 info->timer->refcnt++; 322 322 mod_timer(&info->timer->timer, 323 - msecs_to_jiffies(info->timeout * 1000) + jiffies); 323 + secs_to_jiffies(info->timeout) + jiffies); 324 324 325 325 pr_debug("increased refcnt of timer %s to %u\n", 326 326 info->label, info->timer->refcnt); ··· 382 382 } 383 383 } else { 384 384 mod_timer(&info->timer->timer, 385 - msecs_to_jiffies(info->timeout * 1000) + jiffies); 385 + secs_to_jiffies(info->timeout) + jiffies); 386 386 } 387 387 pr_debug("increased refcnt of timer %s to %u\n", 388 388 info->label, info->timer->refcnt);
+26
net/netfilter/xt_cgroup.c
··· 23 23 MODULE_ALIAS("ipt_cgroup"); 24 24 MODULE_ALIAS("ip6t_cgroup"); 25 25 26 + #define NET_CLS_CLASSID_INVALID_MSG "xt_cgroup: classid invalid without net_cls cgroups\n" 27 + 26 28 static int cgroup_mt_check_v0(const struct xt_mtchk_param *par) 27 29 { 28 30 struct xt_cgroup_info_v0 *info = par->matchinfo; 29 31 30 32 if (info->invert & ~1) 31 33 return -EINVAL; 34 + 35 + if (!IS_ENABLED(CONFIG_CGROUP_NET_CLASSID)) { 36 + pr_info(NET_CLS_CLASSID_INVALID_MSG); 37 + return -EINVAL; 38 + } 32 39 33 40 return 0; 34 41 } ··· 55 48 56 49 if (info->has_path && info->has_classid) { 57 50 pr_info_ratelimited("path and classid specified\n"); 51 + return -EINVAL; 52 + } 53 + 54 + if (info->has_classid && !IS_ENABLED(CONFIG_CGROUP_NET_CLASSID)) { 55 + pr_info(NET_CLS_CLASSID_INVALID_MSG); 58 56 return -EINVAL; 59 57 } 60 58 ··· 95 83 return -EINVAL; 96 84 } 97 85 86 + if (info->has_classid && !IS_ENABLED(CONFIG_CGROUP_NET_CLASSID)) { 87 + pr_info(NET_CLS_CLASSID_INVALID_MSG); 88 + return -EINVAL; 89 + } 90 + 98 91 info->priv = NULL; 99 92 if (info->has_path) { 100 93 cgrp = cgroup_get_from_path(info->path); ··· 117 100 static bool 118 101 cgroup_mt_v0(const struct sk_buff *skb, struct xt_action_param *par) 119 102 { 103 + #ifdef CONFIG_CGROUP_NET_CLASSID 120 104 const struct xt_cgroup_info_v0 *info = par->matchinfo; 121 105 struct sock *sk = skb->sk; 122 106 ··· 126 108 127 109 return (info->id == sock_cgroup_classid(&skb->sk->sk_cgrp_data)) ^ 128 110 info->invert; 111 + #endif 112 + return false; 129 113 } 130 114 131 115 static bool cgroup_mt_v1(const struct sk_buff *skb, struct xt_action_param *par) ··· 143 123 if (ancestor) 144 124 return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^ 145 125 info->invert_path; 126 + #ifdef CONFIG_CGROUP_NET_CLASSID 146 127 else 147 128 return (info->classid == sock_cgroup_classid(skcd)) ^ 148 129 info->invert_classid; 130 + #endif 131 + return false; 149 132 } 150 133 151 134 static bool cgroup_mt_v2(const struct sk_buff *skb, struct xt_action_param *par) ··· 164 141 if (ancestor) 165 142 return cgroup_is_descendant(sock_cgroup_ptr(skcd), ancestor) ^ 166 143 info->invert_path; 144 + #ifdef CONFIG_CGROUP_NET_CLASSID 167 145 else 168 146 return (info->classid == sock_cgroup_classid(skcd)) ^ 169 147 info->invert_classid; 148 + #endif 149 + return false; 170 150 } 171 151 172 152 static void cgroup_mt_destroy_v1(const struct xt_mtdtor_param *par)