Skip to content

Commit 4b80ced

Browse files
author
Florian Westphal
committed
netfilter: nf_tables: validate all pending tables
We have to validate all tables in the transaction that are in VALIDATE_DO state, the blamed commit below did not move the break statement to its right location so we only validate one table. Moreover, we can't init table->validate to _SKIP when a table object is allocated. If we do, then if a transcaction creates a new table and then fails the transaction, nfnetlink will loop and nft will hang until user cancels the command. Add back the pernet state as a place to stash the last state encountered. This is either _DO (we hit an error during commit validation) or _SKIP (transaction passed all checks). Fixes: 00c320f ("netfilter: nf_tables: make validation state per table") Reported-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Florian Westphal <[email protected]>
1 parent bfedba3 commit 4b80ced

File tree

2 files changed

+8
-4
lines changed

2 files changed

+8
-4
lines changed

include/net/netfilter/nf_tables.h

+1
Original file line numberDiff line numberDiff line change
@@ -1729,6 +1729,7 @@ struct nftables_pernet {
17291729
u64 table_handle;
17301730
unsigned int base_seq;
17311731
unsigned int gc_seq;
1732+
u8 validate_state;
17321733
};
17331734

17341735
extern unsigned int nf_tables_net_id;

net/netfilter/nf_tables_api.c

+7-4
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
13731373
if (table == NULL)
13741374
goto err_kzalloc;
13751375

1376-
table->validate_state = NFT_VALIDATE_SKIP;
1376+
table->validate_state = nft_net->validate_state;
13771377
table->name = nla_strdup(attr, GFP_KERNEL_ACCOUNT);
13781378
if (table->name == NULL)
13791379
goto err_strdup;
@@ -9051,9 +9051,8 @@ static int nf_tables_validate(struct net *net)
90519051
return -EAGAIN;
90529052

90539053
nft_validate_state_update(table, NFT_VALIDATE_SKIP);
9054+
break;
90549055
}
9055-
9056-
break;
90579056
}
90589057

90599058
return 0;
@@ -9799,8 +9798,10 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
97999798
}
98009799

98019800
/* 0. Validate ruleset, otherwise roll back for error reporting. */
9802-
if (nf_tables_validate(net) < 0)
9801+
if (nf_tables_validate(net) < 0) {
9802+
nft_net->validate_state = NFT_VALIDATE_DO;
98039803
return -EAGAIN;
9804+
}
98049805

98059806
err = nft_flow_rule_offload_commit(net);
98069807
if (err < 0)
@@ -10059,6 +10060,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
1005910060
nf_tables_commit_audit_log(&adl, nft_net->base_seq);
1006010061

1006110062
nft_gc_seq_end(nft_net, gc_seq);
10063+
nft_net->validate_state = NFT_VALIDATE_SKIP;
1006210064
nf_tables_commit_release(net);
1006310065

1006410066
return 0;
@@ -11115,6 +11117,7 @@ static int __net_init nf_tables_init_net(struct net *net)
1111511117
mutex_init(&nft_net->commit_mutex);
1111611118
nft_net->base_seq = 1;
1111711119
nft_net->gc_seq = 0;
11120+
nft_net->validate_state = NFT_VALIDATE_SKIP;
1111811121

1111911122
return 0;
1112011123
}

0 commit comments

Comments
 (0)