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

Merge tag 'nf-next-24-08-23' 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:

Patch #1 fix checksum calculation in nfnetlink_queue with SCTP,
segment GSO packet since skb_zerocopy() does not support
GSO_BY_FRAGS, from Antonio Ojea.

Patch #2 extend nfnetlink_queue coverage to handle SCTP packets,
from Antonio Ojea.

Patch #3 uses consume_skb() instead of kfree_skb() in nfnetlink,
from Donald Hunter.

Patch #4 adds a dedicate commit list for sets to speed up
intra-transaction lookups, from Florian Westphal.

Patch #5 skips removal of element from abort path for the pipapo
backend, ditching the shadow copy of this datastructure
is sufficient.

Patch #6 moves nf_ct_netns_get() out of nf_conncount_init() to
let users of conncoiunt decide when to enable conntrack,
this is needed by openvswitch, from Xin Long.

Patch #7 pass context to all nft_parse_register_load() in
preparation for the next patch.

Patches #8 and #9 reject loads from uninitialized registers from
control plane to remove register initialization from
datapath. From Florian Westphal.

* tag 'nf-next-24-08-23' of git://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf-next:
netfilter: nf_tables: don't initialize registers in nft_do_chain()
netfilter: nf_tables: allow loads only when register is initialized
netfilter: nf_tables: pass context structure to nft_parse_register_load
netfilter: move nf_ct_netns_get out of nf_conncount_init
netfilter: nf_tables: do not remove elements if set backend implements .abort
netfilter: nf_tables: store new sets in dedicated list
netfilter: nfnetlink: convert kfree_skb to consume_skb
selftests: netfilter: nft_queue.sh: sctp coverage
netfilter: nfnetlink_queue: unbreak SCTP traffic
====================

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

