@@ -120,6 +120,11 @@ static void ipmr_expire_process(struct timer_list *t);
120
120
lockdep_rtnl_is_held() || \
121
121
list_empty(&net->ipv4.mr_tables))
122
122
123
+ static bool ipmr_can_free_table (struct net * net )
124
+ {
125
+ return !check_net (net ) || !net -> ipv4 .mr_rules_ops ;
126
+ }
127
+
123
128
static struct mr_table * ipmr_mr_table_iter (struct net * net ,
124
129
struct mr_table * mrt )
125
130
{
@@ -137,7 +142,7 @@ static struct mr_table *ipmr_mr_table_iter(struct net *net,
137
142
return ret ;
138
143
}
139
144
140
- static struct mr_table * ipmr_get_table (struct net * net , u32 id )
145
+ static struct mr_table * __ipmr_get_table (struct net * net , u32 id )
141
146
{
142
147
struct mr_table * mrt ;
143
148
@@ -148,6 +153,16 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
148
153
return NULL ;
149
154
}
150
155
156
+ static struct mr_table * ipmr_get_table (struct net * net , u32 id )
157
+ {
158
+ struct mr_table * mrt ;
159
+
160
+ rcu_read_lock ();
161
+ mrt = __ipmr_get_table (net , id );
162
+ rcu_read_unlock ();
163
+ return mrt ;
164
+ }
165
+
151
166
static int ipmr_fib_lookup (struct net * net , struct flowi4 * flp4 ,
152
167
struct mr_table * * mrt )
153
168
{
@@ -189,7 +204,7 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
189
204
190
205
arg -> table = fib_rule_get_table (rule , arg );
191
206
192
- mrt = ipmr_get_table (rule -> fr_net , arg -> table );
207
+ mrt = __ipmr_get_table (rule -> fr_net , arg -> table );
193
208
if (!mrt )
194
209
return - EAGAIN ;
195
210
res -> mrt = mrt ;
@@ -302,6 +317,11 @@ EXPORT_SYMBOL(ipmr_rule_default);
302
317
#define ipmr_for_each_table (mrt , net ) \
303
318
for (mrt = net->ipv4.mrt; mrt; mrt = NULL)
304
319
320
+ static bool ipmr_can_free_table (struct net * net )
321
+ {
322
+ return !check_net (net );
323
+ }
324
+
305
325
static struct mr_table * ipmr_mr_table_iter (struct net * net ,
306
326
struct mr_table * mrt )
307
327
{
@@ -315,6 +335,8 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
315
335
return net -> ipv4 .mrt ;
316
336
}
317
337
338
+ #define __ipmr_get_table ipmr_get_table
339
+
318
340
static int ipmr_fib_lookup (struct net * net , struct flowi4 * flp4 ,
319
341
struct mr_table * * mrt )
320
342
{
@@ -403,7 +425,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
403
425
if (id != RT_TABLE_DEFAULT && id >= 1000000000 )
404
426
return ERR_PTR (- EINVAL );
405
427
406
- mrt = ipmr_get_table (net , id );
428
+ mrt = __ipmr_get_table (net , id );
407
429
if (mrt )
408
430
return mrt ;
409
431
@@ -413,6 +435,10 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
413
435
414
436
static void ipmr_free_table (struct mr_table * mrt )
415
437
{
438
+ struct net * net = read_pnet (& mrt -> net );
439
+
440
+ DEBUG_NET_WARN_ON_ONCE (!ipmr_can_free_table (net ));
441
+
416
442
timer_shutdown_sync (& mrt -> ipmr_expire_timer );
417
443
mroute_clean_tables (mrt , MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |
418
444
MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC );
@@ -1374,7 +1400,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
1374
1400
goto out_unlock ;
1375
1401
}
1376
1402
1377
- mrt = ipmr_get_table (net , raw_sk (sk )-> ipmr_table ? : RT_TABLE_DEFAULT );
1403
+ mrt = __ipmr_get_table (net , raw_sk (sk )-> ipmr_table ? : RT_TABLE_DEFAULT );
1378
1404
if (!mrt ) {
1379
1405
ret = - ENOENT ;
1380
1406
goto out_unlock ;
@@ -2262,11 +2288,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
2262
2288
struct mr_table * mrt ;
2263
2289
int err ;
2264
2290
2265
- mrt = ipmr_get_table (net , RT_TABLE_DEFAULT );
2266
- if (!mrt )
2291
+ rcu_read_lock ();
2292
+ mrt = __ipmr_get_table (net , RT_TABLE_DEFAULT );
2293
+ if (!mrt ) {
2294
+ rcu_read_unlock ();
2267
2295
return - ENOENT ;
2296
+ }
2268
2297
2269
- rcu_read_lock ();
2270
2298
cache = ipmr_cache_find (mrt , saddr , daddr );
2271
2299
if (!cache && skb -> dev ) {
2272
2300
int vif = ipmr_find_vif (mrt , skb -> dev );
@@ -2550,7 +2578,7 @@ static int ipmr_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
2550
2578
grp = nla_get_in_addr_default (tb [RTA_DST ], 0 );
2551
2579
tableid = nla_get_u32_default (tb [RTA_TABLE ], 0 );
2552
2580
2553
- mrt = ipmr_get_table (net , tableid ? tableid : RT_TABLE_DEFAULT );
2581
+ mrt = __ipmr_get_table (net , tableid ? tableid : RT_TABLE_DEFAULT );
2554
2582
if (!mrt ) {
2555
2583
err = - ENOENT ;
2556
2584
goto errout_free ;
@@ -2604,7 +2632,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
2604
2632
if (filter .table_id ) {
2605
2633
struct mr_table * mrt ;
2606
2634
2607
- mrt = ipmr_get_table (sock_net (skb -> sk ), filter .table_id );
2635
+ mrt = __ipmr_get_table (sock_net (skb -> sk ), filter .table_id );
2608
2636
if (!mrt ) {
2609
2637
if (rtnl_msg_family (cb -> nlh ) != RTNL_FAMILY_IPMR )
2610
2638
return skb -> len ;
@@ -2712,7 +2740,7 @@ static int rtm_to_ipmr_mfcc(struct net *net, struct nlmsghdr *nlh,
2712
2740
break ;
2713
2741
}
2714
2742
}
2715
- mrt = ipmr_get_table (net , tblid );
2743
+ mrt = __ipmr_get_table (net , tblid );
2716
2744
if (!mrt ) {
2717
2745
ret = - ENOENT ;
2718
2746
goto out ;
@@ -2920,13 +2948,15 @@ static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
2920
2948
struct net * net = seq_file_net (seq );
2921
2949
struct mr_table * mrt ;
2922
2950
2923
- mrt = ipmr_get_table (net , RT_TABLE_DEFAULT );
2924
- if (!mrt )
2951
+ rcu_read_lock ();
2952
+ mrt = __ipmr_get_table (net , RT_TABLE_DEFAULT );
2953
+ if (!mrt ) {
2954
+ rcu_read_unlock ();
2925
2955
return ERR_PTR (- ENOENT );
2956
+ }
2926
2957
2927
2958
iter -> mrt = mrt ;
2928
2959
2929
- rcu_read_lock ();
2930
2960
return mr_vif_seq_start (seq , pos );
2931
2961
}
2932
2962
0 commit comments