Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
authorJakub Kicinski <kuba@kernel.org>
Tue, 31 Aug 2021 16:06:04 +0000 (09:06 -0700)
committerJakub Kicinski <kuba@kernel.org>
Tue, 31 Aug 2021 16:06:04 +0000 (09:06 -0700)
include/linux/netdevice.h
net/socket.c

  d0efb16294d1 ("net: don't unconditionally copy_from_user a struct ifreq for socket ioctls")

  876f0bf9d0d5 ("net: socket: simplify dev_ifconf handling")
  29c4964822aa ("net: socket: rework compat_ifreq_ioctl()")

Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1  2 
drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/lag.c
drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
drivers/net/phy/marvell10g.c
include/linux/netdevice.h
net/socket.c

@@@ -305,13 -277,8 +305,14 @@@ static int mlx5_deactivate_lag(struct m
        int err;
  
        ldev->flags &= ~MLX5_LAG_MODE_FLAGS;
+       mlx5_lag_mp_reset(ldev);
  
 +      if (ldev->shared_fdb) {
 +              mlx5_eswitch_offloads_destroy_single_fdb(ldev->pf[MLX5_LAG_P1].dev->priv.eswitch,
 +                                                       ldev->pf[MLX5_LAG_P2].dev->priv.eswitch);
 +              ldev->shared_fdb = false;
 +      }
 +
        MLX5_SET(destroy_lag_in, in, opcode, MLX5_CMD_OP_DESTROY_LAG);
        err = mlx5_cmd_exec_in(dev0, destroy_lag, in);
        if (err) {
Simple merge
@@@ -4027,12 -4012,14 +4027,16 @@@ int netdev_rx_handler_register(struct n
  void netdev_rx_handler_unregister(struct net_device *dev);
  
  bool dev_valid_name(const char *name);
+ static inline bool is_socket_ioctl_cmd(unsigned int cmd)
+ {
+       return _IOC_TYPE(cmd) == SOCK_IOC_TYPE;
+ }
 +int get_user_ifreq(struct ifreq *ifr, void __user **ifrdata, void __user *arg);
 +int put_user_ifreq(struct ifreq *ifr, void __user *arg);
  int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr,
 -              bool *need_copyout);
 -int dev_ifconf(struct net *net, struct ifconf *, int);
 -int dev_ethtool(struct net *net, struct ifreq *);
 +              void __user *data, bool *need_copyout);
 +int dev_ifconf(struct net *net, struct ifconf __user *ifc);
 +int dev_ethtool(struct net *net, struct ifreq *ifr, void __user *userdata);
  unsigned int dev_get_flags(const struct net_device *);
  int __dev_change_flags(struct net_device *dev, unsigned int flags,
                       struct netlink_ext_ack *extack);
diff --cc net/socket.c
@@@ -1124,13 -1100,27 +1124,16 @@@ static long sock_do_ioctl(struct net *n
        if (err != -ENOIOCTLCMD)
                return err;
  
 -      if (cmd == SIOCGIFCONF) {
 -              struct ifconf ifc;
 -              if (copy_from_user(&ifc, argp, sizeof(struct ifconf)))
 -                      return -EFAULT;
 -              rtnl_lock();
 -              err = dev_ifconf(net, &ifc, sizeof(struct ifreq));
 -              rtnl_unlock();
 -              if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf)))
 -                      err = -EFAULT;
 -      } else if (is_socket_ioctl_cmd(cmd)) {
 -              struct ifreq ifr;
 -              bool need_copyout;
 -              if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
++      if (!is_socket_ioctl_cmd(cmd))
++              return -ENOTTY;
++
 +      if (get_user_ifreq(&ifr, &data, argp))
 +              return -EFAULT;
 +      err = dev_ioctl(net, cmd, &ifr, data, &need_copyout);
 +      if (!err && need_copyout)
 +              if (put_user_ifreq(&ifr, argp))
                        return -EFAULT;
 -              err = dev_ioctl(net, cmd, &ifr, &need_copyout);
 -              if (!err && need_copyout)
 -                      if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
 -                              return -EFAULT;
 -      } else {
 -              err = -ENOTTY;
 -      }
 +
        return err;
  }
  
