@@ -553,18 +553,16 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
553553 const struct in_ifaddr * ifa ;
554554 struct in_device * in_dev ;
555555
556- in_dev = __in_dev_get_rtnl (dev );
556+ in_dev = __in_dev_get_rtnl_net (dev );
557557 if (!in_dev )
558558 return - ENODEV ;
559559
560560 * colon = ':' ;
561561
562- rcu_read_lock ();
563- in_dev_for_each_ifa_rcu (ifa , in_dev ) {
562+ in_dev_for_each_ifa_rtnl_net (net , ifa , in_dev ) {
564563 if (strcmp (ifa -> ifa_label , devname ) == 0 )
565564 break ;
566565 }
567- rcu_read_unlock ();
568566
569567 if (!ifa )
570568 return - ENODEV ;
@@ -635,7 +633,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
635633 if (!ns_capable (net -> user_ns , CAP_NET_ADMIN ))
636634 return - EPERM ;
637635
638- rtnl_lock ( );
636+ rtnl_net_lock ( net );
639637 err = rtentry_to_fib_config (net , cmd , rt , & cfg );
640638 if (err == 0 ) {
641639 struct fib_table * tb ;
@@ -659,7 +657,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
659657 /* allocated by rtentry_to_fib_config() */
660658 kfree (cfg .fc_mx );
661659 }
662- rtnl_unlock ( );
660+ rtnl_net_unlock ( net );
663661 return err ;
664662 }
665663 return - EINVAL ;
@@ -837,19 +835,33 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
837835 }
838836 }
839837
838+ if (cfg -> fc_dst_len > 32 ) {
839+ NL_SET_ERR_MSG (extack , "Invalid prefix length" );
840+ err = - EINVAL ;
841+ goto errout ;
842+ }
843+
844+ if (cfg -> fc_dst_len < 32 && (ntohl (cfg -> fc_dst ) << cfg -> fc_dst_len )) {
845+ NL_SET_ERR_MSG (extack , "Invalid prefix for given prefix length" );
846+ err = - EINVAL ;
847+ goto errout ;
848+ }
849+
840850 if (cfg -> fc_nh_id ) {
841851 if (cfg -> fc_oif || cfg -> fc_gw_family ||
842852 cfg -> fc_encap || cfg -> fc_mp ) {
843853 NL_SET_ERR_MSG (extack ,
844854 "Nexthop specification and nexthop id are mutually exclusive" );
845- return - EINVAL ;
855+ err = - EINVAL ;
856+ goto errout ;
846857 }
847858 }
848859
849860 if (has_gw && has_via ) {
850861 NL_SET_ERR_MSG (extack ,
851862 "Nexthop configuration can not contain both GATEWAY and VIA" );
852- return - EINVAL ;
863+ err = - EINVAL ;
864+ goto errout ;
853865 }
854866
855867 if (!cfg -> fc_table )
@@ -872,20 +884,24 @@ static int inet_rtm_delroute(struct sk_buff *skb, struct nlmsghdr *nlh,
872884 if (err < 0 )
873885 goto errout ;
874886
887+ rtnl_net_lock (net );
888+
875889 if (cfg .fc_nh_id && !nexthop_find_by_id (net , cfg .fc_nh_id )) {
876890 NL_SET_ERR_MSG (extack , "Nexthop id does not exist" );
877891 err = - EINVAL ;
878- goto errout ;
892+ goto unlock ;
879893 }
880894
881895 tb = fib_get_table (net , cfg .fc_table );
882896 if (!tb ) {
883897 NL_SET_ERR_MSG (extack , "FIB table does not exist" );
884898 err = - ESRCH ;
885- goto errout ;
899+ goto unlock ;
886900 }
887901
888902 err = fib_table_delete (net , tb , & cfg , extack );
903+ unlock :
904+ rtnl_net_unlock (net );
889905errout :
890906 return err ;
891907}
@@ -902,15 +918,20 @@ static int inet_rtm_newroute(struct sk_buff *skb, struct nlmsghdr *nlh,
902918 if (err < 0 )
903919 goto errout ;
904920
921+ rtnl_net_lock (net );
922+
905923 tb = fib_new_table (net , cfg .fc_table );
906924 if (!tb ) {
907925 err = - ENOBUFS ;
908- goto errout ;
926+ goto unlock ;
909927 }
910928
911929 err = fib_table_insert (net , tb , & cfg , extack );
912930 if (!err && cfg .fc_type == RTN_LOCAL )
913931 net -> ipv4 .fib_has_custom_local_routes = true;
932+
933+ unlock :
934+ rtnl_net_unlock (net );
914935errout :
915936 return err ;
916937}
@@ -1450,7 +1471,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
14501471 fib_sync_up (dev , RTNH_F_DEAD );
14511472#endif
14521473 atomic_inc (& net -> ipv4 .dev_addr_genid );
1453- rt_cache_flush (dev_net ( dev ) );
1474+ rt_cache_flush (net );
14541475 break ;
14551476 case NETDEV_DOWN :
14561477 fib_del_ifaddr (ifa , NULL );
@@ -1461,7 +1482,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
14611482 */
14621483 fib_disable_ip (dev , event , true);
14631484 } else {
1464- rt_cache_flush (dev_net ( dev ) );
1485+ rt_cache_flush (net );
14651486 }
14661487 break ;
14671488 }
@@ -1575,7 +1596,7 @@ static void ip_fib_net_exit(struct net *net)
15751596{
15761597 int i ;
15771598
1578- ASSERT_RTNL ( );
1599+ ASSERT_RTNL_NET ( net );
15791600#ifdef CONFIG_IP_MULTIPLE_TABLES
15801601 RCU_INIT_POINTER (net -> ipv4 .fib_main , NULL );
15811602 RCU_INIT_POINTER (net -> ipv4 .fib_default , NULL );
@@ -1615,9 +1636,15 @@ static int __net_init fib_net_init(struct net *net)
16151636 error = ip_fib_net_init (net );
16161637 if (error < 0 )
16171638 goto out ;
1639+
1640+ error = fib4_semantics_init (net );
1641+ if (error )
1642+ goto out_semantics ;
1643+
16181644 error = nl_fib_lookup_init (net );
16191645 if (error < 0 )
16201646 goto out_nlfl ;
1647+
16211648 error = fib_proc_init (net );
16221649 if (error < 0 )
16231650 goto out_proc ;
@@ -1627,9 +1654,11 @@ static int __net_init fib_net_init(struct net *net)
16271654out_proc :
16281655 nl_fib_lookup_exit (net );
16291656out_nlfl :
1630- rtnl_lock ();
1657+ fib4_semantics_exit (net );
1658+ out_semantics :
1659+ rtnl_net_lock (net );
16311660 ip_fib_net_exit (net );
1632- rtnl_unlock ( );
1661+ rtnl_net_unlock ( net );
16331662 goto out ;
16341663}
16351664
@@ -1644,10 +1673,15 @@ static void __net_exit fib_net_exit_batch(struct list_head *net_list)
16441673 struct net * net ;
16451674
16461675 rtnl_lock ();
1647- list_for_each_entry (net , net_list , exit_list )
1676+ list_for_each_entry (net , net_list , exit_list ) {
1677+ __rtnl_net_lock (net );
16481678 ip_fib_net_exit (net );
1649-
1679+ __rtnl_net_unlock (net );
1680+ }
16501681 rtnl_unlock ();
1682+
1683+ list_for_each_entry (net , net_list , exit_list )
1684+ fib4_semantics_exit (net );
16511685}
16521686
16531687static struct pernet_operations fib_net_ops = {
@@ -1658,9 +1692,9 @@ static struct pernet_operations fib_net_ops = {
16581692
16591693static const struct rtnl_msg_handler fib_rtnl_msg_handlers [] __initconst = {
16601694 {.protocol = PF_INET , .msgtype = RTM_NEWROUTE ,
1661- .doit = inet_rtm_newroute },
1695+ .doit = inet_rtm_newroute , . flags = RTNL_FLAG_DOIT_PERNET },
16621696 {.protocol = PF_INET , .msgtype = RTM_DELROUTE ,
1663- .doit = inet_rtm_delroute },
1697+ .doit = inet_rtm_delroute , . flags = RTNL_FLAG_DOIT_PERNET },
16641698 {.protocol = PF_INET , .msgtype = RTM_GETROUTE , .dumpit = inet_dump_fib ,
16651699 .flags = RTNL_FLAG_DUMP_UNLOCKED | RTNL_FLAG_DUMP_SPLIT_NLM_DONE },
16661700};
0 commit comments