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)
committerJakub Kicinski <kuba@kernel.org>
Mon, 3 Mar 2025 23:04:11 +0000 (15:04 -0800)
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>
net/ipv4/fib_frontend.c

index c48ed369b1796abd5de94838e8c272b163148aec..a76dacc3e577a53fe045787ec9eaf002a311720b 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;