@@@ -3216,13 -3306,99 +3219,15 @@@ static int compat_ifr_data_ioctl(struc
                                 struct compat_ifreq __user *u_ifreq32)
  {
        struct ifreq ifreq;
 -      u32 data32;
 +      void __user *data;
  
 -      if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ))
 -              return -EFAULT;
 -      if (get_user(data32, &u_ifreq32->ifr_data))
 -              return -EFAULT;
 -      ifreq.ifr_data = compat_ptr(data32);
 -
 -      return dev_ioctl(net, cmd, &ifreq, NULL);
 -}
 -
 -static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
 -                            unsigned int cmd,
 -                            struct compat_ifreq __user *uifr32)
 -{
 -      struct ifreq __user *uifr;
 -      int err;
 -
 -      /* Handle the fact that while struct ifreq has the same *layout* on
 -       * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
 -       * which are handled elsewhere, it still has different *size* due to
 -       * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
 -       * resulting in struct ifreq being 32 and 40 bytes respectively).
 -       * As a result, if the struct happens to be at the end of a page and
 -       * the next page isn't readable/writable, we get a fault. To prevent
 -       * that, copy back and forth to the full size.
 -       */
 -
 -      uifr = compat_alloc_user_space(sizeof(*uifr));
 -      if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
 -              return -EFAULT;
 -
 -      err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
 -
 -      if (!err) {
 -              switch (cmd) {
 -              case SIOCGIFFLAGS:
 -              case SIOCGIFMETRIC:
 -              case SIOCGIFMTU:
 -              case SIOCGIFMEM:
 -              case SIOCGIFHWADDR:
 -              case SIOCGIFINDEX:
 -              case SIOCGIFADDR:
 -              case SIOCGIFBRDADDR:
 -              case SIOCGIFDSTADDR:
 -              case SIOCGIFNETMASK:
 -              case SIOCGIFPFLAGS:
 -              case SIOCGIFTXQLEN:
 -              case SIOCGMIIPHY:
 -              case SIOCGMIIREG:
 -              case SIOCGIFNAME:
 -                      if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
 -                              err = -EFAULT;
 -                      break;
 -              }
 -      }
 -      return err;
 -}
 -
 -static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
 -                      struct compat_ifreq __user *uifr32)
 -{
 -      struct ifreq ifr;
 -      struct compat_ifmap __user *uifmap32;
 -      int err;
 -
 -      uifmap32 = &uifr32->ifr_ifru.ifru_map;
 -      err = copy_from_user(&ifr, uifr32, sizeof(ifr.ifr_name));
 -      err |= get_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
 -      err |= get_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
 -      err |= get_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
 -      err |= get_user(ifr.ifr_map.irq, &uifmap32->irq);
 -      err |= get_user(ifr.ifr_map.dma, &uifmap32->dma);
 -      err |= get_user(ifr.ifr_map.port, &uifmap32->port);
 -      if (err)
+       if (!is_socket_ioctl_cmd(cmd))
+               return -ENOTTY;
 +      if (get_user_ifreq(&ifreq, &data, u_ifreq32))
                return -EFAULT;
 +      ifreq.ifr_data = data;
  
 -      err = dev_ioctl(net, cmd, &ifr, NULL);
 -
 -      if (cmd == SIOCGIFMAP && !err) {
 -              err = copy_to_user(uifr32, &ifr, sizeof(ifr.ifr_name));
 -              err |= put_user(ifr.ifr_map.mem_start, &uifmap32->mem_start);
 -              err |= put_user(ifr.ifr_map.mem_end, &uifmap32->mem_end);
 -              err |= put_user(ifr.ifr_map.base_addr, &uifmap32->base_addr);
 -              err |= put_user(ifr.ifr_map.irq, &uifmap32->irq);
 -              err |= put_user(ifr.ifr_map.dma, &uifmap32->dma);
 -              err |= put_user(ifr.ifr_map.port, &uifmap32->port);
 -              if (err)
 -                      err = -EFAULT;
 -      }
 -      return err;
 +      return dev_ioctl(net, cmd, &ifreq, data, NULL);
  }
  
  /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE