@@ -1216,7 +1216,8 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
1216
1216
if (nla_put_string (skb , NFTA_CHAIN_TYPE , basechain -> type -> name ))
1217
1217
goto nla_put_failure ;
1218
1218
1219
- if (basechain -> stats && nft_dump_stats (skb , basechain -> stats ))
1219
+ if (rcu_access_pointer (basechain -> stats ) &&
1220
+ nft_dump_stats (skb , rcu_dereference (basechain -> stats )))
1220
1221
goto nla_put_failure ;
1221
1222
}
1222
1223
@@ -1392,16 +1393,18 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr)
1392
1393
return newstats ;
1393
1394
}
1394
1395
1395
- static void nft_chain_stats_replace (struct nft_base_chain * chain ,
1396
+ static void nft_chain_stats_replace (struct net * net ,
1397
+ struct nft_base_chain * chain ,
1396
1398
struct nft_stats __percpu * newstats )
1397
1399
{
1398
1400
struct nft_stats __percpu * oldstats ;
1399
1401
1400
1402
if (newstats == NULL )
1401
1403
return ;
1402
1404
1403
- if (chain -> stats ) {
1404
- oldstats = nfnl_dereference (chain -> stats , NFNL_SUBSYS_NFTABLES );
1405
+ if (rcu_access_pointer (chain -> stats )) {
1406
+ oldstats = rcu_dereference_protected (chain -> stats ,
1407
+ lockdep_commit_lock_is_held (net ));
1405
1408
rcu_assign_pointer (chain -> stats , newstats );
1406
1409
synchronize_rcu ();
1407
1410
free_percpu (oldstats );
@@ -1439,9 +1442,10 @@ static void nf_tables_chain_destroy(struct nft_ctx *ctx)
1439
1442
struct nft_base_chain * basechain = nft_base_chain (chain );
1440
1443
1441
1444
module_put (basechain -> type -> owner );
1442
- free_percpu (basechain -> stats );
1443
- if (basechain -> stats )
1445
+ if (rcu_access_pointer (basechain -> stats )) {
1444
1446
static_branch_dec (& nft_counters_enabled );
1447
+ free_percpu (rcu_dereference_raw (basechain -> stats ));
1448
+ }
1445
1449
kfree (chain -> name );
1446
1450
kfree (basechain );
1447
1451
} else {
@@ -1590,7 +1594,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
1590
1594
kfree (basechain );
1591
1595
return PTR_ERR (stats );
1592
1596
}
1593
- basechain -> stats = stats ;
1597
+ rcu_assign_pointer ( basechain -> stats , stats ) ;
1594
1598
static_branch_inc (& nft_counters_enabled );
1595
1599
}
1596
1600
@@ -6180,7 +6184,8 @@ static void nft_chain_commit_update(struct nft_trans *trans)
6180
6184
return ;
6181
6185
6182
6186
basechain = nft_base_chain (trans -> ctx .chain );
6183
- nft_chain_stats_replace (basechain , nft_trans_chain_stats (trans ));
6187
+ nft_chain_stats_replace (trans -> ctx .net , basechain ,
6188
+ nft_trans_chain_stats (trans ));
6184
6189
6185
6190
switch (nft_trans_chain_policy (trans )) {
6186
6191
case NF_DROP :
0 commit comments