Message ID | 20240422194755.4221-6-kuniyu@amazon.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | arp: Random clean up and RCU conversion for ioctl(SIOCGARP). | expand |
Hi Kuniyuki, kernel test robot noticed the following build warnings: url: https://github.com/intel-lab-lkp/linux/commits/Kuniyuki-Iwashima/arp-Move-ATF_COM-setting-in-arp_req_set/20240423-035458 base: net-next/main patch link: https://lore.kernel.org/r/20240422194755.4221-6-kuniyu%40amazon.com patch subject: [PATCH v1 net-next 5/6] arp: Get dev after calling arp_req_(delete|set|get)(). config: i386-randconfig-141-20240424 (https://download.01.org/0day-ci/archive/20240425/202404251215.QHgck00A-lkp@intel.com/config) compiler: gcc-10 (Ubuntu 10.5.0-1ubuntu1) 10.5.0 If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Reported-by: Dan Carpenter <dan.carpenter@linaro.org> | Closes: https://lore.kernel.org/r/202404251215.QHgck00A-lkp@intel.com/ smatch warnings: net/ipv4/arp.c:1242 arp_req_delete() warn: passing zero to 'PTR_ERR' vim +/PTR_ERR +1242 net/ipv4/arp.c 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1235 static int arp_req_delete(struct net *net, struct arpreq *r) 46479b432989d6 Pavel Emelyanov 2007-12-05 1236 { 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1237 struct net_device *dev; 46479b432989d6 Pavel Emelyanov 2007-12-05 1238 __be32 ip; 46479b432989d6 Pavel Emelyanov 2007-12-05 1239 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1240 dev = arp_req_dev(net, r); 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1241 if (!IS_ERR(dev)) The ! is not supposed to be there. 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 @1242 return PTR_ERR(dev); 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1243 46479b432989d6 Pavel Emelyanov 2007-12-05 1244 if (r->arp_flags & ATF_PUBL) 32e569b7277f13 Pavel Emelyanov 2007-12-16 1245 return arp_req_delete_public(net, r, dev); 46479b432989d6 Pavel Emelyanov 2007-12-05 1246 46479b432989d6 Pavel Emelyanov 2007-12-05 1247 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1248 0c51e12e218f20 Ido Schimmel 2022-02-19 1249 return arp_invalidate(dev, ip, true); ^1da177e4c3f41 Linus Torvalds 2005-04-16 1250 }
From: Dan Carpenter <dan.carpenter@linaro.org> Date: Thu, 25 Apr 2024 08:32:22 +0300 > Hi Kuniyuki, > > kernel test robot noticed the following build warnings: > > url: https://github.com/intel-lab-lkp/linux/commits/Kuniyuki-Iwashima/arp-Move-ATF_COM-setting-in-arp_req_set/20240423-035458 > base: net-next/main > patch link: https://lore.kernel.org/r/20240422194755.4221-6-kuniyu%40amazon.com > patch subject: [PATCH v1 net-next 5/6] arp: Get dev after calling arp_req_(delete|set|get)(). > config: i386-randconfig-141-20240424 (https://download.01.org/0day-ci/archive/20240425/202404251215.QHgck00A-lkp@intel.com/config) > compiler: gcc-10 (Ubuntu 10.5.0-1ubuntu1) 10.5.0 > > If you fix the issue in a separate patch/commit (i.e. not just a new version of > the same patch/commit), kindly add following tags > | Reported-by: kernel test robot <lkp@intel.com> > | Reported-by: Dan Carpenter <dan.carpenter@linaro.org> > | Closes: https://lore.kernel.org/r/202404251215.QHgck00A-lkp@intel.com/ > > smatch warnings: > net/ipv4/arp.c:1242 arp_req_delete() warn: passing zero to 'PTR_ERR' > > vim +/PTR_ERR +1242 net/ipv4/arp.c > > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1235 static int arp_req_delete(struct net *net, struct arpreq *r) > 46479b432989d6 Pavel Emelyanov 2007-12-05 1236 { > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1237 struct net_device *dev; > 46479b432989d6 Pavel Emelyanov 2007-12-05 1238 __be32 ip; > 46479b432989d6 Pavel Emelyanov 2007-12-05 1239 > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1240 dev = arp_req_dev(net, r); > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1241 if (!IS_ERR(dev)) > > The ! is not supposed to be there. Oh, I don't know why I added it :S Will fix it, thank you! > > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 @1242 return PTR_ERR(dev); > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1243 > 46479b432989d6 Pavel Emelyanov 2007-12-05 1244 if (r->arp_flags & ATF_PUBL) > 32e569b7277f13 Pavel Emelyanov 2007-12-16 1245 return arp_req_delete_public(net, r, dev); > 46479b432989d6 Pavel Emelyanov 2007-12-05 1246 > 46479b432989d6 Pavel Emelyanov 2007-12-05 1247 ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; > 8f4429edb1b716 Kuniyuki Iwashima 2024-04-22 1248 > 0c51e12e218f20 Ido Schimmel 2022-02-19 1249 return arp_invalidate(dev, ip, true); > ^1da177e4c3f41 Linus Torvalds 2005-04-16 1250 } > > -- > 0-DAY CI Kernel Test Service > https://github.com/intel/lkp-tests/wiki
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 60f633b24ec8..057aa23bf439 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -1003,12 +1003,36 @@ static int arp_rcv(struct sk_buff *skb, struct net_device *dev, * User level interface (ioctl) */ +static struct net_device *arp_req_dev_by_name(struct net *net, struct arpreq *r) +{ + struct net_device *dev; + + dev = __dev_get_by_name(net, r->arp_dev); + if (!dev) + return ERR_PTR(-ENODEV); + + /* Mmmm... It is wrong... ARPHRD_NETROM == 0 */ + if (!r->arp_ha.sa_family) + r->arp_ha.sa_family = dev->type; + + if ((r->arp_flags & ATF_COM) && r->arp_ha.sa_family != dev->type) + return ERR_PTR(-EINVAL); + + return dev; +} + static struct net_device *arp_req_dev(struct net *net, struct arpreq *r) { struct net_device *dev; struct rtable *rt; __be32 ip; + if (r->arp_dev[0]) + return arp_req_dev_by_name(net, r); + + if (r->arp_flags & ATF_PUBL) + return NULL; + ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; rt = ip_route_output(net, ip, 0, 0, 0, RT_SCOPE_LINK); @@ -1063,21 +1087,20 @@ static int arp_req_set_public(struct net *net, struct arpreq *r, return arp_req_set_proxy(net, dev, 1); } -static int arp_req_set(struct net *net, struct arpreq *r, - struct net_device *dev) +static int arp_req_set(struct net *net, struct arpreq *r) { struct neighbour *neigh; + struct net_device *dev; __be32 ip; int err; + dev = arp_req_dev(net, r); + if (IS_ERR(dev)) + return PTR_ERR(dev); + if (r->arp_flags & ATF_PUBL) return arp_req_set_public(net, r, dev); - if (!dev) { - dev = arp_req_dev(net, r); - if (IS_ERR(dev)) - return PTR_ERR(dev); - } switch (dev->type) { #if IS_ENABLED(CONFIG_FDDI) case ARPHRD_FDDI: @@ -1134,10 +1157,18 @@ static unsigned int arp_state_to_flags(struct neighbour *neigh) * Get an ARP cache entry. */ -static int arp_req_get(struct arpreq *r, struct net_device *dev) +static int arp_req_get(struct net *net, struct arpreq *r) { __be32 ip = ((struct sockaddr_in *) &r->arp_pa)->sin_addr.s_addr; struct neighbour *neigh; + struct net_device *dev; + + if (!r->arp_dev[0]) + return -ENODEV; + + dev = arp_req_dev_by_name(net, r); + if (IS_ERR(dev)) + return PTR_ERR(dev); neigh = neigh_lookup(&arp_tbl, &ip, dev); if (!neigh) @@ -1201,20 +1232,20 @@ static int arp_req_delete_public(struct net *net, struct arpreq *r, return arp_req_set_proxy(net, dev, 0); } -static int arp_req_delete(struct net *net, struct arpreq *r, - struct net_device *dev) +static int arp_req_delete(struct net *net, struct arpreq *r) { + struct net_device *dev; __be32 ip; + dev = arp_req_dev(net, r); + if (!IS_ERR(dev)) + return PTR_ERR(dev); + if (r->arp_flags & ATF_PUBL) return arp_req_delete_public(net, r, dev); ip = ((struct sockaddr_in *)&r->arp_pa)->sin_addr.s_addr; - if (!dev) { - dev = arp_req_dev(net, r); - if (IS_ERR(dev)) - return PTR_ERR(dev); - } + return arp_invalidate(dev, ip, true); } @@ -1224,7 +1255,6 @@ static int arp_req_delete(struct net *net, struct arpreq *r, int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) { - struct net_device *dev = NULL; struct arpreq r; __be32 *netmask; int err; @@ -1258,35 +1288,19 @@ int arp_ioctl(struct net *net, unsigned int cmd, void __user *arg) return -EINVAL; rtnl_lock(); - if (r.arp_dev[0]) { - err = -ENODEV; - dev = __dev_get_by_name(net, r.arp_dev); - if (!dev) - goto out; - - /* Mmmm... It is wrong... ARPHRD_NETROM==0 */ - if (!r.arp_ha.sa_family) - r.arp_ha.sa_family = dev->type; - err = -EINVAL; - if ((r.arp_flags & ATF_COM) && r.arp_ha.sa_family != dev->type) - goto out; - } else if (cmd == SIOCGARP) { - err = -ENODEV; - goto out; - } switch (cmd) { case SIOCDARP: - err = arp_req_delete(net, &r, dev); + err = arp_req_delete(net, &r); break; case SIOCSARP: - err = arp_req_set(net, &r, dev); + err = arp_req_set(net, &r); break; case SIOCGARP: - err = arp_req_get(&r, dev); + err = arp_req_get(net, &r); break; } -out: + rtnl_unlock(); if (cmd == SIOCGARP && !err && copy_to_user(arg, &r, sizeof(r))) err = -EFAULT;
arp_ioctl() holds rtnl_lock() first regardless of cmd (SIOCDARP, SIOCSARP, and SIOCGARP) to get net_device by __dev_get_by_name(). In the SIOCGARP path, arp_req_get() calls neigh_lookup(), which looks up a neighbour entry under RCU. We will extend the RCU section not to take rtnl_lock() and instead use dev_get_by_name_rcu() for SIOCGARP. As a preparation, let's move __dev_get_by_name() into another function and call it from arp_req_delete(), arp_req_set(), and arp_req_get(). Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> --- net/ipv4/arp.c | 86 +++++++++++++++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 36 deletions(-)