]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
ipv4: fib: Hold rtnl_net_lock() in ip_rt_ioctl().
authorKuniyuki Iwashima <kuniyu@amazon.com>
Fri, 28 Feb 2025 04:23:26 +0000 (20:23 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 29 May 2025 09:13:00 +0000 (11:13 +0200)
[ Upstream commit c0ebe1cdc2cff0dee092a67f2c50377bb5fcf43d ]

ioctl(SIOCADDRT/SIOCDELRT) calls ip_rt_ioctl() to add/remove a route in
the netns of the specified socket.

Let's hold rtnl_net_lock() there.

Note that rtentry_to_fib_config() can be called without rtnl_net_lock()
if we convert rtentry.dev handling to RCU later.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250228042328.96624-11-kuniyu@amazon.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv4/fib_frontend.c

index 493c37ce232d38c509b5cc1ea0452861ee0572d3..8470e259d8fd8ea24836f37bd038556b96e1bd93 100644 (file)
@@ -553,18 +553,16 @@ static int rtentry_to_fib_config(struct net *net, int cmd, struct rtentry *rt,
                        const struct in_ifaddr *ifa;
                        struct in_device *in_dev;
 
-                       in_dev = __in_dev_get_rtnl(dev);
+                       in_dev = __in_dev_get_rtnl_net(dev);
                        if (!in_dev)
                                return -ENODEV;
 
                        *colon = ':';
 
-                       rcu_read_lock();
-                       in_dev_for_each_ifa_rcu(ifa, in_dev) {
+                       in_dev_for_each_ifa_rtnl_net(net, ifa, in_dev) {
                                if (strcmp(ifa->ifa_label, devname) == 0)
                                        break;
                        }
-                       rcu_read_unlock();
 
                        if (!ifa)
                                return -ENODEV;
@@ -635,7 +633,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
                if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
                        return -EPERM;
 
-               rtnl_lock();
+               rtnl_net_lock(net);
                err = rtentry_to_fib_config(net, cmd, rt, &cfg);
                if (err == 0) {
                        struct fib_table *tb;
@@ -659,7 +657,7 @@ int ip_rt_ioctl(struct net *net, unsigned int cmd, struct rtentry *rt)
                        /* allocated by rtentry_to_fib_config() */
                        kfree(cfg.fc_mx);
                }
-               rtnl_unlock();
+               rtnl_net_unlock(net);
                return err;
        }
        return -EINVAL;