@@ -35,7 +35,7 @@ int nft_register_afinfo(struct net *net, struct nft_af_info *afi)
35
35
{
36
36
INIT_LIST_HEAD (& afi -> tables );
37
37
nfnl_lock (NFNL_SUBSYS_NFTABLES );
38
- list_add_tail (& afi -> list , & net -> nft .af_info );
38
+ list_add_tail_rcu (& afi -> list , & net -> nft .af_info );
39
39
nfnl_unlock (NFNL_SUBSYS_NFTABLES );
40
40
return 0 ;
41
41
}
@@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(nft_register_afinfo);
51
51
void nft_unregister_afinfo (struct nft_af_info * afi )
52
52
{
53
53
nfnl_lock (NFNL_SUBSYS_NFTABLES );
54
- list_del (& afi -> list );
54
+ list_del_rcu (& afi -> list );
55
55
nfnl_unlock (NFNL_SUBSYS_NFTABLES );
56
56
}
57
57
EXPORT_SYMBOL_GPL (nft_unregister_afinfo );
@@ -277,11 +277,12 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
277
277
struct net * net = sock_net (skb -> sk );
278
278
int family = nfmsg -> nfgen_family ;
279
279
280
- list_for_each_entry (afi , & net -> nft .af_info , list ) {
280
+ rcu_read_lock ();
281
+ list_for_each_entry_rcu (afi , & net -> nft .af_info , list ) {
281
282
if (family != NFPROTO_UNSPEC && family != afi -> family )
282
283
continue ;
283
284
284
- list_for_each_entry (table , & afi -> tables , list ) {
285
+ list_for_each_entry_rcu (table , & afi -> tables , list ) {
285
286
if (idx < s_idx )
286
287
goto cont ;
287
288
if (idx > s_idx )
@@ -299,6 +300,7 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
299
300
}
300
301
}
301
302
done :
303
+ rcu_read_unlock ();
302
304
cb -> args [0 ] = idx ;
303
305
return skb -> len ;
304
306
}
@@ -517,7 +519,7 @@ static int nf_tables_newtable(struct sock *nlsk, struct sk_buff *skb,
517
519
module_put (afi -> owner );
518
520
return err ;
519
521
}
520
- list_add_tail (& table -> list , & afi -> tables );
522
+ list_add_tail_rcu (& table -> list , & afi -> tables );
521
523
return 0 ;
522
524
}
523
525
@@ -549,7 +551,7 @@ static int nf_tables_deltable(struct sock *nlsk, struct sk_buff *skb,
549
551
if (err < 0 )
550
552
return err ;
551
553
552
- list_del (& table -> list );
554
+ list_del_rcu (& table -> list );
553
555
return 0 ;
554
556
}
555
557
@@ -764,12 +766,13 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
764
766
struct net * net = sock_net (skb -> sk );
765
767
int family = nfmsg -> nfgen_family ;
766
768
767
- list_for_each_entry (afi , & net -> nft .af_info , list ) {
769
+ rcu_read_lock ();
770
+ list_for_each_entry_rcu (afi , & net -> nft .af_info , list ) {
768
771
if (family != NFPROTO_UNSPEC && family != afi -> family )
769
772
continue ;
770
773
771
- list_for_each_entry (table , & afi -> tables , list ) {
772
- list_for_each_entry (chain , & table -> chains , list ) {
774
+ list_for_each_entry_rcu (table , & afi -> tables , list ) {
775
+ list_for_each_entry_rcu (chain , & table -> chains , list ) {
773
776
if (idx < s_idx )
774
777
goto cont ;
775
778
if (idx > s_idx )
@@ -787,11 +790,11 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
787
790
}
788
791
}
789
792
done :
793
+ rcu_read_unlock ();
790
794
cb -> args [0 ] = idx ;
791
795
return skb -> len ;
792
796
}
793
797
794
-
795
798
static int nf_tables_getchain (struct sock * nlsk , struct sk_buff * skb ,
796
799
const struct nlmsghdr * nlh ,
797
800
const struct nlattr * const nla [])
@@ -1133,7 +1136,7 @@ static int nf_tables_newchain(struct sock *nlsk, struct sk_buff *skb,
1133
1136
goto err2 ;
1134
1137
1135
1138
table -> use ++ ;
1136
- list_add_tail (& chain -> list , & table -> chains );
1139
+ list_add_tail_rcu (& chain -> list , & table -> chains );
1137
1140
return 0 ;
1138
1141
err2 :
1139
1142
if (!(table -> flags & NFT_TABLE_F_DORMANT ) &&
@@ -1183,7 +1186,7 @@ static int nf_tables_delchain(struct sock *nlsk, struct sk_buff *skb,
1183
1186
return err ;
1184
1187
1185
1188
table -> use -- ;
1186
- list_del (& chain -> list );
1189
+ list_del_rcu (& chain -> list );
1187
1190
return 0 ;
1188
1191
}
1189
1192
@@ -1202,9 +1205,9 @@ int nft_register_expr(struct nft_expr_type *type)
1202
1205
{
1203
1206
nfnl_lock (NFNL_SUBSYS_NFTABLES );
1204
1207
if (type -> family == NFPROTO_UNSPEC )
1205
- list_add_tail (& type -> list , & nf_tables_expressions );
1208
+ list_add_tail_rcu (& type -> list , & nf_tables_expressions );
1206
1209
else
1207
- list_add (& type -> list , & nf_tables_expressions );
1210
+ list_add_rcu (& type -> list , & nf_tables_expressions );
1208
1211
nfnl_unlock (NFNL_SUBSYS_NFTABLES );
1209
1212
return 0 ;
1210
1213
}
@@ -1219,7 +1222,7 @@ EXPORT_SYMBOL_GPL(nft_register_expr);
1219
1222
void nft_unregister_expr (struct nft_expr_type * type )
1220
1223
{
1221
1224
nfnl_lock (NFNL_SUBSYS_NFTABLES );
1222
- list_del (& type -> list );
1225
+ list_del_rcu (& type -> list );
1223
1226
nfnl_unlock (NFNL_SUBSYS_NFTABLES );
1224
1227
}
1225
1228
EXPORT_SYMBOL_GPL (nft_unregister_expr );
@@ -1555,13 +1558,14 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
1555
1558
u8 genctr = ACCESS_ONCE (net -> nft .genctr );
1556
1559
u8 gencursor = ACCESS_ONCE (net -> nft .gencursor );
1557
1560
1558
- list_for_each_entry (afi , & net -> nft .af_info , list ) {
1561
+ rcu_read_lock ();
1562
+ list_for_each_entry_rcu (afi , & net -> nft .af_info , list ) {
1559
1563
if (family != NFPROTO_UNSPEC && family != afi -> family )
1560
1564
continue ;
1561
1565
1562
- list_for_each_entry (table , & afi -> tables , list ) {
1563
- list_for_each_entry (chain , & table -> chains , list ) {
1564
- list_for_each_entry (rule , & chain -> rules , list ) {
1566
+ list_for_each_entry_rcu (table , & afi -> tables , list ) {
1567
+ list_for_each_entry_rcu (chain , & table -> chains , list ) {
1568
+ list_for_each_entry_rcu (rule , & chain -> rules , list ) {
1565
1569
if (!nft_rule_is_active (net , rule ))
1566
1570
goto cont ;
1567
1571
if (idx < s_idx )
@@ -1582,6 +1586,8 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
1582
1586
}
1583
1587
}
1584
1588
done :
1589
+ rcu_read_unlock ();
1590
+
1585
1591
/* Invalidate this dump, a transition to the new generation happened */
1586
1592
if (gencursor != net -> nft .gencursor || genctr != net -> nft .genctr )
1587
1593
return - EBUSY ;
@@ -1935,7 +1941,7 @@ static LIST_HEAD(nf_tables_set_ops);
1935
1941
int nft_register_set (struct nft_set_ops * ops )
1936
1942
{
1937
1943
nfnl_lock (NFNL_SUBSYS_NFTABLES );
1938
- list_add_tail (& ops -> list , & nf_tables_set_ops );
1944
+ list_add_tail_rcu (& ops -> list , & nf_tables_set_ops );
1939
1945
nfnl_unlock (NFNL_SUBSYS_NFTABLES );
1940
1946
return 0 ;
1941
1947
}
@@ -1944,7 +1950,7 @@ EXPORT_SYMBOL_GPL(nft_register_set);
1944
1950
void nft_unregister_set (struct nft_set_ops * ops )
1945
1951
{
1946
1952
nfnl_lock (NFNL_SUBSYS_NFTABLES );
1947
- list_del (& ops -> list );
1953
+ list_del_rcu (& ops -> list );
1948
1954
nfnl_unlock (NFNL_SUBSYS_NFTABLES );
1949
1955
}
1950
1956
EXPORT_SYMBOL_GPL (nft_unregister_set );
@@ -2237,7 +2243,8 @@ static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb,
2237
2243
if (cb -> args [1 ])
2238
2244
return skb -> len ;
2239
2245
2240
- list_for_each_entry (set , & ctx -> table -> sets , list ) {
2246
+ rcu_read_lock ();
2247
+ list_for_each_entry_rcu (set , & ctx -> table -> sets , list ) {
2241
2248
if (idx < s_idx )
2242
2249
goto cont ;
2243
2250
if (nf_tables_fill_set (skb , ctx , set , NFT_MSG_NEWSET ,
@@ -2250,6 +2257,7 @@ static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb,
2250
2257
}
2251
2258
cb -> args [1 ] = 1 ;
2252
2259
done :
2260
+ rcu_read_unlock ();
2253
2261
return skb -> len ;
2254
2262
}
2255
2263
@@ -2263,7 +2271,8 @@ static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2263
2271
if (cb -> args [1 ])
2264
2272
return skb -> len ;
2265
2273
2266
- list_for_each_entry (table , & ctx -> afi -> tables , list ) {
2274
+ rcu_read_lock ();
2275
+ list_for_each_entry_rcu (table , & ctx -> afi -> tables , list ) {
2267
2276
if (cur_table ) {
2268
2277
if (cur_table != table )
2269
2278
continue ;
@@ -2272,7 +2281,7 @@ static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2272
2281
}
2273
2282
ctx -> table = table ;
2274
2283
idx = 0 ;
2275
- list_for_each_entry (set , & ctx -> table -> sets , list ) {
2284
+ list_for_each_entry_rcu (set , & ctx -> table -> sets , list ) {
2276
2285
if (idx < s_idx )
2277
2286
goto cont ;
2278
2287
if (nf_tables_fill_set (skb , ctx , set , NFT_MSG_NEWSET ,
@@ -2287,6 +2296,7 @@ static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb,
2287
2296
}
2288
2297
cb -> args [1 ] = 1 ;
2289
2298
done :
2299
+ rcu_read_unlock ();
2290
2300
return skb -> len ;
2291
2301
}
2292
2302
@@ -2303,15 +2313,16 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2303
2313
if (cb -> args [1 ])
2304
2314
return skb -> len ;
2305
2315
2306
- list_for_each_entry (afi , & net -> nft .af_info , list ) {
2316
+ rcu_read_lock ();
2317
+ list_for_each_entry_rcu (afi , & net -> nft .af_info , list ) {
2307
2318
if (cur_family ) {
2308
2319
if (afi -> family != cur_family )
2309
2320
continue ;
2310
2321
2311
2322
cur_family = 0 ;
2312
2323
}
2313
2324
2314
- list_for_each_entry (table , & afi -> tables , list ) {
2325
+ list_for_each_entry_rcu (table , & afi -> tables , list ) {
2315
2326
if (cur_table ) {
2316
2327
if (cur_table != table )
2317
2328
continue ;
@@ -2322,7 +2333,7 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2322
2333
ctx -> table = table ;
2323
2334
ctx -> afi = afi ;
2324
2335
idx = 0 ;
2325
- list_for_each_entry (set , & ctx -> table -> sets , list ) {
2336
+ list_for_each_entry_rcu (set , & ctx -> table -> sets , list ) {
2326
2337
if (idx < s_idx )
2327
2338
goto cont ;
2328
2339
if (nf_tables_fill_set (skb , ctx , set ,
@@ -2342,6 +2353,7 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb,
2342
2353
}
2343
2354
cb -> args [1 ] = 1 ;
2344
2355
done :
2356
+ rcu_read_unlock ();
2345
2357
return skb -> len ;
2346
2358
}
2347
2359
@@ -2600,7 +2612,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2600
2612
if (err < 0 )
2601
2613
goto err2 ;
2602
2614
2603
- list_add_tail (& set -> list , & table -> sets );
2615
+ list_add_tail_rcu (& set -> list , & table -> sets );
2604
2616
table -> use ++ ;
2605
2617
return 0 ;
2606
2618
@@ -2620,7 +2632,7 @@ static void nft_set_destroy(struct nft_set *set)
2620
2632
2621
2633
static void nf_tables_set_destroy (const struct nft_ctx * ctx , struct nft_set * set )
2622
2634
{
2623
- list_del (& set -> list );
2635
+ list_del_rcu (& set -> list );
2624
2636
nf_tables_set_notify (ctx , set , NFT_MSG_DELSET , GFP_ATOMIC );
2625
2637
nft_set_destroy (set );
2626
2638
}
@@ -2655,7 +2667,7 @@ static int nf_tables_delset(struct sock *nlsk, struct sk_buff *skb,
2655
2667
if (err < 0 )
2656
2668
return err ;
2657
2669
2658
- list_del (& set -> list );
2670
+ list_del_rcu (& set -> list );
2659
2671
ctx .table -> use -- ;
2660
2672
return 0 ;
2661
2673
}
@@ -2707,14 +2719,14 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
2707
2719
}
2708
2720
bind :
2709
2721
binding -> chain = ctx -> chain ;
2710
- list_add_tail (& binding -> list , & set -> bindings );
2722
+ list_add_tail_rcu (& binding -> list , & set -> bindings );
2711
2723
return 0 ;
2712
2724
}
2713
2725
2714
2726
void nf_tables_unbind_set (const struct nft_ctx * ctx , struct nft_set * set ,
2715
2727
struct nft_set_binding * binding )
2716
2728
{
2717
- list_del (& binding -> list );
2729
+ list_del_rcu (& binding -> list );
2718
2730
2719
2731
if (list_empty (& set -> bindings ) && set -> flags & NFT_SET_ANONYMOUS &&
2720
2732
!(set -> flags & NFT_SET_INACTIVE ))
@@ -3494,12 +3506,12 @@ static int nf_tables_abort(struct sk_buff *skb)
3494
3506
}
3495
3507
nft_trans_destroy (trans );
3496
3508
} else {
3497
- list_del (& trans -> ctx .table -> list );
3509
+ list_del_rcu (& trans -> ctx .table -> list );
3498
3510
}
3499
3511
break ;
3500
3512
case NFT_MSG_DELTABLE :
3501
- list_add_tail (& trans -> ctx .table -> list ,
3502
- & trans -> ctx .afi -> tables );
3513
+ list_add_tail_rcu (& trans -> ctx .table -> list ,
3514
+ & trans -> ctx .afi -> tables );
3503
3515
nft_trans_destroy (trans );
3504
3516
break ;
3505
3517
case NFT_MSG_NEWCHAIN :
@@ -3510,7 +3522,7 @@ static int nf_tables_abort(struct sk_buff *skb)
3510
3522
nft_trans_destroy (trans );
3511
3523
} else {
3512
3524
trans -> ctx .table -> use -- ;
3513
- list_del (& trans -> ctx .chain -> list );
3525
+ list_del_rcu (& trans -> ctx .chain -> list );
3514
3526
if (!(trans -> ctx .table -> flags & NFT_TABLE_F_DORMANT ) &&
3515
3527
trans -> ctx .chain -> flags & NFT_BASE_CHAIN ) {
3516
3528
nf_unregister_hooks (nft_base_chain (trans -> ctx .chain )-> ops ,
@@ -3520,8 +3532,8 @@ static int nf_tables_abort(struct sk_buff *skb)
3520
3532
break ;
3521
3533
case NFT_MSG_DELCHAIN :
3522
3534
trans -> ctx .table -> use ++ ;
3523
- list_add_tail (& trans -> ctx .chain -> list ,
3524
- & trans -> ctx .table -> chains );
3535
+ list_add_tail_rcu (& trans -> ctx .chain -> list ,
3536
+ & trans -> ctx .table -> chains );
3525
3537
nft_trans_destroy (trans );
3526
3538
break ;
3527
3539
case NFT_MSG_NEWRULE :
@@ -3535,12 +3547,12 @@ static int nf_tables_abort(struct sk_buff *skb)
3535
3547
break ;
3536
3548
case NFT_MSG_NEWSET :
3537
3549
trans -> ctx .table -> use -- ;
3538
- list_del (& nft_trans_set (trans )-> list );
3550
+ list_del_rcu (& nft_trans_set (trans )-> list );
3539
3551
break ;
3540
3552
case NFT_MSG_DELSET :
3541
3553
trans -> ctx .table -> use ++ ;
3542
- list_add_tail (& nft_trans_set (trans )-> list ,
3543
- & trans -> ctx .table -> sets );
3554
+ list_add_tail_rcu (& nft_trans_set (trans )-> list ,
3555
+ & trans -> ctx .table -> sets );
3544
3556
nft_trans_destroy (trans );
3545
3557
break ;
3546
3558
case NFT_MSG_NEWSETELEM :
0 commit comments