@@ -480,12 +480,19 @@ static void nft_request_module(struct net *net, const char *fmt, ...)
480
480
if (WARN (ret >= MODULE_NAME_LEN , "truncated: '%s' (len %d)" , module_name , ret ))
481
481
return ;
482
482
483
- nfnl_unlock ( NFNL_SUBSYS_NFTABLES );
483
+ mutex_unlock ( & net -> nft . commit_mutex );
484
484
request_module ("%s" , module_name );
485
- nfnl_lock ( NFNL_SUBSYS_NFTABLES );
485
+ mutex_lock ( & net -> nft . commit_mutex );
486
486
}
487
487
#endif
488
488
489
+ static void lockdep_nfnl_nft_mutex_not_held (void )
490
+ {
491
+ #ifdef CONFIG_PROVE_LOCKING
492
+ WARN_ON_ONCE (lockdep_nfnl_is_held (NFNL_SUBSYS_NFTABLES ));
493
+ #endif
494
+ }
495
+
489
496
static const struct nft_chain_type *
490
497
nf_tables_chain_type_lookup (struct net * net , const struct nlattr * nla ,
491
498
u8 family , bool autoload )
@@ -495,6 +502,8 @@ nf_tables_chain_type_lookup(struct net *net, const struct nlattr *nla,
495
502
type = __nf_tables_chain_type_lookup (nla , family );
496
503
if (type != NULL )
497
504
return type ;
505
+
506
+ lockdep_nfnl_nft_mutex_not_held ();
498
507
#ifdef CONFIG_MODULES
499
508
if (autoload ) {
500
509
nft_request_module (net , "nft-chain-%u-%.*s" , family ,
@@ -802,6 +811,7 @@ static int nf_tables_newtable(struct net *net, struct sock *nlsk,
802
811
struct nft_ctx ctx ;
803
812
int err ;
804
813
814
+ lockdep_assert_held (& net -> nft .commit_mutex );
805
815
attr = nla [NFTA_TABLE_NAME ];
806
816
table = nft_table_lookup (net , attr , family , genmask );
807
817
if (IS_ERR (table )) {
@@ -1042,7 +1052,17 @@ nft_chain_lookup_byhandle(const struct nft_table *table, u64 handle, u8 genmask)
1042
1052
return ERR_PTR (- ENOENT );
1043
1053
}
1044
1054
1045
- static struct nft_chain * nft_chain_lookup (struct nft_table * table ,
1055
+ static bool lockdep_commit_lock_is_held (struct net * net )
1056
+ {
1057
+ #ifdef CONFIG_PROVE_LOCKING
1058
+ return lockdep_is_held (& net -> nft .commit_mutex );
1059
+ #else
1060
+ return true;
1061
+ #endif
1062
+ }
1063
+
1064
+ static struct nft_chain * nft_chain_lookup (struct net * net ,
1065
+ struct nft_table * table ,
1046
1066
const struct nlattr * nla , u8 genmask )
1047
1067
{
1048
1068
char search [NFT_CHAIN_MAXNAMELEN + 1 ];
@@ -1055,7 +1075,7 @@ static struct nft_chain *nft_chain_lookup(struct nft_table *table,
1055
1075
nla_strlcpy (search , nla , sizeof (search ));
1056
1076
1057
1077
WARN_ON (!rcu_read_lock_held () &&
1058
- !lockdep_nfnl_is_held ( NFNL_SUBSYS_NFTABLES ));
1078
+ !lockdep_commit_lock_is_held ( net ));
1059
1079
1060
1080
chain = ERR_PTR (- ENOENT );
1061
1081
rcu_read_lock ();
@@ -1295,7 +1315,7 @@ static int nf_tables_getchain(struct net *net, struct sock *nlsk,
1295
1315
return PTR_ERR (table );
1296
1316
}
1297
1317
1298
- chain = nft_chain_lookup (table , nla [NFTA_CHAIN_NAME ], genmask );
1318
+ chain = nft_chain_lookup (net , table , nla [NFTA_CHAIN_NAME ], genmask );
1299
1319
if (IS_ERR (chain )) {
1300
1320
NL_SET_BAD_ATTR (extack , nla [NFTA_CHAIN_NAME ]);
1301
1321
return PTR_ERR (chain );
@@ -1428,6 +1448,9 @@ static int nft_chain_parse_hook(struct net *net,
1428
1448
struct net_device * dev ;
1429
1449
int err ;
1430
1450
1451
+ lockdep_assert_held (& net -> nft .commit_mutex );
1452
+ lockdep_nfnl_nft_mutex_not_held ();
1453
+
1431
1454
err = nla_parse_nested (ha , NFTA_HOOK_MAX , nla [NFTA_CHAIN_HOOK ],
1432
1455
nft_hook_policy , NULL );
1433
1456
if (err < 0 )
@@ -1662,7 +1685,8 @@ static int nf_tables_updchain(struct nft_ctx *ctx, u8 genmask, u8 policy,
1662
1685
nla [NFTA_CHAIN_NAME ]) {
1663
1686
struct nft_chain * chain2 ;
1664
1687
1665
- chain2 = nft_chain_lookup (table , nla [NFTA_CHAIN_NAME ], genmask );
1688
+ chain2 = nft_chain_lookup (ctx -> net , table ,
1689
+ nla [NFTA_CHAIN_NAME ], genmask );
1666
1690
if (!IS_ERR (chain2 ))
1667
1691
return - EEXIST ;
1668
1692
}
@@ -1724,6 +1748,8 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1724
1748
1725
1749
create = nlh -> nlmsg_flags & NLM_F_CREATE ? true : false;
1726
1750
1751
+ lockdep_assert_held (& net -> nft .commit_mutex );
1752
+
1727
1753
table = nft_table_lookup (net , nla [NFTA_CHAIN_TABLE ], family , genmask );
1728
1754
if (IS_ERR (table )) {
1729
1755
NL_SET_BAD_ATTR (extack , nla [NFTA_CHAIN_TABLE ]);
@@ -1742,7 +1768,7 @@ static int nf_tables_newchain(struct net *net, struct sock *nlsk,
1742
1768
}
1743
1769
attr = nla [NFTA_CHAIN_HANDLE ];
1744
1770
} else {
1745
- chain = nft_chain_lookup (table , attr , genmask );
1771
+ chain = nft_chain_lookup (net , table , attr , genmask );
1746
1772
if (IS_ERR (chain )) {
1747
1773
if (PTR_ERR (chain ) != - ENOENT ) {
1748
1774
NL_SET_BAD_ATTR (extack , attr );
@@ -1820,7 +1846,7 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
1820
1846
chain = nft_chain_lookup_byhandle (table , handle , genmask );
1821
1847
} else {
1822
1848
attr = nla [NFTA_CHAIN_NAME ];
1823
- chain = nft_chain_lookup (table , attr , genmask );
1849
+ chain = nft_chain_lookup (net , table , attr , genmask );
1824
1850
}
1825
1851
if (IS_ERR (chain )) {
1826
1852
NL_SET_BAD_ATTR (extack , attr );
@@ -1918,6 +1944,7 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net,
1918
1944
if (type != NULL && try_module_get (type -> owner ))
1919
1945
return type ;
1920
1946
1947
+ lockdep_nfnl_nft_mutex_not_held ();
1921
1948
#ifdef CONFIG_MODULES
1922
1949
if (type == NULL ) {
1923
1950
nft_request_module (net , "nft-expr-%u-%.*s" , family ,
@@ -2352,7 +2379,7 @@ static int nf_tables_getrule(struct net *net, struct sock *nlsk,
2352
2379
return PTR_ERR (table );
2353
2380
}
2354
2381
2355
- chain = nft_chain_lookup (table , nla [NFTA_RULE_CHAIN ], genmask );
2382
+ chain = nft_chain_lookup (net , table , nla [NFTA_RULE_CHAIN ], genmask );
2356
2383
if (IS_ERR (chain )) {
2357
2384
NL_SET_BAD_ATTR (extack , nla [NFTA_RULE_CHAIN ]);
2358
2385
return PTR_ERR (chain );
@@ -2386,6 +2413,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
2386
2413
{
2387
2414
struct nft_expr * expr ;
2388
2415
2416
+ lockdep_assert_held (& ctx -> net -> nft .commit_mutex );
2389
2417
/*
2390
2418
* Careful: some expressions might not be initialized in case this
2391
2419
* is called on error from nf_tables_newrule().
@@ -2476,6 +2504,8 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2476
2504
bool create ;
2477
2505
u64 handle , pos_handle ;
2478
2506
2507
+ lockdep_assert_held (& net -> nft .commit_mutex );
2508
+
2479
2509
create = nlh -> nlmsg_flags & NLM_F_CREATE ? true : false;
2480
2510
2481
2511
table = nft_table_lookup (net , nla [NFTA_RULE_TABLE ], family , genmask );
@@ -2484,7 +2514,7 @@ static int nf_tables_newrule(struct net *net, struct sock *nlsk,
2484
2514
return PTR_ERR (table );
2485
2515
}
2486
2516
2487
- chain = nft_chain_lookup (table , nla [NFTA_RULE_CHAIN ], genmask );
2517
+ chain = nft_chain_lookup (net , table , nla [NFTA_RULE_CHAIN ], genmask );
2488
2518
if (IS_ERR (chain )) {
2489
2519
NL_SET_BAD_ATTR (extack , nla [NFTA_RULE_CHAIN ]);
2490
2520
return PTR_ERR (chain );
@@ -2684,7 +2714,8 @@ static int nf_tables_delrule(struct net *net, struct sock *nlsk,
2684
2714
}
2685
2715
2686
2716
if (nla [NFTA_RULE_CHAIN ]) {
2687
- chain = nft_chain_lookup (table , nla [NFTA_RULE_CHAIN ], genmask );
2717
+ chain = nft_chain_lookup (net , table , nla [NFTA_RULE_CHAIN ],
2718
+ genmask );
2688
2719
if (IS_ERR (chain )) {
2689
2720
NL_SET_BAD_ATTR (extack , nla [NFTA_RULE_CHAIN ]);
2690
2721
return PTR_ERR (chain );
@@ -2776,6 +2807,8 @@ nft_select_set_ops(const struct nft_ctx *ctx,
2776
2807
const struct nft_set_type * type ;
2777
2808
u32 flags = 0 ;
2778
2809
2810
+ lockdep_assert_held (& ctx -> net -> nft .commit_mutex );
2811
+ lockdep_nfnl_nft_mutex_not_held ();
2779
2812
#ifdef CONFIG_MODULES
2780
2813
if (list_empty (& nf_tables_set_types )) {
2781
2814
nft_request_module (ctx -> net , "nft-set" );
@@ -4820,6 +4853,7 @@ nft_obj_type_get(struct net *net, u32 objtype)
4820
4853
if (type != NULL && try_module_get (type -> owner ))
4821
4854
return type ;
4822
4855
4856
+ lockdep_nfnl_nft_mutex_not_held ();
4823
4857
#ifdef CONFIG_MODULES
4824
4858
if (type == NULL ) {
4825
4859
nft_request_module (net , "nft-obj-%u" , objtype );
@@ -5379,6 +5413,7 @@ nft_flowtable_type_get(struct net *net, u8 family)
5379
5413
if (type != NULL && try_module_get (type -> owner ))
5380
5414
return type ;
5381
5415
5416
+ lockdep_nfnl_nft_mutex_not_held ();
5382
5417
#ifdef CONFIG_MODULES
5383
5418
if (type == NULL ) {
5384
5419
nft_request_module (net , "nf-flowtable-%u" , family );
@@ -6232,9 +6267,9 @@ static void nf_tables_commit_chain_active(struct net *net, struct nft_chain *cha
6232
6267
next_genbit = nft_gencursor_next (net );
6233
6268
6234
6269
g0 = rcu_dereference_protected (chain -> rules_gen_0 ,
6235
- lockdep_nfnl_is_held ( NFNL_SUBSYS_NFTABLES ));
6270
+ lockdep_commit_lock_is_held ( net ));
6236
6271
g1 = rcu_dereference_protected (chain -> rules_gen_1 ,
6237
- lockdep_nfnl_is_held ( NFNL_SUBSYS_NFTABLES ));
6272
+ lockdep_commit_lock_is_held ( net ));
6238
6273
6239
6274
/* No changes to this chain? */
6240
6275
if (chain -> rules_next == NULL ) {
@@ -6442,6 +6477,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
6442
6477
6443
6478
nf_tables_commit_release (net );
6444
6479
nf_tables_gen_notify (net , skb , NFT_MSG_NEWGEN );
6480
+ mutex_unlock (& net -> nft .commit_mutex );
6445
6481
6446
6482
return 0 ;
6447
6483
}
@@ -6593,12 +6629,25 @@ static void nf_tables_cleanup(struct net *net)
6593
6629
6594
6630
static int nf_tables_abort (struct net * net , struct sk_buff * skb )
6595
6631
{
6596
- return __nf_tables_abort (net );
6632
+ int ret = __nf_tables_abort (net );
6633
+
6634
+ mutex_unlock (& net -> nft .commit_mutex );
6635
+
6636
+ return ret ;
6597
6637
}
6598
6638
6599
6639
static bool nf_tables_valid_genid (struct net * net , u32 genid )
6600
6640
{
6601
- return genid == 0 || net -> nft .base_seq == genid ;
6641
+ bool genid_ok ;
6642
+
6643
+ mutex_lock (& net -> nft .commit_mutex );
6644
+
6645
+ genid_ok = genid == 0 || net -> nft .base_seq == genid ;
6646
+ if (!genid_ok )
6647
+ mutex_unlock (& net -> nft .commit_mutex );
6648
+
6649
+ /* else, commit mutex has to be released by commit or abort function */
6650
+ return genid_ok ;
6602
6651
}
6603
6652
6604
6653
static const struct nfnetlink_subsystem nf_tables_subsys = {
@@ -6937,8 +6986,8 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
6937
6986
case NFT_GOTO :
6938
6987
if (!tb [NFTA_VERDICT_CHAIN ])
6939
6988
return - EINVAL ;
6940
- chain = nft_chain_lookup (ctx -> table , tb [ NFTA_VERDICT_CHAIN ] ,
6941
- genmask );
6989
+ chain = nft_chain_lookup (ctx -> net , ctx -> table ,
6990
+ tb [ NFTA_VERDICT_CHAIN ], genmask );
6942
6991
if (IS_ERR (chain ))
6943
6992
return PTR_ERR (chain );
6944
6993
if (nft_is_base_chain (chain ))
@@ -7183,6 +7232,7 @@ static int __net_init nf_tables_init_net(struct net *net)
7183
7232
{
7184
7233
INIT_LIST_HEAD (& net -> nft .tables );
7185
7234
INIT_LIST_HEAD (& net -> nft .commit_list );
7235
+ mutex_init (& net -> nft .commit_mutex );
7186
7236
net -> nft .base_seq = 1 ;
7187
7237
net -> nft .validate_state = NFT_VALIDATE_SKIP ;
7188
7238
@@ -7191,11 +7241,11 @@ static int __net_init nf_tables_init_net(struct net *net)
7191
7241
7192
7242
static void __net_exit nf_tables_exit_net (struct net * net )
7193
7243
{
7194
- nfnl_lock ( NFNL_SUBSYS_NFTABLES );
7244
+ mutex_lock ( & net -> nft . commit_mutex );
7195
7245
if (!list_empty (& net -> nft .commit_list ))
7196
7246
__nf_tables_abort (net );
7197
7247
__nft_release_tables (net );
7198
- nfnl_unlock ( NFNL_SUBSYS_NFTABLES );
7248
+ mutex_unlock ( & net -> nft . commit_mutex );
7199
7249
WARN_ON_ONCE (!list_empty (& net -> nft .tables ));
7200
7250
}
7201
7251
0 commit comments