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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'nf-24-01-24' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf

Pablo Neira Ayuso says:

====================
Netfilter fixes for net

The following patchset contains Netfilter fixes for net:

1) Update nf_tables kdoc to keep it in sync with the code, from George Guo.

2) Handle NETDEV_UNREGISTER event for inet/ingress basechain.

3) Reject configuration that cause nft_limit to overflow,
from Florian Westphal.

4) Restrict anonymous set/map names to 16 bytes, from Florian Westphal.

5) Disallow to encode queue number and error in verdicts. This reverts
a patch which seems to have introduced an early attempt to support for
nfqueue maps, which is these days supported via nft_queue expression.

6) Sanitize family via .validate for expressions that explicitly refer
to NF_INET_* hooks.

* tag 'nf-24-01-24' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf:
netfilter: nf_tables: validate NFPROTO_* family
netfilter: nf_tables: reject QUEUE/DROP verdict parameters
netfilter: nf_tables: restrict anonymous set and map names to 16 bytes
netfilter: nft_limit: reject configurations that cause integer overflow
netfilter: nft_chain_filter: handle NETDEV_UNREGISTER for inet/ingress basechain
netfilter: nf_tables: cleanup documentation
====================

Link: https://lore.kernel.org/r/20240124191248.75463-1-pablo@netfilter.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+121 -31
+39 -10
include/net/netfilter/nf_tables.h
··· 205 205 * @nla: netlink attributes 206 206 * @portid: netlink portID of the original message 207 207 * @seq: netlink sequence number 208 + * @flags: modifiers to new request 208 209 * @family: protocol family 209 210 * @level: depth of the chains 210 211 * @report: notify via unicast netlink message ··· 283 282 * 284 283 * @key: element key 285 284 * @key_end: closing element key 285 + * @data: element data 286 286 * @priv: element private data and extensions 287 287 */ 288 288 struct nft_set_elem { ··· 327 325 * @dtype: data type 328 326 * @dlen: data length 329 327 * @objtype: object type 330 - * @flags: flags 331 328 * @size: number of set elements 332 329 * @policy: set policy 333 330 * @gc_int: garbage collector interval 331 + * @timeout: element timeout 334 332 * @field_len: length of each field in concatenation, bytes 335 333 * @field_count: number of concatenated fields in element 336 334 * @expr: set must support for expressions ··· 353 351 /** 354 352 * enum nft_set_class - performance class 355 353 * 356 - * @NFT_LOOKUP_O_1: constant, O(1) 357 - * @NFT_LOOKUP_O_LOG_N: logarithmic, O(log N) 358 - * @NFT_LOOKUP_O_N: linear, O(N) 354 + * @NFT_SET_CLASS_O_1: constant, O(1) 355 + * @NFT_SET_CLASS_O_LOG_N: logarithmic, O(log N) 356 + * @NFT_SET_CLASS_O_N: linear, O(N) 359 357 */ 360 358 enum nft_set_class { 361 359 NFT_SET_CLASS_O_1, ··· 424 422 * @remove: remove element from set 425 423 * @walk: iterate over all set elements 426 424 * @get: get set elements 425 + * @commit: commit set elements 426 + * @abort: abort set elements 427 427 * @privsize: function to return size of set private data 428 + * @estimate: estimate the required memory size and the lookup complexity class 428 429 * @init: initialize private data of new set instance 429 430 * @destroy: destroy private data of set instance 431 + * @gc_init: initialize garbage collection 430 432 * @elemsize: element private size 431 433 * 432 434 * Operations lookup, update and delete have simpler interfaces, are faster ··· 546 540 * @policy: set parameterization (see enum nft_set_policies) 547 541 * @udlen: user data length 548 542 * @udata: user data 549 - * @expr: stateful expression 543 + * @pending_update: list of pending update set element 550 544 * @ops: set ops 551 545 * @flags: set flags 552 546 * @dead: set will be freed, never cleared 553 547 * @genmask: generation mask 554 548 * @klen: key length 555 549 * @dlen: data length 550 + * @num_exprs: numbers of exprs 551 + * @exprs: stateful expression 552 + * @catchall_list: list of catch-all set element 556 553 * @data: private set data 557 554 */ 558 555 struct nft_set { ··· 701 692 * 702 693 * @len: length of extension area 703 694 * @offset: offsets of individual extension types 695 + * @ext_len: length of the expected extension(used to sanity check) 704 696 */ 705 697 struct nft_set_ext_tmpl { 706 698 u16 len; ··· 850 840 * @select_ops: function to select nft_expr_ops 851 841 * @release_ops: release nft_expr_ops 852 842 * @ops: default ops, used when no select_ops functions is present 843 + * @inner_ops: inner ops, used for inner packet operation 853 844 * @list: used internally 854 845 * @name: Identifier 855 846 * @owner: module reference ··· 892 881 * struct nft_expr_ops - nf_tables expression operations 893 882 * 894 883 * @eval: Expression evaluation function 884 + * @clone: Expression clone function 895 885 * @size: full expression size, including private data size 896 886 * @init: initialization function 897 887 * @activate: activate expression in the next generation 898 888 * @deactivate: deactivate expression in next generation 899 889 * @destroy: destruction function, called after synchronize_rcu 890 + * @destroy_clone: destruction clone function 900 891 * @dump: function to dump parameters 901 - * @type: expression type 902 892 * @validate: validate expression, called during loop detection 893 + * @reduce: reduce expression 894 + * @gc: garbage collection expression 895 + * @offload: hardware offload expression 896 + * @offload_action: function to report true/false to allocate one slot or not in the flow 897 + * offload array 898 + * @offload_stats: function to synchronize hardware stats via updating the counter expression 899 + * @type: expression type 903 900 * @data: extra data to attach to this expression operation 904 901 */ 905 902 struct nft_expr_ops { ··· 1060 1041 /** 1061 1042 * struct nft_chain - nf_tables chain 1062 1043 * 1044 + * @blob_gen_0: rule blob pointer to the current generation 1045 + * @blob_gen_1: rule blob pointer to the future generation 1063 1046 * @rules: list of rules in the chain 1064 1047 * @list: used internally 1065 1048 * @rhlhead: used internally 1066 1049 * @table: table that this chain belongs to 1067 1050 * @handle: chain handle 1068 1051 * @use: number of jump references to this chain 1069 - * @flags: bitmask of enum nft_chain_flags 1052 + * @flags: bitmask of enum NFTA_CHAIN_FLAGS 1053 + * @bound: bind or not 1054 + * @genmask: generation mask 1070 1055 * @name: name of the chain 1056 + * @udlen: user data length 1057 + * @udata: user data in the chain 1058 + * @blob_next: rule blob pointer to the next in the chain 1071 1059 */ 1072 1060 struct nft_chain { 1073 1061 struct nft_rule_blob __rcu *blob_gen_0; ··· 1172 1146 * @hook_list: list of netfilter hooks (for NFPROTO_NETDEV family) 1173 1147 * @type: chain type 1174 1148 * @policy: default policy 1149 + * @flags: indicate the base chain disabled or not 1175 1150 * @stats: per-cpu chain stats 1176 1151 * @chain: the chain 1177 1152 * @flow_block: flow block (for hardware offload) ··· 1301 1274 * struct nft_object - nf_tables stateful object 1302 1275 * 1303 1276 * @list: table stateful object list node 1304 - * @key: keys that identify this object 1305 1277 * @rhlhead: nft_objname_ht node 1278 + * @key: keys that identify this object 1306 1279 * @genmask: generation mask 1307 1280 * @use: number of references to this stateful object 1308 1281 * @handle: unique object handle 1282 + * @udlen: length of user data 1283 + * @udata: user data 1309 1284 * @ops: object operations 1310 1285 * @data: object data, layout depends on type 1311 1286 */ ··· 1373 1344 * @destroy: release existing stateful object 1374 1345 * @dump: netlink dump stateful object 1375 1346 * @update: update stateful object 1347 + * @type: pointer to object type 1376 1348 */ 1377 1349 struct nft_object_ops { 1378 1350 void (*eval)(struct nft_object *obj, ··· 1409 1379 * @genmask: generation mask 1410 1380 * @use: number of references to this flow table 1411 1381 * @handle: unique object handle 1412 - * @dev_name: array of device names 1382 + * @hook_list: hook list for hooks per net_device in flowtables 1413 1383 * @data: rhashtable and garbage collector 1414 - * @ops: array of hooks 1415 1384 */ 1416 1385 struct nft_flowtable { 1417 1386 struct list_head list;
+10 -10
net/netfilter/nf_tables_api.c
··· 24 24 #include <net/sock.h> 25 25 26 26 #define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-")) 27 + #define NFT_SET_MAX_ANONLEN 16 27 28 28 29 unsigned int nf_tables_net_id __read_mostly; 29 30 ··· 4412 4411 p = strchr(name, '%'); 4413 4412 if (p != NULL) { 4414 4413 if (p[1] != 'd' || strchr(p + 2, '%')) 4414 + return -EINVAL; 4415 + 4416 + if (strnlen(name, NFT_SET_MAX_ANONLEN) >= NFT_SET_MAX_ANONLEN) 4415 4417 return -EINVAL; 4416 4418 4417 4419 inuse = (unsigned long *)get_zeroed_page(GFP_KERNEL); ··· 10992 10988 data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); 10993 10989 10994 10990 switch (data->verdict.code) { 10995 - default: 10996 - switch (data->verdict.code & NF_VERDICT_MASK) { 10997 - case NF_ACCEPT: 10998 - case NF_DROP: 10999 - case NF_QUEUE: 11000 - break; 11001 - default: 11002 - return -EINVAL; 11003 - } 11004 - fallthrough; 10991 + case NF_ACCEPT: 10992 + case NF_DROP: 10993 + case NF_QUEUE: 10994 + break; 11005 10995 case NFT_CONTINUE: 11006 10996 case NFT_BREAK: 11007 10997 case NFT_RETURN: ··· 11030 11032 11031 11033 data->verdict.chain = chain; 11032 11034 break; 11035 + default: 11036 + return -EINVAL; 11033 11037 } 11034 11038 11035 11039 desc->len = sizeof(data->verdict);
+9 -2
net/netfilter/nft_chain_filter.c
··· 357 357 unsigned long event, void *ptr) 358 358 { 359 359 struct net_device *dev = netdev_notifier_info_to_dev(ptr); 360 + struct nft_base_chain *basechain; 360 361 struct nftables_pernet *nft_net; 361 - struct nft_table *table; 362 362 struct nft_chain *chain, *nr; 363 + struct nft_table *table; 363 364 struct nft_ctx ctx = { 364 365 .net = dev_net(dev), 365 366 }; ··· 372 371 nft_net = nft_pernet(ctx.net); 373 372 mutex_lock(&nft_net->commit_mutex); 374 373 list_for_each_entry(table, &nft_net->tables, list) { 375 - if (table->family != NFPROTO_NETDEV) 374 + if (table->family != NFPROTO_NETDEV && 375 + table->family != NFPROTO_INET) 376 376 continue; 377 377 378 378 ctx.family = table->family; 379 379 ctx.table = table; 380 380 list_for_each_entry_safe(chain, nr, &table->chains, list) { 381 381 if (!nft_is_base_chain(chain)) 382 + continue; 383 + 384 + basechain = nft_base_chain(chain); 385 + if (table->family == NFPROTO_INET && 386 + basechain->ops.hooknum != NF_INET_INGRESS) 382 387 continue; 383 388 384 389 ctx.chain = chain;
+12
net/netfilter/nft_compat.c
··· 350 350 unsigned int hook_mask = 0; 351 351 int ret; 352 352 353 + if (ctx->family != NFPROTO_IPV4 && 354 + ctx->family != NFPROTO_IPV6 && 355 + ctx->family != NFPROTO_BRIDGE && 356 + ctx->family != NFPROTO_ARP) 357 + return -EOPNOTSUPP; 358 + 353 359 if (nft_is_base_chain(ctx->chain)) { 354 360 const struct nft_base_chain *basechain = 355 361 nft_base_chain(ctx->chain); ··· 600 594 struct xt_match *match = expr->ops->data; 601 595 unsigned int hook_mask = 0; 602 596 int ret; 597 + 598 + if (ctx->family != NFPROTO_IPV4 && 599 + ctx->family != NFPROTO_IPV6 && 600 + ctx->family != NFPROTO_BRIDGE && 601 + ctx->family != NFPROTO_ARP) 602 + return -EOPNOTSUPP; 603 603 604 604 if (nft_is_base_chain(ctx->chain)) { 605 605 const struct nft_base_chain *basechain =
+5
net/netfilter/nft_flow_offload.c
··· 384 384 { 385 385 unsigned int hook_mask = (1 << NF_INET_FORWARD); 386 386 387 + if (ctx->family != NFPROTO_IPV4 && 388 + ctx->family != NFPROTO_IPV6 && 389 + ctx->family != NFPROTO_INET) 390 + return -EOPNOTSUPP; 391 + 387 392 return nft_chain_validate_hooks(ctx->chain, hook_mask); 388 393 } 389 394
+16 -7
net/netfilter/nft_limit.c
··· 58 58 static int nft_limit_init(struct nft_limit_priv *priv, 59 59 const struct nlattr * const tb[], bool pkts) 60 60 { 61 + u64 unit, tokens, rate_with_burst; 61 62 bool invert = false; 62 - u64 unit, tokens; 63 63 64 64 if (tb[NFTA_LIMIT_RATE] == NULL || 65 65 tb[NFTA_LIMIT_UNIT] == NULL) 66 66 return -EINVAL; 67 67 68 68 priv->rate = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_RATE])); 69 + if (priv->rate == 0) 70 + return -EINVAL; 71 + 69 72 unit = be64_to_cpu(nla_get_be64(tb[NFTA_LIMIT_UNIT])); 70 - priv->nsecs = unit * NSEC_PER_SEC; 71 - if (priv->rate == 0 || priv->nsecs < unit) 73 + if (check_mul_overflow(unit, NSEC_PER_SEC, &priv->nsecs)) 72 74 return -EOVERFLOW; 73 75 74 76 if (tb[NFTA_LIMIT_BURST]) ··· 79 77 if (pkts && priv->burst == 0) 80 78 priv->burst = NFT_LIMIT_PKT_BURST_DEFAULT; 81 79 82 - if (priv->rate + priv->burst < priv->rate) 80 + if (check_add_overflow(priv->rate, priv->burst, &rate_with_burst)) 83 81 return -EOVERFLOW; 84 82 85 83 if (pkts) { 86 - tokens = div64_u64(priv->nsecs, priv->rate) * priv->burst; 84 + u64 tmp = div64_u64(priv->nsecs, priv->rate); 85 + 86 + if (check_mul_overflow(tmp, priv->burst, &tokens)) 87 + return -EOVERFLOW; 87 88 } else { 89 + u64 tmp; 90 + 88 91 /* The token bucket size limits the number of tokens can be 89 92 * accumulated. tokens_max specifies the bucket size. 90 93 * tokens_max = unit * (rate + burst) / rate. 91 94 */ 92 - tokens = div64_u64(priv->nsecs * (priv->rate + priv->burst), 93 - priv->rate); 95 + if (check_mul_overflow(priv->nsecs, rate_with_burst, &tmp)) 96 + return -EOVERFLOW; 97 + 98 + tokens = div64_u64(tmp, priv->rate); 94 99 } 95 100 96 101 if (tb[NFTA_LIMIT_FLAGS]) {
+5
net/netfilter/nft_nat.c
··· 143 143 struct nft_nat *priv = nft_expr_priv(expr); 144 144 int err; 145 145 146 + if (ctx->family != NFPROTO_IPV4 && 147 + ctx->family != NFPROTO_IPV6 && 148 + ctx->family != NFPROTO_INET) 149 + return -EOPNOTSUPP; 150 + 146 151 err = nft_chain_validate_dependency(ctx->chain, NFT_CHAIN_T_NAT); 147 152 if (err < 0) 148 153 return err;
+5
net/netfilter/nft_rt.c
··· 166 166 const struct nft_rt *priv = nft_expr_priv(expr); 167 167 unsigned int hooks; 168 168 169 + if (ctx->family != NFPROTO_IPV4 && 170 + ctx->family != NFPROTO_IPV6 && 171 + ctx->family != NFPROTO_INET) 172 + return -EOPNOTSUPP; 173 + 169 174 switch (priv->key) { 170 175 case NFT_RT_NEXTHOP4: 171 176 case NFT_RT_NEXTHOP6:
+5
net/netfilter/nft_socket.c
··· 242 242 const struct nft_expr *expr, 243 243 const struct nft_data **data) 244 244 { 245 + if (ctx->family != NFPROTO_IPV4 && 246 + ctx->family != NFPROTO_IPV6 && 247 + ctx->family != NFPROTO_INET) 248 + return -EOPNOTSUPP; 249 + 245 250 return nft_chain_validate_hooks(ctx->chain, 246 251 (1 << NF_INET_PRE_ROUTING) | 247 252 (1 << NF_INET_LOCAL_IN) |
+5 -2
net/netfilter/nft_synproxy.c
··· 186 186 break; 187 187 #endif 188 188 case NFPROTO_INET: 189 - case NFPROTO_BRIDGE: 190 189 err = nf_synproxy_ipv4_init(snet, ctx->net); 191 190 if (err) 192 191 goto nf_ct_failure; ··· 218 219 break; 219 220 #endif 220 221 case NFPROTO_INET: 221 - case NFPROTO_BRIDGE: 222 222 nf_synproxy_ipv4_fini(snet, ctx->net); 223 223 nf_synproxy_ipv6_fini(snet, ctx->net); 224 224 break; ··· 251 253 const struct nft_expr *expr, 252 254 const struct nft_data **data) 253 255 { 256 + if (ctx->family != NFPROTO_IPV4 && 257 + ctx->family != NFPROTO_IPV6 && 258 + ctx->family != NFPROTO_INET) 259 + return -EOPNOTSUPP; 260 + 254 261 return nft_chain_validate_hooks(ctx->chain, (1 << NF_INET_LOCAL_IN) | 255 262 (1 << NF_INET_FORWARD)); 256 263 }
+5
net/netfilter/nft_tproxy.c
··· 316 316 const struct nft_expr *expr, 317 317 const struct nft_data **data) 318 318 { 319 + if (ctx->family != NFPROTO_IPV4 && 320 + ctx->family != NFPROTO_IPV6 && 321 + ctx->family != NFPROTO_INET) 322 + return -EOPNOTSUPP; 323 + 319 324 return nft_chain_validate_hooks(ctx->chain, 1 << NF_INET_PRE_ROUTING); 320 325 } 321 326
+5
net/netfilter/nft_xfrm.c
··· 235 235 const struct nft_xfrm *priv = nft_expr_priv(expr); 236 236 unsigned int hooks; 237 237 238 + if (ctx->family != NFPROTO_IPV4 && 239 + ctx->family != NFPROTO_IPV6 && 240 + ctx->family != NFPROTO_INET) 241 + return -EOPNOTSUPP; 242 + 238 243 switch (priv->dir) { 239 244 case XFRM_POLICY_IN: 240 245 hooks = (1 << NF_INET_FORWARD) |