@@ -623,23 +623,22 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
623
623
struct rt6_rtnl_dump_arg arg = {
624
624
.filter .dump_exceptions = true,
625
625
.filter .dump_routes = true,
626
- .filter .rtnl_held = true ,
626
+ .filter .rtnl_held = false ,
627
627
};
628
628
const struct nlmsghdr * nlh = cb -> nlh ;
629
629
struct net * net = sock_net (skb -> sk );
630
- unsigned int h , s_h ;
631
630
unsigned int e = 0 , s_e ;
631
+ struct hlist_head * head ;
632
632
struct fib6_walker * w ;
633
633
struct fib6_table * tb ;
634
- struct hlist_head * head ;
635
- int res = 0 ;
634
+ unsigned int h , s_h ;
635
+ int err = 0 ;
636
636
637
+ rcu_read_lock ();
637
638
if (cb -> strict_check ) {
638
- int err ;
639
-
640
639
err = ip_valid_fib_dump_req (net , nlh , & arg .filter , cb );
641
640
if (err < 0 )
642
- return err ;
641
+ goto unlock ;
643
642
} else if (nlmsg_len (nlh ) >= sizeof (struct rtmsg )) {
644
643
struct rtmsg * rtm = nlmsg_data (nlh );
645
644
@@ -660,8 +659,10 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
660
659
* 2. allocate and initialize walker.
661
660
*/
662
661
w = kzalloc (sizeof (* w ), GFP_ATOMIC );
663
- if (!w )
664
- return - ENOMEM ;
662
+ if (!w ) {
663
+ err = - ENOMEM ;
664
+ goto unlock ;
665
+ }
665
666
w -> func = fib6_dump_node ;
666
667
cb -> args [2 ] = (long )w ;
667
668
}
@@ -675,46 +676,46 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
675
676
tb = fib6_get_table (net , arg .filter .table_id );
676
677
if (!tb ) {
677
678
if (rtnl_msg_family (cb -> nlh ) != PF_INET6 )
678
- goto out ;
679
+ goto unlock ;
679
680
680
681
NL_SET_ERR_MSG_MOD (cb -> extack , "FIB table does not exist" );
681
- return - ENOENT ;
682
+ err = - ENOENT ;
683
+ goto unlock ;
682
684
}
683
685
684
686
if (!cb -> args [0 ]) {
685
- res = fib6_dump_table (tb , skb , cb );
686
- if (!res )
687
+ err = fib6_dump_table (tb , skb , cb );
688
+ if (!err )
687
689
cb -> args [0 ] = 1 ;
688
690
}
689
- goto out ;
691
+ goto unlock ;
690
692
}
691
693
692
694
s_h = cb -> args [0 ];
693
695
s_e = cb -> args [1 ];
694
696
695
- rcu_read_lock ();
696
697
for (h = s_h ; h < FIB6_TABLE_HASHSZ ; h ++ , s_e = 0 ) {
697
698
e = 0 ;
698
699
head = & net -> ipv6 .fib_table_hash [h ];
699
700
hlist_for_each_entry_rcu (tb , head , tb6_hlist ) {
700
701
if (e < s_e )
701
702
goto next ;
702
- res = fib6_dump_table (tb , skb , cb );
703
- if (res != 0 )
704
- goto out_unlock ;
703
+ err = fib6_dump_table (tb , skb , cb );
704
+ if (err != 0 )
705
+ goto out ;
705
706
next :
706
707
e ++ ;
707
708
}
708
709
}
709
- out_unlock :
710
- rcu_read_unlock ();
710
+ out :
711
711
cb -> args [1 ] = e ;
712
712
cb -> args [0 ] = h ;
713
- out :
714
- res = res < 0 ? res : skb -> len ;
715
- if (res <= 0 )
713
+
714
+ unlock :
715
+ rcu_read_unlock ();
716
+ if (err <= 0 )
716
717
fib6_dump_end (cb );
717
- return res ;
718
+ return err ;
718
719
}
719
720
720
721
void fib6_metric_set (struct fib6_info * f6i , int metric , u32 val )
@@ -2506,7 +2507,7 @@ int __init fib6_init(void)
2506
2507
goto out_kmem_cache_create ;
2507
2508
2508
2509
ret = rtnl_register_module (THIS_MODULE , PF_INET6 , RTM_GETROUTE , NULL ,
2509
- inet6_dump_fib , 0 );
2510
+ inet6_dump_fib , RTNL_FLAG_DUMP_UNLOCKED );
2510
2511
if (ret )
2511
2512
goto out_unregister_subsys ;
2512
2513
0 commit comments