Skip to content

Commit 938154b

Browse files
committed
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 <[email protected]>
1 parent c88c535 commit 938154b

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
@@ -1573,13 +1573,15 @@ static inline void nft_set_elem_clear_busy(struct nft_set_ext *ext)
15731573
* struct nft_trans - nf_tables object update in transaction
15741574
*
15751575
* @list: used internally
1576+
* @binding_list: list of objects with possible bindings
15761577
* @msg_type: message type
15771578
* @put_net: ctx->net needs to be put
15781579
* @ctx: transaction context
15791580
* @data: internal information related to the transaction
15801581
*/
15811582
struct nft_trans {
15821583
struct list_head list;
1584+
struct list_head binding_list;
15831585
int msg_type;
15841586
bool put_net;
15851587
struct nft_ctx ctx;
@@ -1724,6 +1726,7 @@ static inline int nft_request_module(struct net *net, const char *fmt, ...) { re
17241726
struct nftables_pernet {
17251727
struct list_head tables;
17261728
struct list_head commit_list;
1729+
struct list_head binding_list;
17271730
struct list_head module_list;
17281731
struct list_head notify_list;
17291732
struct mutex commit_mutex;

net/netfilter/nf_tables_api.c

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

153153
INIT_LIST_HEAD(&trans->list);
154+
INIT_LIST_HEAD(&trans->binding_list);
154155
trans->msg_type = msg_type;
155156
trans->ctx = *ctx;
156157

@@ -163,9 +164,15 @@ static struct nft_trans *nft_trans_alloc(const struct nft_ctx *ctx,
163164
return nft_trans_alloc_gfp(ctx, msg_type, size, GFP_KERNEL);
164165
}
165166

166-
static void nft_trans_destroy(struct nft_trans *trans)
167+
static void nft_trans_list_del(struct nft_trans *trans)
167168
{
168169
list_del(&trans->list);
170+
list_del(&trans->binding_list);
171+
}
172+
173+
static void nft_trans_destroy(struct nft_trans *trans)
174+
{
175+
nft_trans_list_del(trans);
169176
kfree(trans);
170177
}
171178

@@ -357,6 +364,14 @@ static void nft_trans_commit_list_add_tail(struct net *net, struct nft_trans *tr
357364
{
358365
struct nftables_pernet *nft_net = nft_pernet(net);
359366

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

@@ -9111,7 +9126,7 @@ static void nf_tables_trans_destroy_work(struct work_struct *w)
91119126
synchronize_rcu();
91129127

91139128
list_for_each_entry_safe(trans, next, &head, list) {
9114-
list_del(&trans->list);
9129+
nft_trans_list_del(trans);
91159130
nft_commit_release(trans);
91169131
}
91179132
}
@@ -9476,6 +9491,19 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
94769491
return 0;
94779492
}
94789493

9494+
list_for_each_entry(trans, &nft_net->binding_list, binding_list) {
9495+
switch (trans->msg_type) {
9496+
case NFT_MSG_NEWSET:
9497+
if (!nft_trans_set_update(trans) &&
9498+
nft_set_is_anonymous(nft_trans_set(trans)) &&
9499+
!nft_trans_set_bound(trans)) {
9500+
pr_warn_once("nftables ruleset with unbound set\n");
9501+
return -EINVAL;
9502+
}
9503+
break;
9504+
}
9505+
}
9506+
94799507
/* 0. Validate ruleset, otherwise roll back for error reporting. */
94809508
if (nf_tables_validate(net) < 0)
94819509
return -EAGAIN;
@@ -9989,7 +10017,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
998910017

999010018
list_for_each_entry_safe_reverse(trans, next,
999110019
&nft_net->commit_list, list) {
9992-
list_del(&trans->list);
10020+
nft_trans_list_del(trans);
999310021
nf_tables_abort_release(trans);
999410022
}
999510023

@@ -10765,6 +10793,7 @@ static int __net_init nf_tables_init_net(struct net *net)
1076510793

1076610794
INIT_LIST_HEAD(&nft_net->tables);
1076710795
INIT_LIST_HEAD(&nft_net->commit_list);
10796+
INIT_LIST_HEAD(&nft_net->binding_list);
1076810797
INIT_LIST_HEAD(&nft_net->module_list);
1076910798
INIT_LIST_HEAD(&nft_net->notify_list);
1077010799
mutex_init(&nft_net->commit_mutex);

0 commit comments

Comments
 (0)