@@ -120,6 +120,11 @@ static void ipmr_expire_process(struct timer_list *t);
120120 lockdep_rtnl_is_held() || \
121121 list_empty(&net->ipv4.mr_tables))
122122
123+ static bool ipmr_can_free_table (struct net * net )
124+ {
125+ return !check_net (net ) || !net -> ipv4 .mr_rules_ops ;
126+ }
127+
123128static struct mr_table * ipmr_mr_table_iter (struct net * net ,
124129 struct mr_table * mrt )
125130{
@@ -137,7 +142,7 @@ static struct mr_table *ipmr_mr_table_iter(struct net *net,
137142 return ret ;
138143}
139144
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 )
141146{
142147 struct mr_table * mrt ;
143148
@@ -148,6 +153,16 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
148153 return NULL ;
149154}
150155
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+
151166static int ipmr_fib_lookup (struct net * net , struct flowi4 * flp4 ,
152167 struct mr_table * * mrt )
153168{
@@ -189,7 +204,7 @@ static int ipmr_rule_action(struct fib_rule *rule, struct flowi *flp,
189204
190205 arg -> table = fib_rule_get_table (rule , arg );
191206
192- mrt = ipmr_get_table (rule -> fr_net , arg -> table );
207+ mrt = __ipmr_get_table (rule -> fr_net , arg -> table );
193208 if (!mrt )
194209 return - EAGAIN ;
195210 res -> mrt = mrt ;
@@ -302,6 +317,11 @@ EXPORT_SYMBOL(ipmr_rule_default);
302317#define ipmr_for_each_table (mrt , net ) \
303318 for (mrt = net->ipv4.mrt; mrt; mrt = NULL)
304319
320+ static bool ipmr_can_free_table (struct net * net )
321+ {
322+ return !check_net (net );
323+ }
324+
305325static struct mr_table * ipmr_mr_table_iter (struct net * net ,
306326 struct mr_table * mrt )
307327{
@@ -315,6 +335,8 @@ static struct mr_table *ipmr_get_table(struct net *net, u32 id)
315335 return net -> ipv4 .mrt ;
316336}
317337
338+ #define __ipmr_get_table ipmr_get_table
339+
318340static int ipmr_fib_lookup (struct net * net , struct flowi4 * flp4 ,
319341 struct mr_table * * mrt )
320342{
@@ -403,7 +425,7 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
403425 if (id != RT_TABLE_DEFAULT && id >= 1000000000 )
404426 return ERR_PTR (- EINVAL );
405427
406- mrt = ipmr_get_table (net , id );
428+ mrt = __ipmr_get_table (net , id );
407429 if (mrt )
408430 return mrt ;
409431
@@ -413,6 +435,10 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
413435
414436static void ipmr_free_table (struct mr_table * mrt )
415437{
438+ struct net * net = read_pnet (& mrt -> net );
439+
440+ DEBUG_NET_WARN_ON_ONCE (!ipmr_can_free_table (net ));
441+
416442 timer_shutdown_sync (& mrt -> ipmr_expire_timer );
417443 mroute_clean_tables (mrt , MRT_FLUSH_VIFS | MRT_FLUSH_VIFS_STATIC |
418444 MRT_FLUSH_MFC | MRT_FLUSH_MFC_STATIC );
@@ -1374,7 +1400,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, sockptr_t optval,
13741400 goto out_unlock ;
13751401 }
13761402
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 );
13781404 if (!mrt ) {
13791405 ret = - ENOENT ;
13801406 goto out_unlock ;
@@ -2262,11 +2288,13 @@ int ipmr_get_route(struct net *net, struct sk_buff *skb,
22622288 struct mr_table * mrt ;
22632289 int err ;
22642290
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 ();
22672295 return - ENOENT ;
2296+ }
22682297
2269- rcu_read_lock ();
22702298 cache = ipmr_cache_find (mrt , saddr , daddr );
22712299 if (!cache && skb -> dev ) {
22722300 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,
25502578 grp = nla_get_in_addr_default (tb [RTA_DST ], 0 );
25512579 tableid = nla_get_u32_default (tb [RTA_TABLE ], 0 );
25522580
2553- mrt = ipmr_get_table (net , tableid ? tableid : RT_TABLE_DEFAULT );
2581+ mrt = __ipmr_get_table (net , tableid ? tableid : RT_TABLE_DEFAULT );
25542582 if (!mrt ) {
25552583 err = - ENOENT ;
25562584 goto errout_free ;
@@ -2604,7 +2632,7 @@ static int ipmr_rtm_dumproute(struct sk_buff *skb, struct netlink_callback *cb)
26042632 if (filter .table_id ) {
26052633 struct mr_table * mrt ;
26062634
2607- mrt = ipmr_get_table (sock_net (skb -> sk ), filter .table_id );
2635+ mrt = __ipmr_get_table (sock_net (skb -> sk ), filter .table_id );
26082636 if (!mrt ) {
26092637 if (rtnl_msg_family (cb -> nlh ) != RTNL_FAMILY_IPMR )
26102638 return skb -> len ;
@@ -2712,7 +2740,7 @@ static int rtm_to_ipmr_mfcc(struct net *net, struct nlmsghdr *nlh,
27122740 break ;
27132741 }
27142742 }
2715- mrt = ipmr_get_table (net , tblid );
2743+ mrt = __ipmr_get_table (net , tblid );
27162744 if (!mrt ) {
27172745 ret = - ENOENT ;
27182746 goto out ;
@@ -2920,13 +2948,15 @@ static void *ipmr_vif_seq_start(struct seq_file *seq, loff_t *pos)
29202948 struct net * net = seq_file_net (seq );
29212949 struct mr_table * mrt ;
29222950
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 ();
29252955 return ERR_PTR (- ENOENT );
2956+ }
29262957
29272958 iter -> mrt = mrt ;
29282959
2929- rcu_read_lock ();
29302960 return mr_vif_seq_start (seq , pos );
29312961}
29322962
0 commit comments