]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
ipv6: Convert inet6_rtm_newaddr() to per-netns RTNL.
authorKuniyuki Iwashima <kuniyu@amazon.com>
Wed, 15 Jan 2025 08:06:07 +0000 (17:06 +0900)
committerJakub Kicinski <kuba@kernel.org>
Mon, 20 Jan 2025 20:16:06 +0000 (12:16 -0800)
Let's register inet6_rtm_newaddr() with RTNL_FLAG_DOIT_PERNET
and hold rtnl_net_lock() before __dev_get_by_index().

Now that inet6_addr_add() and inet6_addr_modify() are always
called under per-netns RTNL.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Link: https://patch.msgid.link/20250115080608.28127-11-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
net/ipv6/addrconf.c

index 9ae25a8d163291a8d7ae2ce49dc8bcf0296e4ddd..b848e4038d2eff7afcdf713bf1cd0fed111e89de 100644 (file)
@@ -3014,7 +3014,7 @@ static int inet6_addr_add(struct net *net, struct net_device *dev,
        struct inet6_ifaddr *ifp;
        struct inet6_dev *idev;
 
-       ASSERT_RTNL();
+       ASSERT_RTNL_NET(net);
 
        if (cfg->plen > 128) {
                NL_SET_ERR_MSG_MOD(extack, "Invalid prefix length");
@@ -4849,7 +4849,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
        bool new_peer = false;
        bool had_prefixroute;
 
-       ASSERT_RTNL();
+       ASSERT_RTNL_NET(net);
 
        if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR &&
            (ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
@@ -5016,15 +5016,20 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
                }
        }
 
+       rtnl_net_lock(net);
+
        dev =  __dev_get_by_index(net, ifm->ifa_index);
        if (!dev) {
                NL_SET_ERR_MSG_MOD(extack, "Unable to find the interface");
-               return -ENODEV;
+               err = -ENODEV;
+               goto unlock;
        }
 
        idev = ipv6_find_idev(dev);
-       if (IS_ERR(idev))
-               return PTR_ERR(idev);
+       if (IS_ERR(idev)) {
+               err = PTR_ERR(idev);
+               goto unlock;
+       }
 
        if (!ipv6_allow_optimistic_dad(net, idev))
                cfg.ifa_flags &= ~IFA_F_OPTIMISTIC;
@@ -5032,7 +5037,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
        if (cfg.ifa_flags & IFA_F_NODAD &&
            cfg.ifa_flags & IFA_F_OPTIMISTIC) {
                NL_SET_ERR_MSG(extack, "IFA_F_NODAD and IFA_F_OPTIMISTIC are mutually exclusive");
-               return -EINVAL;
+               err = -EINVAL;
+               goto unlock;
        }
 
        ifa = ipv6_get_ifaddr(net, cfg.pfx, dev, 1);
@@ -5041,7 +5047,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
                 * It would be best to check for !NLM_F_CREATE here but
                 * userspace already relies on not having to provide this.
                 */
-               return inet6_addr_add(net, dev, &cfg, expires, flags, extack);
+               err = inet6_addr_add(net, dev, &cfg, expires, flags, extack);
+               goto unlock;
        }
 
        if (nlh->nlmsg_flags & NLM_F_EXCL ||
@@ -5053,6 +5060,8 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
        }
 
        in6_ifa_put(ifa);
+unlock:
+       rtnl_net_unlock(net);
 
        return err;
 }
@@ -7393,7 +7402,7 @@ static const struct rtnl_msg_handler addrconf_rtnl_msg_handlers[] __initconst_or
        {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETLINK,
         .dumpit = inet6_dump_ifinfo, .flags = RTNL_FLAG_DUMP_UNLOCKED},
        {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_NEWADDR,
-        .doit = inet6_rtm_newaddr},
+        .doit = inet6_rtm_newaddr, .flags = RTNL_FLAG_DOIT_PERNET},
        {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_DELADDR,
         .doit = inet6_rtm_deladdr},
        {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETADDR,