Skip to content

Commit 5a63039

Browse files
committed
netfilter: nf_tables: reject unbound anonymous set before commit phase
JIRA: https://issues.redhat.com/browse/RHEL-1720 JIRA: https://issues.redhat.com/browse/RHEL-1721 Upstream Status: commit 938154b commit 938154b Author: Pablo Neira Ayuso <pablo@netfilter.org> Date: Fri Jun 16 15:21:33 2023 +0200 netfilter: nf_tables: reject unbound anonymous set before commit phase Add a new list to track set transaction and to check for unbound anonymous sets before entering the commit phase. Bail out at the end of the transaction handling if an anonymous set remains unbound. Fixes: 9651851 ("netfilter: add nftables") Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Florian Westphal <fwestpha@redhat.com>
1 parent 46d60b5 commit 5a63039

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

include/net/netfilter/nf_tables.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1511,13 +1511,15 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
15111511
* struct nft_trans - nf_tables object update in transaction
15121512
*
15131513
* @list: used internally
1514+
* @binding_list: list of objects with possible bindings
15141515
* @msg_type: message type
15151516
* @put_net: ctx->net needs to be put
15161517
* @ctx: transaction context
15171518
* @data: internal information related to the transaction
15181519
*/
15191520
struct nft_trans {
15201521
struct list_head list;
1522+
struct list_head binding_list;
15211523
int msg_type;
15221524
bool put_net;
15231525
struct nft_ctx ctx;
@@ -1656,6 +1658,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
16561658
struct nftables_pernet {
16571659
struct list_head tables;
16581660
struct list_head commit_list;
1661+
struct list_head binding_list;
16591662
struct list_head module_list;
16601663
struct list_head notify_list;
16611664
struct mutex commit_mutex;

net/netfilter/nf_tables_api.c

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ static struct nft_trans *nft_trans_alloc_gfp(const struct nft_ctx *ctx,
153153
return NULL;
154154

155155
INIT_LIST_HEAD(&trans->list);
156+
INIT_LIST_HEAD(&trans->binding_list);
156157
trans->msg_type = msg_type;
157158
trans->ctx = *ctx;
158159

@@ -165,9 +166,15 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
165166
return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
166167
}
167168

168-
static void nft_trans_destroy(struct nft_trans *trans)
169+
static void nft_trans_list_del(struct nft_trans *trans)
169170
{
170171
list_del(&trans->list);
172+
list_del(&trans->binding_list);
173+
}
174+
175+
static void nft_trans_destroy(struct nft_trans *trans)
176+
{
177+
nft_trans_list_del(trans);
171178
kfree(trans);
172179
}
173180

@@ -359,6 +366,14 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
359366
{
360367
struct nftables_pernet *nft_net = nft_pernet(net);
361368

369+
switch (trans->msg_type) {
370+
case NFT_MSG_NEWSET:
371+
if (!nft_trans_set_update(trans) &&
372+
nft_set_is_anonymous(nft_trans_set(trans)))
373+
list_add_tail(&trans->binding_list, &nft_net->binding_list);
374+
break;
375+
}
376+
362377
list_add_tail(&trans->list, &nft_net->commit_list);
363378
}
364379

@@ -8863,7 +8878,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
88638878
synchronize_rcu();
88648879

88658880
list_for_each_entry_safe(trans, next, &head, list) {
8866-
list_del(&trans->list);
8881+
nft_trans_list_del(trans);
88678882
nft_commit_release(trans);
88688883
}
88698884
}
@@ -9181,6 +9196,19 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
91819196
return 0;
91829197
}
91839198

9199+
list_for_each_entry(trans, &nft_net->binding_list, binding_list) {
9200+
switch (trans->msg_type) {
9201+
case NFT_MSG_NEWSET:
9202+
if (!nft_trans_set_update(trans) &&
9203+
nft_set_is_anonymous(nft_trans_set(trans)) &&
9204+
!nft_trans_set_bound(trans)) {
9205+
pr_warn_once("nftables ruleset with unbound set\n");
9206+
return -EINVAL;
9207+
}
9208+
break;
9209+
}
9210+
}
9211+
91849212
/* 0. Validate ruleset, otherwise roll back for error reporting. */
91859213
if (nf_tables_validate(net) < 0)
91869214
return -EAGAIN;
@@ -9671,7 +9699,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
96719699

96729700
list_for_each_entry_safe_reverse(trans, next,
96739701
&nft_net->commit_list, list) {
9674-
list_del(&trans->list);
9702+
nft_trans_list_del(trans);
96759703
nf_tables_abort_release(trans);
96769704
}
96779705

@@ -10448,6 +10476,7 @@ static int __net_init nf_tables_init_net(struct net *net)
1044810476

1044910477
INIT_LIST_HEAD(&nft_net->tables);
1045010478
INIT_LIST_HEAD(&nft_net->commit_list);
10479+
INIT_LIST_HEAD(&nft_net->binding_list);
1045110480
INIT_LIST_HEAD(&nft_net->module_list);
1045210481
INIT_LIST_HEAD(&nft_net->notify_list);
1045310482
mutex_init(&nft_net->commit_mutex);

0 commit comments

Comments
 (0)