+226 -84
+2 -4
include/net/netfilter/nf_conntrack_count.h
··· 15 15 unsigned int count; /* length of list */ 16 16 }; 17 17 18 - struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family, 19 - unsigned int keylen); 20 - void nf_conncount_destroy(struct net *net, unsigned int family, 21 - struct nf_conncount_data *data); 18 + struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int keylen); 19 + void nf_conncount_destroy(struct net *net, struct nf_conncount_data *data); 22 20 23 21 unsigned int nf_conncount_count(struct net *net, 24 22 struct nf_conncount_data *data,
+5 -1
include/net/netfilter/nf_tables.h
··· 221 221 u8 family; 222 222 u8 level; 223 223 bool report; 224 + DECLARE_BITMAP(reg_inited, NFT_REG32_NUM); 224 225 }; 225 226 226 227 enum nft_data_desc_flags { ··· 255 254 int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest); 256 255 int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg); 257 256 258 - int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len); 257 + int nft_parse_register_load(const struct nft_ctx *ctx, 258 + const struct nlattr *attr, u8 *sreg, u32 len); 259 259 int nft_parse_register_store(const struct nft_ctx *ctx, 260 260 const struct nlattr *attr, u8 *dreg, 261 261 const struct nft_data *data, ··· 1676 1674 1677 1675 struct nft_trans_set { 1678 1676 struct nft_trans_binding nft_trans_binding; 1677 + struct list_head list_trans_newset; 1679 1678 struct nft_set *set; 1680 1679 u32 set_id; 1681 1680 u32 gc_int; ··· 1878 1875 struct nftables_pernet { 1879 1876 struct list_head tables; 1880 1877 struct list_head commit_list; 1878 + struct list_head commit_set_list; 1881 1879 struct list_head binding_list; 1882 1880 struct list_head module_list; 1883 1881 struct list_head notify_list;
+1 -1
net/bridge/netfilter/nft_meta_bridge.c
··· 142 142 } 143 143 144 144 priv->len = len; 145 - err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len); 145 + err = nft_parse_register_load(ctx, tb[NFTA_META_SREG], &priv->sreg, len); 146 146 if (err < 0) 147 147 return err; 148 148
+1
net/core/dev.c
··· 3387 3387 out: 3388 3388 return ret; 3389 3389 } 3390 + EXPORT_SYMBOL(skb_crc32c_csum_help); 3390 3391 3391 3392 __be16 skb_network_protocol(struct sk_buff *skb, int *depth) 3392 3393 {
+2 -2
net/ipv4/netfilter/nft_dup_ipv4.c
··· 40 40 if (tb[NFTA_DUP_SREG_ADDR] == NULL) 41 41 return -EINVAL; 42 42 43 - err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, 43 + err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, 44 44 sizeof(struct in_addr)); 45 45 if (err < 0) 46 46 return err; 47 47 48 48 if (tb[NFTA_DUP_SREG_DEV]) 49 - err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], 49 + err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], 50 50 &priv->sreg_dev, sizeof(int)); 51 51 52 52 return err;
+2 -2
net/ipv6/netfilter/nft_dup_ipv6.c
··· 38 38 if (tb[NFTA_DUP_SREG_ADDR] == NULL) 39 39 return -EINVAL; 40 40 41 - err = nft_parse_register_load(tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, 41 + err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_ADDR], &priv->sreg_addr, 42 42 sizeof(struct in6_addr)); 43 43 if (err < 0) 44 44 return err; 45 45 46 46 if (tb[NFTA_DUP_SREG_DEV]) 47 - err = nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], 47 + err = nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], 48 48 &priv->sreg_dev, sizeof(int)); 49 49 50 50 return err;
+3 -12
net/netfilter/nf_conncount.c
··· 522 522 } 523 523 EXPORT_SYMBOL_GPL(nf_conncount_count); 524 524 525 - struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family, 526 - unsigned int keylen) 525 + struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int keylen) 527 526 { 528 527 struct nf_conncount_data *data; 529 - int ret, i; 528 + int i; 530 529 531 530 if (keylen % sizeof(u32) || 532 531 keylen / sizeof(u32) > MAX_KEYLEN || ··· 537 538 data = kmalloc(sizeof(*data), GFP_KERNEL); 538 539 if (!data) 539 540 return ERR_PTR(-ENOMEM); 540 - 541 - ret = nf_ct_netns_get(net, family); 542 - if (ret < 0) { 543 - kfree(data); 544 - return ERR_PTR(ret); 545 - } 546 541 547 542 for (i = 0; i < ARRAY_SIZE(data->root); ++i) 548 543 data->root[i] = RB_ROOT; ··· 574 581 } 575 582 } 576 583 577 - void nf_conncount_destroy(struct net *net, unsigned int family, 578 - struct nf_conncount_data *data) 584 + void nf_conncount_destroy(struct net *net, struct nf_conncount_data *data) 579 585 { 580 586 unsigned int i; 581 587 582 588 cancel_work_sync(&data->gc_work); 583 - nf_ct_netns_put(net, family); 584 589 585 590 for (i = 0; i < ARRAY_SIZE(data->root); ++i) 586 591 destroy_tree(&data->root[i]);
+60 -15
net/netfilter/nf_tables_api.c
··· 146 146 ctx->report = nlmsg_report(nlh); 147 147 ctx->flags = nlh->nlmsg_flags; 148 148 ctx->seq = nlh->nlmsg_seq; 149 + 150 + bitmap_zero(ctx->reg_inited, NFT_REG32_NUM); 149 151 } 150 152 151 153 static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx, ··· 395 393 { 396 394 struct nftables_pernet *nft_net = nft_pernet(net); 397 395 struct nft_trans_binding *binding; 396 + struct nft_trans_set *trans_set; 398 397 399 398 list_add_tail(&trans->list, &nft_net->commit_list); 400 399 ··· 405 402 406 403 switch (trans->msg_type) { 407 404 case NFT_MSG_NEWSET: 405 + trans_set = nft_trans_container_set(trans); 406 + 408 407 if (!nft_trans_set_update(trans) && 409 408 nft_set_is_anonymous(nft_trans_set(trans))) 410 409 list_add_tail(&binding->binding_list, &nft_net->binding_list); 410 + 411 + list_add_tail(&trans_set->list_trans_newset, &nft_net->commit_set_list); 411 412 break; 412 413 case NFT_MSG_NEWCHAIN: 413 414 if (!nft_trans_chain_update(trans) && ··· 618 611 619 612 trans_set = nft_trans_container_set(trans); 620 613 INIT_LIST_HEAD(&trans_set->nft_trans_binding.binding_list); 614 + INIT_LIST_HEAD(&trans_set->list_trans_newset); 621 615 622 616 if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] && !desc) { 623 617 nft_trans_set_id(trans) = ··· 4493 4485 { 4494 4486 struct nftables_pernet *nft_net = nft_pernet(net); 4495 4487 u32 id = ntohl(nla_get_be32(nla)); 4496 - struct nft_trans *trans; 4488 + struct nft_trans_set *trans; 4497 4489 4498 - list_for_each_entry(trans, &nft_net->commit_list, list) { 4499 - if (trans->msg_type == NFT_MSG_NEWSET) { 4500 - struct nft_set *set = nft_trans_set(trans); 4490 + /* its likely the id we need is at the tail, not at start */ 4491 + list_for_each_entry_reverse(trans, &nft_net->commit_set_list, list_trans_newset) { 4492 + struct nft_set *set = trans->set; 4501 4493 4502 - if (id == nft_trans_set_id(trans) && 4503 - set->table == table && 4504 - nft_active_genmask(set, genmask)) 4505 - return set; 4506 - } 4494 + if (id == trans->set_id && 4495 + set->table == table && 4496 + nft_active_genmask(set, genmask)) 4497 + return set; 4507 4498 } 4508 4499 return ERR_PTR(-ENOENT); 4509 4500 } ··· 10454 10447 nft_flow_rule_destroy(nft_trans_flow_rule(trans)); 10455 10448 break; 10456 10449 case NFT_MSG_NEWSET: 10450 + list_del(&nft_trans_container_set(trans)->list_trans_newset); 10457 10451 if (nft_trans_set_update(trans)) { 10458 10452 struct nft_set *set = nft_trans_set(trans); 10459 10453 ··· 10763 10755 nft_trans_destroy(trans); 10764 10756 break; 10765 10757 case NFT_MSG_NEWSET: 10758 + list_del(&nft_trans_container_set(trans)->list_trans_newset); 10766 10759 if (nft_trans_set_update(trans)) { 10767 10760 nft_trans_destroy(trans); 10768 10761 break; ··· 10791 10782 break; 10792 10783 } 10793 10784 te = nft_trans_container_elem(trans); 10794 - nft_setelem_remove(net, te->set, te->elem_priv); 10785 + if (!te->set->ops->abort || 10786 + nft_setelem_is_catchall(te->set, te->elem_priv)) 10787 + nft_setelem_remove(net, te->set, te->elem_priv); 10788 + 10795 10789 if (!nft_setelem_is_catchall(te->set, te->elem_priv)) 10796 10790 atomic_dec(&te->set->nelems); 10797 10791 ··· 10861 10849 break; 10862 10850 } 10863 10851 } 10852 + 10853 + WARN_ON_ONCE(!list_empty(&nft_net->commit_set_list)); 10864 10854 10865 10855 nft_set_abort_update(&set_update_list); 10866 10856 ··· 11040 11026 return 0; 11041 11027 } 11042 11028 11043 - int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len) 11029 + int nft_parse_register_load(const struct nft_ctx *ctx, 11030 + const struct nlattr *attr, u8 *sreg, u32 len) 11044 11031 { 11045 - u32 reg; 11046 - int err; 11032 + int err, invalid_reg; 11033 + u32 reg, next_register; 11047 11034 11048 11035 err = nft_parse_register(attr, &reg); 11049 11036 if (err < 0) ··· 11054 11039 if (err < 0) 11055 11040 return err; 11056 11041 11042 + next_register = DIV_ROUND_UP(len, NFT_REG32_SIZE) + reg; 11043 + 11044 + /* Can't happen: nft_validate_register_load() should have failed */ 11045 + if (WARN_ON_ONCE(next_register > NFT_REG32_NUM)) 11046 + return -EINVAL; 11047 + 11048 + /* find first register that did not see an earlier store. */ 11049 + invalid_reg = find_next_zero_bit(ctx->reg_inited, NFT_REG32_NUM, reg); 11050 + 11051 + /* invalid register within the range that we're loading from? */ 11052 + if (invalid_reg < next_register) 11053 + return -ENODATA; 11054 + 11057 11055 *sreg = reg; 11058 11056 return 0; 11059 11057 } 11060 11058 EXPORT_SYMBOL_GPL(nft_parse_register_load); 11059 + 11060 + static void nft_saw_register_store(const struct nft_ctx *__ctx, 11061 + int reg, unsigned int len) 11062 + { 11063 + unsigned int registers = DIV_ROUND_UP(len, NFT_REG32_SIZE); 11064 + struct nft_ctx *ctx = (struct nft_ctx *)__ctx; 11065 + 11066 + if (WARN_ON_ONCE(len == 0 || reg < 0)) 11067 + return; 11068 + 11069 + bitmap_set(ctx->reg_inited, reg, registers); 11070 + } 11061 11071 11062 11072 static int nft_validate_register_store(const struct nft_ctx *ctx, 11063 11073 enum nft_registers reg, ··· 11105 11065 return err; 11106 11066 } 11107 11067 11108 - return 0; 11068 + break; 11109 11069 default: 11110 11070 if (type != NFT_DATA_VALUE) 11111 11071 return -EINVAL; ··· 11118 11078 sizeof_field(struct nft_regs, data)) 11119 11079 return -ERANGE; 11120 11080 11121 - return 0; 11081 + break; 11122 11082 } 11083 + 11084 + nft_saw_register_store(ctx, reg, len); 11085 + return 0; 11123 11086 } 11124 11087 11125 11088 int nft_parse_register_store(const struct nft_ctx *ctx, ··· 11562 11519 11563 11520 INIT_LIST_HEAD(&nft_net->tables); 11564 11521 INIT_LIST_HEAD(&nft_net->commit_list); 11522 + INIT_LIST_HEAD(&nft_net->commit_set_list); 11565 11523 INIT_LIST_HEAD(&nft_net->binding_list); 11566 11524 INIT_LIST_HEAD(&nft_net->module_list); 11567 11525 INIT_LIST_HEAD(&nft_net->notify_list); ··· 11593 11549 gc_seq = nft_gc_seq_begin(nft_net); 11594 11550 11595 11551 WARN_ON_ONCE(!list_empty(&nft_net->commit_list)); 11552 + WARN_ON_ONCE(!list_empty(&nft_net->commit_set_list)); 11596 11553 11597 11554 if (!list_empty(&nft_net->module_list)) 11598 11555 nf_tables_module_autoload_cleanup(net);
+1 -1
net/netfilter/nf_tables_core.c
··· 256 256 const struct net *net = nft_net(pkt); 257 257 const struct nft_expr *expr, *last; 258 258 const struct nft_rule_dp *rule; 259 - struct nft_regs regs = {}; 259 + struct nft_regs regs; 260 260 unsigned int stackptr = 0; 261 261 struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE]; 262 262 bool genbit = READ_ONCE(net->nft.gencursor);
+7 -7
net/netfilter/nfnetlink.c
··· 402 402 { 403 403 nfnl_unlock(subsys_id); 404 404 netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL); 405 - return kfree_skb(skb); 405 + return consume_skb(skb); 406 406 } 407 407 } 408 408 409 409 if (!ss->valid_genid || !ss->commit || !ss->abort) { 410 410 nfnl_unlock(subsys_id); 411 411 netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL); 412 - return kfree_skb(skb); 412 + return consume_skb(skb); 413 413 } 414 414 415 415 if (!try_module_get(ss->owner)) { 416 416 nfnl_unlock(subsys_id); 417 417 netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL); 418 - return kfree_skb(skb); 418 + return consume_skb(skb); 419 419 } 420 420 421 421 if (!ss->valid_genid(net, genid)) { 422 422 module_put(ss->owner); 423 423 nfnl_unlock(subsys_id); 424 424 netlink_ack(oskb, nlh, -ERESTART, NULL); 425 - return kfree_skb(skb); 425 + return consume_skb(skb); 426 426 } 427 427 428 428 nfnl_unlock(subsys_id); ··· 567 567 if (status & NFNL_BATCH_REPLAY) { 568 568 ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD); 569 569 nfnl_err_reset(&err_list); 570 - kfree_skb(skb); 570 + consume_skb(skb); 571 571 module_put(ss->owner); 572 572 goto replay; 573 573 } else if (status == NFNL_BATCH_DONE) { ··· 593 593 err = ss->abort(net, oskb, abort_action); 594 594 if (err == -EAGAIN) { 595 595 nfnl_err_reset(&err_list); 596 - kfree_skb(skb); 596 + consume_skb(skb); 597 597 module_put(ss->owner); 598 598 status |= NFNL_BATCH_FAILURE; 599 599 goto replay_abort; ··· 601 601 } 602 602 603 603 nfnl_err_deliver(&err_list, oskb); 604 - kfree_skb(skb); 604 + consume_skb(skb); 605 605 module_put(ss->owner); 606 606 } 607 607
+2 -2
net/netfilter/nft_bitwise.c
··· 171 171 172 172 priv->len = len; 173 173 174 - err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg, 174 + err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG], &priv->sreg, 175 175 priv->len); 176 176 if (err < 0) 177 177 return err; ··· 365 365 struct nft_bitwise_fast_expr *priv = nft_expr_priv(expr); 366 366 int err; 367 367 368 - err = nft_parse_register_load(tb[NFTA_BITWISE_SREG], &priv->sreg, 368 + err = nft_parse_register_load(ctx, tb[NFTA_BITWISE_SREG], &priv->sreg, 369 369 sizeof(u32)); 370 370 if (err < 0) 371 371 return err;
+1 -1
net/netfilter/nft_byteorder.c
··· 139 139 140 140 priv->len = len; 141 141 142 - err = nft_parse_register_load(tb[NFTA_BYTEORDER_SREG], &priv->sreg, 142 + err = nft_parse_register_load(ctx, tb[NFTA_BYTEORDER_SREG], &priv->sreg, 143 143 priv->len); 144 144 if (err < 0) 145 145 return err;
+3 -3
net/netfilter/nft_cmp.c
··· 83 83 if (err < 0) 84 84 return err; 85 85 86 - err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); 86 + err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len); 87 87 if (err < 0) 88 88 return err; 89 89 ··· 222 222 if (err < 0) 223 223 return err; 224 224 225 - err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); 225 + err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len); 226 226 if (err < 0) 227 227 return err; 228 228 ··· 323 323 if (err < 0) 324 324 return err; 325 325 326 - err = nft_parse_register_load(tb[NFTA_CMP_SREG], &priv->sreg, desc.len); 326 + err = nft_parse_register_load(ctx, tb[NFTA_CMP_SREG], &priv->sreg, desc.len); 327 327 if (err < 0) 328 328 return err; 329 329
+1 -1
net/netfilter/nft_ct.c
··· 606 606 } 607 607 608 608 priv->len = len; 609 - err = nft_parse_register_load(tb[NFTA_CT_SREG], &priv->sreg, len); 609 + err = nft_parse_register_load(ctx, tb[NFTA_CT_SREG], &priv->sreg, len); 610 610 if (err < 0) 611 611 goto err1; 612 612
+1 -1
net/netfilter/nft_dup_netdev.c
··· 40 40 if (tb[NFTA_DUP_SREG_DEV] == NULL) 41 41 return -EINVAL; 42 42 43 - return nft_parse_register_load(tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev, 43 + return nft_parse_register_load(ctx, tb[NFTA_DUP_SREG_DEV], &priv->sreg_dev, 44 44 sizeof(int)); 45 45 } 46 46
+2 -2
net/netfilter/nft_dynset.c
··· 215 215 return err; 216 216 } 217 217 218 - err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key, 218 + err = nft_parse_register_load(ctx, tb[NFTA_DYNSET_SREG_KEY], &priv->sreg_key, 219 219 set->klen); 220 220 if (err < 0) 221 221 return err; ··· 226 226 if (set->dtype == NFT_DATA_VERDICT) 227 227 return -EOPNOTSUPP; 228 228 229 - err = nft_parse_register_load(tb[NFTA_DYNSET_SREG_DATA], 229 + err = nft_parse_register_load(ctx, tb[NFTA_DYNSET_SREG_DATA], 230 230 &priv->sreg_data, set->dlen); 231 231 if (err < 0) 232 232 return err;
+1 -1
net/netfilter/nft_exthdr.c
··· 588 588 priv->flags = flags; 589 589 priv->op = op; 590 590 591 - return nft_parse_register_load(tb[NFTA_EXTHDR_SREG], &priv->sreg, 591 + return nft_parse_register_load(ctx, tb[NFTA_EXTHDR_SREG], &priv->sreg, 592 592 priv->len); 593 593 } 594 594
+3 -3
net/netfilter/nft_fwd_netdev.c
··· 52 52 if (tb[NFTA_FWD_SREG_DEV] == NULL) 53 53 return -EINVAL; 54 54 55 - return nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, 55 + return nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, 56 56 sizeof(int)); 57 57 } 58 58 ··· 178 178 return -EOPNOTSUPP; 179 179 } 180 180 181 - err = nft_parse_register_load(tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, 181 + err = nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_DEV], &priv->sreg_dev, 182 182 sizeof(int)); 183 183 if (err < 0) 184 184 return err; 185 185 186 - return nft_parse_register_load(tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr, 186 + return nft_parse_register_load(ctx, tb[NFTA_FWD_SREG_ADDR], &priv->sreg_addr, 187 187 addr_len); 188 188 } 189 189
+1 -1
net/netfilter/nft_hash.c
··· 92 92 93 93 priv->len = len; 94 94 95 - err = nft_parse_register_load(tb[NFTA_HASH_SREG], &priv->sreg, len); 95 + err = nft_parse_register_load(ctx, tb[NFTA_HASH_SREG], &priv->sreg, len); 96 96 if (err < 0) 97 97 return err; 98 98
+1 -1
net/netfilter/nft_lookup.c
··· 113 113 if (IS_ERR(set)) 114 114 return PTR_ERR(set); 115 115 116 - err = nft_parse_register_load(tb[NFTA_LOOKUP_SREG], &priv->sreg, 116 + err = nft_parse_register_load(ctx, tb[NFTA_LOOKUP_SREG], &priv->sreg, 117 117 set->klen); 118 118 if (err < 0) 119 119 return err;
+2 -2
net/netfilter/nft_masq.c
··· 52 52 priv->flags = ntohl(nla_get_be32(tb[NFTA_MASQ_FLAGS])); 53 53 54 54 if (tb[NFTA_MASQ_REG_PROTO_MIN]) { 55 - err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MIN], 55 + err = nft_parse_register_load(ctx, tb[NFTA_MASQ_REG_PROTO_MIN], 56 56 &priv->sreg_proto_min, plen); 57 57 if (err < 0) 58 58 return err; 59 59 60 60 if (tb[NFTA_MASQ_REG_PROTO_MAX]) { 61 - err = nft_parse_register_load(tb[NFTA_MASQ_REG_PROTO_MAX], 61 + err = nft_parse_register_load(ctx, tb[NFTA_MASQ_REG_PROTO_MAX], 62 62 &priv->sreg_proto_max, 63 63 plen); 64 64 if (err < 0)
+1 -1
net/netfilter/nft_meta.c
··· 657 657 } 658 658 659 659 priv->len = len; 660 - err = nft_parse_register_load(tb[NFTA_META_SREG], &priv->sreg, len); 660 + err = nft_parse_register_load(ctx, tb[NFTA_META_SREG], &priv->sreg, len); 661 661 if (err < 0) 662 662 return err; 663 663
+4 -4
net/netfilter/nft_nat.c
··· 214 214 priv->family = family; 215 215 216 216 if (tb[NFTA_NAT_REG_ADDR_MIN]) { 217 - err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MIN], 217 + err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_ADDR_MIN], 218 218 &priv->sreg_addr_min, alen); 219 219 if (err < 0) 220 220 return err; 221 221 222 222 if (tb[NFTA_NAT_REG_ADDR_MAX]) { 223 - err = nft_parse_register_load(tb[NFTA_NAT_REG_ADDR_MAX], 223 + err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_ADDR_MAX], 224 224 &priv->sreg_addr_max, 225 225 alen); 226 226 if (err < 0) ··· 234 234 235 235 plen = sizeof_field(struct nf_nat_range, min_proto.all); 236 236 if (tb[NFTA_NAT_REG_PROTO_MIN]) { 237 - err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MIN], 237 + err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_PROTO_MIN], 238 238 &priv->sreg_proto_min, plen); 239 239 if (err < 0) 240 240 return err; 241 241 242 242 if (tb[NFTA_NAT_REG_PROTO_MAX]) { 243 - err = nft_parse_register_load(tb[NFTA_NAT_REG_PROTO_MAX], 243 + err = nft_parse_register_load(ctx, tb[NFTA_NAT_REG_PROTO_MAX], 244 244 &priv->sreg_proto_max, 245 245 plen); 246 246 if (err < 0)
+1 -1
net/netfilter/nft_objref.c
··· 143 143 if (!(set->flags & NFT_SET_OBJECT)) 144 144 return -EINVAL; 145 145 146 - err = nft_parse_register_load(tb[NFTA_OBJREF_SET_SREG], &priv->sreg, 146 + err = nft_parse_register_load(ctx, tb[NFTA_OBJREF_SET_SREG], &priv->sreg, 147 147 set->klen); 148 148 if (err < 0) 149 149 return err;
+1 -1
net/netfilter/nft_payload.c
··· 981 981 } 982 982 priv->csum_type = csum_type; 983 983 984 - return nft_parse_register_load(tb[NFTA_PAYLOAD_SREG], &priv->sreg, 984 + return nft_parse_register_load(ctx, tb[NFTA_PAYLOAD_SREG], &priv->sreg, 985 985 priv->len); 986 986 } 987 987
+1 -1
net/netfilter/nft_queue.c
··· 136 136 struct nft_queue *priv = nft_expr_priv(expr); 137 137 int err; 138 138 139 - err = nft_parse_register_load(tb[NFTA_QUEUE_SREG_QNUM], 139 + err = nft_parse_register_load(ctx, tb[NFTA_QUEUE_SREG_QNUM], 140 140 &priv->sreg_qnum, sizeof(u32)); 141 141 if (err < 0) 142 142 return err;
+1 -1
net/netfilter/nft_range.c
··· 83 83 goto err2; 84 84 } 85 85 86 - err = nft_parse_register_load(tb[NFTA_RANGE_SREG], &priv->sreg, 86 + err = nft_parse_register_load(ctx, tb[NFTA_RANGE_SREG], &priv->sreg, 87 87 desc_from.len); 88 88 if (err < 0) 89 89 goto err2;
+2 -2
net/netfilter/nft_redir.c
··· 51 51 52 52 plen = sizeof_field(struct nf_nat_range, min_proto.all); 53 53 if (tb[NFTA_REDIR_REG_PROTO_MIN]) { 54 - err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MIN], 54 + err = nft_parse_register_load(ctx, tb[NFTA_REDIR_REG_PROTO_MIN], 55 55 &priv->sreg_proto_min, plen); 56 56 if (err < 0) 57 57 return err; 58 58 59 59 if (tb[NFTA_REDIR_REG_PROTO_MAX]) { 60 - err = nft_parse_register_load(tb[NFTA_REDIR_REG_PROTO_MAX], 60 + err = nft_parse_register_load(ctx, tb[NFTA_REDIR_REG_PROTO_MAX], 61 61 &priv->sreg_proto_max, 62 62 plen); 63 63 if (err < 0)
+2 -2
net/netfilter/nft_tproxy.c
··· 254 254 } 255 255 256 256 if (tb[NFTA_TPROXY_REG_ADDR]) { 257 - err = nft_parse_register_load(tb[NFTA_TPROXY_REG_ADDR], 257 + err = nft_parse_register_load(ctx, tb[NFTA_TPROXY_REG_ADDR], 258 258 &priv->sreg_addr, alen); 259 259 if (err < 0) 260 260 return err; 261 261 } 262 262 263 263 if (tb[NFTA_TPROXY_REG_PORT]) { 264 - err = nft_parse_register_load(tb[NFTA_TPROXY_REG_PORT], 264 + err = nft_parse_register_load(ctx, tb[NFTA_TPROXY_REG_PORT], 265 265 &priv->sreg_port, sizeof(u16)); 266 266 if (err < 0) 267 267 return err;
+13 -2
net/netfilter/xt_connlimit.c
··· 86 86 { 87 87 struct xt_connlimit_info *info = par->matchinfo; 88 88 unsigned int keylen; 89 + int ret; 89 90 90 91 keylen = sizeof(u32); 91 92 if (par->family == NFPROTO_IPV6) ··· 94 93 else 95 94 keylen += sizeof(struct in_addr); 96 95 96 + ret = nf_ct_netns_get(par->net, par->family); 97 + if (ret < 0) { 98 + pr_info_ratelimited("cannot load conntrack support for proto=%u\n", 99 + par->family); 100 + return ret; 101 + } 102 + 97 103 /* init private data */ 98 - info->data = nf_conncount_init(par->net, par->family, keylen); 104 + info->data = nf_conncount_init(par->net, keylen); 105 + if (IS_ERR(info->data)) 106 + nf_ct_netns_put(par->net, par->family); 99 107 100 108 return PTR_ERR_OR_ZERO(info->data); 101 109 } ··· 113 103 { 114 104 const struct xt_connlimit_info *info = par->matchinfo; 115 105 116 - nf_conncount_destroy(par->net, par->family, info->data); 106 + nf_conncount_destroy(par->net, info->data); 107 + nf_ct_netns_put(par->net, par->family); 117 108 } 118 109 119 110 static struct xt_match connlimit_mt_reg __read_mostly = {
+2 -3
net/openvswitch/conntrack.c
··· 1608 1608 for (i = 0; i < CT_LIMIT_HASH_BUCKETS; i++) 1609 1609 INIT_HLIST_HEAD(&ovs_net->ct_limit_info->limits[i]); 1610 1610 1611 - ovs_net->ct_limit_info->data = 1612 - nf_conncount_init(net, NFPROTO_INET, sizeof(u32)); 1611 + ovs_net->ct_limit_info->data = nf_conncount_init(net, sizeof(u32)); 1613 1612 1614 1613 if (IS_ERR(ovs_net->ct_limit_info->data)) { 1615 1614 err = PTR_ERR(ovs_net->ct_limit_info->data); ··· 1625 1626 const struct ovs_ct_limit_info *info = ovs_net->ct_limit_info; 1626 1627 int i; 1627 1628 1628 - nf_conncount_destroy(net, NFPROTO_INET, info->data); 1629 + nf_conncount_destroy(net, info->data); 1629 1630 for (i = 0; i < CT_LIMIT_HASH_BUCKETS; ++i) { 1630 1631 struct hlist_head *head = &info->limits[i]; 1631 1632 struct ovs_ct_limit *ct_limit;
+2
tools/testing/selftests/net/netfilter/config
··· 87 87 CONFIG_XFRM_STATISTICS=y 88 88 CONFIG_NET_PKTGEN=m 89 89 CONFIG_TUN=m 90 + CONFIG_INET_DIAG=m 91 + CONFIG_SCTP_DIAG=m
+84 -1
tools/testing/selftests/net/netfilter/nft_queue.sh
··· 25 25 } 26 26 27 27 checktool "nft --version" "test without nft tool" 28 + checktool "socat -h" "run test without socat" 29 + 30 + modprobe -q sctp 28 31 29 32 trap cleanup EXIT 30 33 ··· 268 265 269 266 test_tcp_localhost() 270 267 { 271 - dd conv=sparse status=none if=/dev/zero bs=1M count=200 of="$TMPINPUT" 272 268 timeout 5 ip netns exec "$nsrouter" socat -u TCP-LISTEN:12345 STDOUT >/dev/null & 273 269 local rpid=$! 274 270 ··· 377 375 wait 2>/dev/null 378 376 } 379 377 378 + sctp_listener_ready() 379 + { 380 + ss -S -N "$1" -ln -o "sport = :12345" | grep -q 12345 381 + } 382 + 383 + test_sctp_forward() 384 + { 385 + ip netns exec "$nsrouter" nft -f /dev/stdin <<EOF 386 + flush ruleset 387 + table inet sctpq { 388 + chain forward { 389 + type filter hook forward priority 0; policy accept; 390 + sctp dport 12345 queue num 10 391 + } 392 + } 393 + EOF 394 + timeout 60 ip netns exec "$ns2" socat -u SCTP-LISTEN:12345 STDOUT > "$TMPFILE1" & 395 + local rpid=$! 396 + 397 + busywait "$BUSYWAIT_TIMEOUT" sctp_listener_ready "$ns2" 398 + 399 + ip netns exec "$nsrouter" ./nf_queue -q 10 -G -t "$timeout" & 400 + local nfqpid=$! 401 + 402 + ip netns exec "$ns1" socat -u STDIN SCTP:10.0.2.99:12345 <"$TMPINPUT" >/dev/null 403 + 404 + if ! ip netns exec "$nsrouter" nft delete table inet sctpq; then 405 + echo "FAIL: Could not delete sctpq table" 406 + exit 1 407 + fi 408 + 409 + wait "$rpid" && echo "PASS: sctp and nfqueue in forward chain" 410 + 411 + if ! diff -u "$TMPINPUT" "$TMPFILE1" ; then 412 + echo "FAIL: lost packets?!" 1>&2 413 + exit 1 414 + fi 415 + } 416 + 417 + test_sctp_output() 418 + { 419 + ip netns exec "$ns1" nft -f /dev/stdin <<EOF 420 + table inet sctpq { 421 + chain output { 422 + type filter hook output priority 0; policy accept; 423 + sctp dport 12345 queue num 11 424 + } 425 + } 426 + EOF 427 + # reduce test file size, software segmentation causes sk wmem increase. 428 + dd conv=sparse status=none if=/dev/zero bs=1M count=50 of="$TMPINPUT" 429 + 430 + timeout 60 ip netns exec "$ns2" socat -u SCTP-LISTEN:12345 STDOUT > "$TMPFILE1" & 431 + local rpid=$! 432 + 433 + busywait "$BUSYWAIT_TIMEOUT" sctp_listener_ready "$ns2" 434 + 435 + ip netns exec "$ns1" ./nf_queue -q 11 -t "$timeout" & 436 + local nfqpid=$! 437 + 438 + ip netns exec "$ns1" socat -u STDIN SCTP:10.0.2.99:12345 <"$TMPINPUT" >/dev/null 439 + 440 + if ! ip netns exec "$ns1" nft delete table inet sctpq; then 441 + echo "FAIL: Could not delete sctpq table" 442 + exit 1 443 + fi 444 + 445 + # must wait before checking completeness of output file. 446 + wait "$rpid" && echo "PASS: sctp and nfqueue in output chain with GSO" 447 + 448 + if ! diff -u "$TMPINPUT" "$TMPFILE1" ; then 449 + echo "FAIL: lost packets?!" 1>&2 450 + exit 1 451 + fi 452 + } 453 + 380 454 test_queue_removal() 381 455 { 382 456 read tainted_then < /proc/sys/kernel/tainted ··· 521 443 # same. We queue to a second program as well. 522 444 load_ruleset "filter2" 20 523 445 test_queue 20 446 + ip netns exec "$ns1" nft flush ruleset 524 447 525 448 test_tcp_forward 526 449 test_tcp_localhost 527 450 test_tcp_localhost_connectclose 528 451 test_tcp_localhost_requeue 452 + test_sctp_forward 453 + test_sctp_output 454 + 455 + # should be last, adds vrf device in ns1 and changes routes 529 456 test_icmp_vrf 530 457 test_queue_removal 531 458