mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 13:44:15 +08:00
netfilter: nf_tables: use READ_ONCE and WRITE_ONCE for shared generation id access
The generation ID is bumped from the commit path while holding the
mutex, however, netlink dump operations rely on RCU.
This patch also adds missing cb->base_eq initialization in
nf_tables_dump_set().
Fixes: 38e029f14a
("netfilter: nf_tables: set NLM_F_DUMP_INTR if netlink dumping is stale")
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
f329a0ebea
commit
3400278328
@ -889,7 +889,7 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = nft_net->base_seq;
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (family != NFPROTO_UNSPEC && family != table->family)
|
||||
@ -1705,7 +1705,7 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = nft_net->base_seq;
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (family != NFPROTO_UNSPEC && family != table->family)
|
||||
@ -3149,7 +3149,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = nft_net->base_seq;
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (family != NFPROTO_UNSPEC && family != table->family)
|
||||
@ -4133,7 +4133,7 @@ static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = nft_net->base_seq;
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (ctx->family != NFPROTO_UNSPEC &&
|
||||
@ -5061,6 +5061,8 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (dump_ctx->ctx.family != NFPROTO_UNSPEC &&
|
||||
dump_ctx->ctx.family != table->family)
|
||||
@ -6941,7 +6943,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = nft_net->base_seq;
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (family != NFPROTO_UNSPEC && family != table->family)
|
||||
@ -7873,7 +7875,7 @@ static int nf_tables_dump_flowtable(struct sk_buff *skb,
|
||||
|
||||
rcu_read_lock();
|
||||
nft_net = nft_pernet(net);
|
||||
cb->seq = nft_net->base_seq;
|
||||
cb->seq = READ_ONCE(nft_net->base_seq);
|
||||
|
||||
list_for_each_entry_rcu(table, &nft_net->tables, list) {
|
||||
if (family != NFPROTO_UNSPEC && family != table->family)
|
||||
@ -8806,6 +8808,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||
struct nft_trans_elem *te;
|
||||
struct nft_chain *chain;
|
||||
struct nft_table *table;
|
||||
unsigned int base_seq;
|
||||
LIST_HEAD(adl);
|
||||
int err;
|
||||
|
||||
@ -8855,9 +8858,12 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
|
||||
* Bump generation counter, invalidate any dump in progress.
|
||||
* Cannot fail after this point.
|
||||
*/
|
||||
while (++nft_net->base_seq == 0)
|
||||
base_seq = READ_ONCE(nft_net->base_seq);
|
||||
while (++base_seq == 0)
|
||||
;
|
||||
|
||||
WRITE_ONCE(nft_net->base_seq, base_seq);
|
||||
|
||||
/* step 3. Start new generation, rules_gen_X now in use. */
|
||||
net->nft.gencursor = nft_gencursor_next(net);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user