@@ -371,7 +371,8 @@ static int call_fib_rule_notifiers(struct net *net,
371371 .rule = rule ,
372372 };
373373
374- ASSERT_RTNL ();
374+ ASSERT_RTNL_NET (net );
375+
375376 /* Paired with READ_ONCE() in fib_rules_seq() */
376377 WRITE_ONCE (ops -> fib_rules_seq , ops -> fib_rules_seq + 1 );
377378 return call_fib_notifiers (net , event_type , & info .info );
@@ -459,9 +460,6 @@ static struct fib_rule *rule_find(struct fib_rules_ops *ops,
459460 if (rule -> tun_id && r -> tun_id != rule -> tun_id )
460461 continue ;
461462
462- if (r -> fr_net != rule -> fr_net )
463- continue ;
464-
465463 if (rule -> l3mdev && r -> l3mdev != rule -> l3mdev )
466464 continue ;
467465
@@ -515,14 +513,13 @@ static int fib_nl2rule_l3mdev(struct nlattr *nla, struct fib_rule *nlrule,
515513}
516514#endif
517515
518- static int fib_nl2rule (struct sk_buff * skb , struct nlmsghdr * nlh ,
516+ static int fib_nl2rule (struct net * net , struct nlmsghdr * nlh ,
519517 struct netlink_ext_ack * extack ,
520518 struct fib_rules_ops * ops ,
521519 struct nlattr * tb [],
522520 struct fib_rule * * rule ,
523521 bool * user_priority )
524522{
525- struct net * net = sock_net (skb -> sk );
526523 struct fib_rule_hdr * frh = nlmsg_data (nlh );
527524 struct fib_rule * nlrule = NULL ;
528525 int err = - EINVAL ;
@@ -554,30 +551,18 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
554551 if (tb [FRA_PRIORITY ]) {
555552 nlrule -> pref = nla_get_u32 (tb [FRA_PRIORITY ]);
556553 * user_priority = true;
557- } else {
558- nlrule -> pref = fib_default_rule_pref (ops );
559554 }
560555
561556 nlrule -> proto = nla_get_u8_default (tb [FRA_PROTOCOL ], RTPROT_UNSPEC );
562557
563558 if (tb [FRA_IIFNAME ]) {
564- struct net_device * dev ;
565-
566559 nlrule -> iifindex = -1 ;
567560 nla_strscpy (nlrule -> iifname , tb [FRA_IIFNAME ], IFNAMSIZ );
568- dev = __dev_get_by_name (net , nlrule -> iifname );
569- if (dev )
570- nlrule -> iifindex = dev -> ifindex ;
571561 }
572562
573563 if (tb [FRA_OIFNAME ]) {
574- struct net_device * dev ;
575-
576564 nlrule -> oifindex = -1 ;
577565 nla_strscpy (nlrule -> oifname , tb [FRA_OIFNAME ], IFNAMSIZ );
578- dev = __dev_get_by_name (net , nlrule -> oifname );
579- if (dev )
580- nlrule -> oifindex = dev -> ifindex ;
581566 }
582567
583568 if (tb [FRA_FWMARK ]) {
@@ -619,11 +604,6 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
619604 }
620605
621606 nlrule -> target = nla_get_u32 (tb [FRA_GOTO ]);
622- /* Backward jumps are prohibited to avoid endless loops */
623- if (nlrule -> target <= nlrule -> pref ) {
624- NL_SET_ERR_MSG (extack , "Backward goto not supported" );
625- goto errout_free ;
626- }
627607 } else if (nlrule -> action == FR_ACT_GOTO ) {
628608 NL_SET_ERR_MSG (extack , "Missing goto target for action goto" );
629609 goto errout_free ;
@@ -683,6 +663,39 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh,
683663 return err ;
684664}
685665
666+ static int fib_nl2rule_rtnl (struct fib_rule * nlrule ,
667+ struct fib_rules_ops * ops ,
668+ struct nlattr * tb [],
669+ struct netlink_ext_ack * extack )
670+ {
671+ if (!tb [FRA_PRIORITY ])
672+ nlrule -> pref = fib_default_rule_pref (ops );
673+
674+ /* Backward jumps are prohibited to avoid endless loops */
675+ if (tb [FRA_GOTO ] && nlrule -> target <= nlrule -> pref ) {
676+ NL_SET_ERR_MSG (extack , "Backward goto not supported" );
677+ return - EINVAL ;
678+ }
679+
680+ if (tb [FRA_IIFNAME ]) {
681+ struct net_device * dev ;
682+
683+ dev = __dev_get_by_name (nlrule -> fr_net , nlrule -> iifname );
684+ if (dev )
685+ nlrule -> iifindex = dev -> ifindex ;
686+ }
687+
688+ if (tb [FRA_OIFNAME ]) {
689+ struct net_device * dev ;
690+
691+ dev = __dev_get_by_name (nlrule -> fr_net , nlrule -> oifname );
692+ if (dev )
693+ nlrule -> oifindex = dev -> ifindex ;
694+ }
695+
696+ return 0 ;
697+ }
698+
686699static int rule_exists (struct fib_rules_ops * ops , struct fib_rule_hdr * frh ,
687700 struct nlattr * * tb , struct fib_rule * rule )
688701{
@@ -719,9 +732,6 @@ static int rule_exists(struct fib_rules_ops *ops, struct fib_rule_hdr *frh,
719732 if (r -> tun_id != rule -> tun_id )
720733 continue ;
721734
722- if (r -> fr_net != rule -> fr_net )
723- continue ;
724-
725735 if (r -> l3mdev != rule -> l3mdev )
726736 continue ;
727737
@@ -774,15 +784,14 @@ static const struct nla_policy fib_rule_policy[FRA_MAX + 1] = {
774784 [FRA_FLOWLABEL_MASK ] = { .type = NLA_BE32 },
775785};
776786
777- int fib_nl_newrule ( struct sk_buff * skb , struct nlmsghdr * nlh ,
778- struct netlink_ext_ack * extack )
787+ int fib_newrule ( struct net * net , struct sk_buff * skb , struct nlmsghdr * nlh ,
788+ struct netlink_ext_ack * extack , bool rtnl_held )
779789{
780- struct net * net = sock_net ( skb -> sk ) ;
790+ struct fib_rule * rule = NULL , * r , * last = NULL ;
781791 struct fib_rule_hdr * frh = nlmsg_data (nlh );
792+ int err = - EINVAL , unresolved = 0 ;
782793 struct fib_rules_ops * ops = NULL ;
783- struct fib_rule * rule = NULL , * r , * last = NULL ;
784794 struct nlattr * tb [FRA_MAX + 1 ];
785- int err = - EINVAL , unresolved = 0 ;
786795 bool user_priority = false;
787796
788797 if (nlh -> nlmsg_len < nlmsg_msg_size (sizeof (* frh ))) {
@@ -804,10 +813,17 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
804813 goto errout ;
805814 }
806815
807- err = fib_nl2rule (skb , nlh , extack , ops , tb , & rule , & user_priority );
816+ err = fib_nl2rule (net , nlh , extack , ops , tb , & rule , & user_priority );
808817 if (err )
809818 goto errout ;
810819
820+ if (!rtnl_held )
821+ rtnl_net_lock (net );
822+
823+ err = fib_nl2rule_rtnl (rule , ops , tb , extack );
824+ if (err )
825+ goto errout_free ;
826+
811827 if ((nlh -> nlmsg_flags & NLM_F_EXCL ) &&
812828 rule_exists (ops , frh , tb , rule )) {
813829 err = - EEXIST ;
@@ -869,29 +885,42 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
869885 if (rule -> tun_id )
870886 ip_tunnel_need_metadata ();
871887
888+ fib_rule_get (rule );
889+
890+ if (!rtnl_held )
891+ rtnl_net_unlock (net );
892+
872893 notify_rule_change (RTM_NEWRULE , rule , ops , nlh , NETLINK_CB (skb ).portid );
894+ fib_rule_put (rule );
873895 flush_route_cache (ops );
874896 rules_ops_put (ops );
875897 return 0 ;
876898
877899errout_free :
900+ if (!rtnl_held )
901+ rtnl_net_unlock (net );
878902 kfree (rule );
879903errout :
880904 rules_ops_put (ops );
881905 return err ;
882906}
883- EXPORT_SYMBOL_GPL (fib_nl_newrule );
907+ EXPORT_SYMBOL_GPL (fib_newrule );
884908
885- int fib_nl_delrule (struct sk_buff * skb , struct nlmsghdr * nlh ,
886- struct netlink_ext_ack * extack )
909+ static int fib_nl_newrule (struct sk_buff * skb , struct nlmsghdr * nlh ,
910+ struct netlink_ext_ack * extack )
887911{
888- struct net * net = sock_net (skb -> sk );
912+ return fib_newrule (sock_net (skb -> sk ), skb , nlh , extack , false);
913+ }
914+
915+ int fib_delrule (struct net * net , struct sk_buff * skb , struct nlmsghdr * nlh ,
916+ struct netlink_ext_ack * extack , bool rtnl_held )
917+ {
918+ struct fib_rule * rule = NULL , * nlrule = NULL ;
889919 struct fib_rule_hdr * frh = nlmsg_data (nlh );
890920 struct fib_rules_ops * ops = NULL ;
891- struct fib_rule * rule = NULL , * r , * nlrule = NULL ;
892921 struct nlattr * tb [FRA_MAX + 1 ];
893- int err = - EINVAL ;
894922 bool user_priority = false;
923+ int err = - EINVAL ;
895924
896925 if (nlh -> nlmsg_len < nlmsg_msg_size (sizeof (* frh ))) {
897926 NL_SET_ERR_MSG (extack , "Invalid msg length" );
@@ -912,25 +941,32 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
912941 goto errout ;
913942 }
914943
915- err = fib_nl2rule (skb , nlh , extack , ops , tb , & nlrule , & user_priority );
944+ err = fib_nl2rule (net , nlh , extack , ops , tb , & nlrule , & user_priority );
916945 if (err )
917946 goto errout ;
918947
948+ if (!rtnl_held )
949+ rtnl_net_lock (net );
950+
951+ err = fib_nl2rule_rtnl (nlrule , ops , tb , extack );
952+ if (err )
953+ goto errout_free ;
954+
919955 rule = rule_find (ops , frh , tb , nlrule , user_priority );
920956 if (!rule ) {
921957 err = - ENOENT ;
922- goto errout ;
958+ goto errout_free ;
923959 }
924960
925961 if (rule -> flags & FIB_RULE_PERMANENT ) {
926962 err = - EPERM ;
927- goto errout ;
963+ goto errout_free ;
928964 }
929965
930966 if (ops -> delete ) {
931967 err = ops -> delete (rule );
932968 if (err )
933- goto errout ;
969+ goto errout_free ;
934970 }
935971
936972 if (rule -> tun_id )
@@ -952,7 +988,7 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
952988 * current if it is goto rule, have actually been added.
953989 */
954990 if (ops -> nr_goto_rules > 0 ) {
955- struct fib_rule * n ;
991+ struct fib_rule * n , * r ;
956992
957993 n = list_next_entry (rule , list );
958994 if (& n -> list == & ops -> rules_list || n -> pref != rule -> pref )
@@ -966,22 +1002,33 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh,
9661002 }
9671003 }
9681004
969- call_fib_rule_notifiers (net , FIB_EVENT_RULE_DEL , rule , ops ,
970- NULL );
971- notify_rule_change (RTM_DELRULE , rule , ops , nlh ,
972- NETLINK_CB (skb ).portid );
1005+ call_fib_rule_notifiers (net , FIB_EVENT_RULE_DEL , rule , ops , NULL );
1006+
1007+ if (!rtnl_held )
1008+ rtnl_net_unlock (net );
1009+
1010+ notify_rule_change (RTM_DELRULE , rule , ops , nlh , NETLINK_CB (skb ).portid );
9731011 fib_rule_put (rule );
9741012 flush_route_cache (ops );
9751013 rules_ops_put (ops );
9761014 kfree (nlrule );
9771015 return 0 ;
9781016
979- errout :
1017+ errout_free :
1018+ if (!rtnl_held )
1019+ rtnl_net_unlock (net );
9801020 kfree (nlrule );
1021+ errout :
9811022 rules_ops_put (ops );
9821023 return err ;
9831024}
984- EXPORT_SYMBOL_GPL (fib_nl_delrule );
1025+ EXPORT_SYMBOL_GPL (fib_delrule );
1026+
1027+ static int fib_nl_delrule (struct sk_buff * skb , struct nlmsghdr * nlh ,
1028+ struct netlink_ext_ack * extack )
1029+ {
1030+ return fib_delrule (sock_net (skb -> sk ), skb , nlh , extack , false);
1031+ }
9851032
9861033static inline size_t fib_rule_nlmsg_size (struct fib_rules_ops * ops ,
9871034 struct fib_rule * rule )
@@ -1293,8 +1340,10 @@ static struct pernet_operations fib_rules_net_ops = {
12931340};
12941341
12951342static const struct rtnl_msg_handler fib_rules_rtnl_msg_handlers [] __initconst = {
1296- {.msgtype = RTM_NEWRULE , .doit = fib_nl_newrule },
1297- {.msgtype = RTM_DELRULE , .doit = fib_nl_delrule },
1343+ {.msgtype = RTM_NEWRULE , .doit = fib_nl_newrule ,
1344+ .flags = RTNL_FLAG_DOIT_PERNET },
1345+ {.msgtype = RTM_DELRULE , .doit = fib_nl_delrule ,
1346+ .flags = RTNL_FLAG_DOIT_PERNET },
12981347 {.msgtype = RTM_GETRULE , .dumpit = fib_nl_dumprule ,
12991348 .flags = RTNL_FLAG_DUMP_UNLOCKED },
13001349};
0 commit comments