Skip to content

Commit b2ede25

Browse files
committed
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 alobakin#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/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 18aaa82 + c88baab commit b2ede25

34 files changed

+226
-84
lines changed

include/net/netfilter/nf_conntrack_count.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,8 @@ struct nf_conncount_list {
1515
unsigned int count; /* length of list */
1616
};
1717

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);
2220

2321
unsigned int nf_conncount_count(struct net *net,
2422
struct nf_conncount_data *data,

include/net/netfilter/nf_tables.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ struct nft_ctx {
221221
u8 family;
222222
u8 level;
223223
bool report;
224+
DECLARE_BITMAP(reg_inited, NFT_REG32_NUM);
224225
};
225226

226227
enum nft_data_desc_flags {
@@ -254,7 +255,8 @@ static inline enum nft_registers nft_type_to_reg(enum nft_data_types type)
254255
int nft_parse_u32_check(const struct nlattr *attr, int max, u32 *dest);
255256
int nft_dump_register(struct sk_buff *skb, unsigned int attr, unsigned int reg);
256257

257-
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len);
258+
int nft_parse_register_load(const struct nft_ctx *ctx,
259+
const struct nlattr *attr, u8 *sreg, u32 len);
258260
int nft_parse_register_store(const struct nft_ctx *ctx,
259261
const struct nlattr *attr, u8 *dreg,
260262
const struct nft_data *data,
@@ -1674,6 +1676,7 @@ struct nft_trans_rule {
16741676

16751677
struct nft_trans_set {
16761678
struct nft_trans_binding nft_trans_binding;
1679+
struct list_head list_trans_newset;
16771680
struct nft_set *set;
16781681
u32 set_id;
16791682
u32 gc_int;
@@ -1875,6 +1878,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
18751878
struct nftables_pernet {
18761879
struct list_head tables;
18771880
struct list_head commit_list;
1881+
struct list_head commit_set_list;
18781882
struct list_head binding_list;
18791883
struct list_head module_list;
18801884
struct list_head notify_list;

net/bridge/netfilter/nft_meta_bridge.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static int nft_meta_bridge_set_init(const struct nft_ctx *ctx,
142142
}
143143

144144
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);
146146
if (err < 0)
147147
return err;
148148

net/core/dev.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3387,6 +3387,7 @@ int skb_crc32c_csum_help(struct sk_buff *skb)
33873387
out:
33883388
return ret;
33893389
}
3390+
EXPORT_SYMBOL(skb_crc32c_csum_help);
33903391

33913392
__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
33923393
{

net/ipv4/netfilter/nft_dup_ipv4.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ static int nft_dup_ipv4_init(const struct nft_ctx *ctx,
4040
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
4141
return -EINVAL;
4242

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,
4444
sizeof(struct in_addr));
4545
if (err < 0)
4646
return err;
4747

4848
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],
5050
&priv->sreg_dev, sizeof(int));
5151

5252
return err;

net/ipv6/netfilter/nft_dup_ipv6.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ static int nft_dup_ipv6_init(const struct nft_ctx *ctx,
3838
if (tb[NFTA_DUP_SREG_ADDR] == NULL)
3939
return -EINVAL;
4040

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,
4242
sizeof(struct in6_addr));
4343
if (err < 0)
4444
return err;
4545

4646
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],
4848
&priv->sreg_dev, sizeof(int));
4949

5050
return err;

net/netfilter/nf_conncount.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -522,11 +522,10 @@ unsigned int nf_conncount_count(struct net *net,
522522
}
523523
EXPORT_SYMBOL_GPL(nf_conncount_count);
524524

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)
527526
{
528527
struct nf_conncount_data *data;
529-
int ret, i;
528+
int i;
530529

531530
if (keylen % sizeof(u32) ||
532531
keylen / sizeof(u32) > MAX_KEYLEN ||
@@ -539,12 +538,6 @@ struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family
539538
if (!data)
540539
return ERR_PTR(-ENOMEM);
541540

542-
ret = nf_ct_netns_get(net, family);
543-
if (ret < 0) {
544-
kfree(data);
545-
return ERR_PTR(ret);
546-
}
547-
548541
for (i = 0; i < ARRAY_SIZE(data->root); ++i)
549542
data->root[i] = RB_ROOT;
550543

@@ -581,13 +574,11 @@ static void destroy_tree(struct rb_root *r)
581574
}
582575
}
583576

584-
void nf_conncount_destroy(struct net *net, unsigned int family,
585-
struct nf_conncount_data *data)
577+
void nf_conncount_destroy(struct net *net, struct nf_conncount_data *data)
586578
{
587579
unsigned int i;
588580

589581
cancel_work_sync(&data->gc_work);
590-
nf_ct_netns_put(net, family);
591582

592583
for (i = 0; i < ARRAY_SIZE(data->root); ++i)
593584
destroy_tree(&data->root[i]);

net/netfilter/nf_tables_api.c

Lines changed: 60 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ static void nft_ctx_init(struct nft_ctx *ctx,
146146
ctx->report = nlmsg_report(nlh);
147147
ctx->flags = nlh->nlmsg_flags;
148148
ctx->seq = nlh->nlmsg_seq;
149+
150+
bitmap_zero(ctx->reg_inited, NFT_REG32_NUM);
149151
}
150152

151153
static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
@@ -393,6 +395,7 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
393395
{
394396
struct nftables_pernet *nft_net = nft_pernet(net);
395397
struct nft_trans_binding *binding;
398+
struct nft_trans_set *trans_set;
396399

397400
list_add_tail(&trans->list, &nft_net->commit_list);
398401

@@ -402,9 +405,13 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
402405

403406
switch (trans->msg_type) {
404407
case NFT_MSG_NEWSET:
408+
trans_set = nft_trans_container_set(trans);
409+
405410
if (!nft_trans_set_update(trans) &&
406411
nft_set_is_anonymous(nft_trans_set(trans)))
407412
list_add_tail(&binding->binding_list, &nft_net->binding_list);
413+
414+
list_add_tail(&trans_set->list_trans_newset, &nft_net->commit_set_list);
408415
break;
409416
case NFT_MSG_NEWCHAIN:
410417
if (!nft_trans_chain_update(trans) &&
@@ -611,6 +618,7 @@ static int __nft_trans_set_add(const struct nft_ctx *ctx, int msg_type,
611618

612619
trans_set = nft_trans_container_set(trans);
613620
INIT_LIST_HEAD(&trans_set->nft_trans_binding.binding_list);
621+
INIT_LIST_HEAD(&trans_set->list_trans_newset);
614622

615623
if (msg_type == NFT_MSG_NEWSET && ctx->nla[NFTA_SET_ID] && !desc) {
616624
nft_trans_set_id(trans) =
@@ -4485,17 +4493,16 @@ static struct nft_set *nft_set_lookup_byid(const struct net *net,
44854493
{
44864494
struct nftables_pernet *nft_net = nft_pernet(net);
44874495
u32 id = ntohl(nla_get_be32(nla));
4488-
struct nft_trans *trans;
4496+
struct nft_trans_set *trans;
44894497

4490-
list_for_each_entry(trans, &nft_net->commit_list, list) {
4491-
if (trans->msg_type == NFT_MSG_NEWSET) {
4492-
struct nft_set *set = nft_trans_set(trans);
4498+
/* its likely the id we need is at the tail, not at start */
4499+
list_for_each_entry_reverse(trans, &nft_net->commit_set_list, list_trans_newset) {
4500+
struct nft_set *set = trans->set;
44934501

4494-
if (id == nft_trans_set_id(trans) &&
4495-
set->table == table &&
4496-
nft_active_genmask(set, genmask))
4497-
return set;
4498-
}
4502+
if (id == trans->set_id &&
4503+
set->table == table &&
4504+
nft_active_genmask(set, genmask))
4505+
return set;
44994506
}
45004507
return ERR_PTR(-ENOENT);
45014508
}
@@ -10447,6 +10454,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1044710454
nft_flow_rule_destroy(nft_trans_flow_rule(trans));
1044810455
break;
1044910456
case NFT_MSG_NEWSET:
10457+
list_del(&nft_trans_container_set(trans)->list_trans_newset);
1045010458
if (nft_trans_set_update(trans)) {
1045110459
struct nft_set *set = nft_trans_set(trans);
1045210460

@@ -10755,6 +10763,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1075510763
nft_trans_destroy(trans);
1075610764
break;
1075710765
case NFT_MSG_NEWSET:
10766+
list_del(&nft_trans_container_set(trans)->list_trans_newset);
1075810767
if (nft_trans_set_update(trans)) {
1075910768
nft_trans_destroy(trans);
1076010769
break;
@@ -10782,7 +10791,10 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1078210791
break;
1078310792
}
1078410793
te = nft_trans_container_elem(trans);
10785-
nft_setelem_remove(net, te->set, te->elem_priv);
10794+
if (!te->set->ops->abort ||
10795+
nft_setelem_is_catchall(te->set, te->elem_priv))
10796+
nft_setelem_remove(net, te->set, te->elem_priv);
10797+
1078610798
if (!nft_setelem_is_catchall(te->set, te->elem_priv))
1078710799
atomic_dec(&te->set->nelems);
1078810800

@@ -10850,6 +10862,8 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
1085010862
}
1085110863
}
1085210864

10865+
WARN_ON_ONCE(!list_empty(&nft_net->commit_set_list));
10866+
1085310867
nft_set_abort_update(&set_update_list);
1085410868

1085510869
synchronize_rcu();
@@ -11026,10 +11040,11 @@ static int nft_validate_register_load(enum nft_registers reg, unsigned int len)
1102611040
return 0;
1102711041
}
1102811042

11029-
int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
11043+
int nft_parse_register_load(const struct nft_ctx *ctx,
11044+
const struct nlattr *attr, u8 *sreg, u32 len)
1103011045
{
11031-
u32 reg;
11032-
int err;
11046+
int err, invalid_reg;
11047+
u32 reg, next_register;
1103311048

1103411049
err = nft_parse_register(attr, &reg);
1103511050
if (err < 0)
@@ -11039,11 +11054,36 @@ int nft_parse_register_load(const struct nlattr *attr, u8 *sreg, u32 len)
1103911054
if (err < 0)
1104011055
return err;
1104111056

11057+
next_register = DIV_ROUND_UP(len, NFT_REG32_SIZE) + reg;
11058+
11059+
/* Can't happen: nft_validate_register_load() should have failed */
11060+
if (WARN_ON_ONCE(next_register > NFT_REG32_NUM))
11061+
return -EINVAL;
11062+
11063+
/* find first register that did not see an earlier store. */
11064+
invalid_reg = find_next_zero_bit(ctx->reg_inited, NFT_REG32_NUM, reg);
11065+
11066+
/* invalid register within the range that we're loading from? */
11067+
if (invalid_reg < next_register)
11068+
return -ENODATA;
11069+
1104211070
*sreg = reg;
1104311071
return 0;
1104411072
}
1104511073
EXPORT_SYMBOL_GPL(nft_parse_register_load);
1104611074

11075+
static void nft_saw_register_store(const struct nft_ctx *__ctx,
11076+
int reg, unsigned int len)
11077+
{
11078+
unsigned int registers = DIV_ROUND_UP(len, NFT_REG32_SIZE);
11079+
struct nft_ctx *ctx = (struct nft_ctx *)__ctx;
11080+
11081+
if (WARN_ON_ONCE(len == 0 || reg < 0))
11082+
return;
11083+
11084+
bitmap_set(ctx->reg_inited, reg, registers);
11085+
}
11086+
1104711087
static int nft_validate_register_store(const struct nft_ctx *ctx,
1104811088
enum nft_registers reg,
1104911089
const struct nft_data *data,
@@ -11065,7 +11105,7 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
1106511105
return err;
1106611106
}
1106711107

11068-
return 0;
11108+
break;
1106911109
default:
1107011110
if (type != NFT_DATA_VALUE)
1107111111
return -EINVAL;
@@ -11078,8 +11118,11 @@ static int nft_validate_register_store(const struct nft_ctx *ctx,
1107811118
sizeof_field(struct nft_regs, data))
1107911119
return -ERANGE;
1108011120

11081-
return 0;
11121+
break;
1108211122
}
11123+
11124+
nft_saw_register_store(ctx, reg, len);
11125+
return 0;
1108311126
}
1108411127

1108511128
int nft_parse_register_store(const struct nft_ctx *ctx,
@@ -11519,6 +11562,7 @@ static int __net_init nf_tables_init_net(struct net *net)
1151911562

1152011563
INIT_LIST_HEAD(&nft_net->tables);
1152111564
INIT_LIST_HEAD(&nft_net->commit_list);
11565+
INIT_LIST_HEAD(&nft_net->commit_set_list);
1152211566
INIT_LIST_HEAD(&nft_net->binding_list);
1152311567
INIT_LIST_HEAD(&nft_net->module_list);
1152411568
INIT_LIST_HEAD(&nft_net->notify_list);
@@ -11549,6 +11593,7 @@ static void __net_exit nf_tables_exit_net(struct net *net)
1154911593
gc_seq = nft_gc_seq_begin(nft_net);
1155011594

1155111595
WARN_ON_ONCE(!list_empty(&nft_net->commit_list));
11596+
WARN_ON_ONCE(!list_empty(&nft_net->commit_set_list));
1155211597

1155311598
if (!list_empty(&nft_net->module_list))
1155411599
nf_tables_module_autoload_cleanup(net);

net/netfilter/nf_tables_core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ nft_do_chain(struct nft_pktinfo *pkt, void *priv)
256256
const struct net *net = nft_net(pkt);
257257
const struct nft_expr *expr, *last;
258258
const struct nft_rule_dp *rule;
259-
struct nft_regs regs = {};
259+
struct nft_regs regs;
260260
unsigned int stackptr = 0;
261261
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
262262
bool genbit = READ_ONCE(net->nft.gencursor);

net/netfilter/nfnetlink.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -402,27 +402,27 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
402402
{
403403
nfnl_unlock(subsys_id);
404404
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
405-
return kfree_skb(skb);
405+
return consume_skb(skb);
406406
}
407407
}
408408

409409
if (!ss->valid_genid || !ss->commit || !ss->abort) {
410410
nfnl_unlock(subsys_id);
411411
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
412-
return kfree_skb(skb);
412+
return consume_skb(skb);
413413
}
414414

415415
if (!try_module_get(ss->owner)) {
416416
nfnl_unlock(subsys_id);
417417
netlink_ack(oskb, nlh, -EOPNOTSUPP, NULL);
418-
return kfree_skb(skb);
418+
return consume_skb(skb);
419419
}
420420

421421
if (!ss->valid_genid(net, genid)) {
422422
module_put(ss->owner);
423423
nfnl_unlock(subsys_id);
424424
netlink_ack(oskb, nlh, -ERESTART, NULL);
425-
return kfree_skb(skb);
425+
return consume_skb(skb);
426426
}
427427

428428
nfnl_unlock(subsys_id);
@@ -567,7 +567,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
567567
if (status & NFNL_BATCH_REPLAY) {
568568
ss->abort(net, oskb, NFNL_ABORT_AUTOLOAD);
569569
nfnl_err_reset(&err_list);
570-
kfree_skb(skb);
570+
consume_skb(skb);
571571
module_put(ss->owner);
572572
goto replay;
573573
} else if (status == NFNL_BATCH_DONE) {
@@ -593,15 +593,15 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh,
593593
err = ss->abort(net, oskb, abort_action);
594594
if (err == -EAGAIN) {
595595
nfnl_err_reset(&err_list);
596-
kfree_skb(skb);
596+
consume_skb(skb);
597597
module_put(ss->owner);
598598
status |= NFNL_BATCH_FAILURE;
599599
goto replay_abort;
600600
}
601601
}
602602

603603
nfnl_err_deliver(&err_list, oskb);
604-
kfree_skb(skb);
604+
consume_skb(skb);
605605
module_put(ss->owner);
606606
}
607607

0 commit comments

Comments
 (0)