LCOV - code coverage report
Current view: top level - net/core - dev_ioctl.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 61 214 28.5 %
Date: 2021-04-22 12:43:58 Functions: 4 8 50.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/kmod.h>
       3             : #include <linux/netdevice.h>
       4             : #include <linux/etherdevice.h>
       5             : #include <linux/rtnetlink.h>
       6             : #include <linux/net_tstamp.h>
       7             : #include <linux/wireless.h>
       8             : #include <net/dsa.h>
       9             : #include <net/wext.h>
      10             : 
      11             : /*
      12             :  *      Map an interface index to its name (SIOCGIFNAME)
      13             :  */
      14             : 
      15             : /*
      16             :  *      We need this ioctl for efficient implementation of the
      17             :  *      if_indextoname() function required by the IPv6 API.  Without
      18             :  *      it, we would have to search all the interfaces to find a
      19             :  *      match.  --pb
      20             :  */
      21             : 
      22           3 : static int dev_ifname(struct net *net, struct ifreq *ifr)
      23             : {
      24           3 :         ifr->ifr_name[IFNAMSIZ-1] = 0;
      25           3 :         return netdev_get_name(net, ifr->ifr_name, ifr->ifr_ifindex);
      26             : }
      27             : 
      28             : static gifconf_func_t *gifconf_list[NPROTO];
      29             : 
      30             : /**
      31             :  *      register_gifconf        -       register a SIOCGIF handler
      32             :  *      @family: Address family
      33             :  *      @gifconf: Function handler
      34             :  *
      35             :  *      Register protocol dependent address dumping routines. The handler
      36             :  *      that is passed must not be freed or reused until it has been replaced
      37             :  *      by another handler.
      38             :  */
      39           1 : int register_gifconf(unsigned int family, gifconf_func_t *gifconf)
      40             : {
      41           1 :         if (family >= NPROTO)
      42             :                 return -EINVAL;
      43           1 :         gifconf_list[family] = gifconf;
      44           1 :         return 0;
      45             : }
      46             : EXPORT_SYMBOL(register_gifconf);
      47             : 
      48             : /*
      49             :  *      Perform a SIOCGIFCONF call. This structure will change
      50             :  *      size eventually, and there is nothing I can do about it.
      51             :  *      Thus we will need a 'compatibility mode'.
      52             :  */
      53             : 
      54           0 : int dev_ifconf(struct net *net, struct ifconf *ifc, int size)
      55             : {
      56           0 :         struct net_device *dev;
      57           0 :         char __user *pos;
      58           0 :         int len;
      59           0 :         int total;
      60           0 :         int i;
      61             : 
      62             :         /*
      63             :          *      Fetch the caller's info block.
      64             :          */
      65             : 
      66           0 :         pos = ifc->ifc_buf;
      67           0 :         len = ifc->ifc_len;
      68             : 
      69             :         /*
      70             :          *      Loop over the interfaces, and write an info block for each.
      71             :          */
      72             : 
      73           0 :         total = 0;
      74           0 :         for_each_netdev(net, dev) {
      75           0 :                 for (i = 0; i < NPROTO; i++) {
      76           0 :                         if (gifconf_list[i]) {
      77           0 :                                 int done;
      78           0 :                                 if (!pos)
      79           0 :                                         done = gifconf_list[i](dev, NULL, 0, size);
      80             :                                 else
      81           0 :                                         done = gifconf_list[i](dev, pos + total,
      82             :                                                                len - total, size);
      83           0 :                                 if (done < 0)
      84             :                                         return -EFAULT;
      85           0 :                                 total += done;
      86             :                         }
      87             :                 }
      88             :         }
      89             : 
      90             :         /*
      91             :          *      All done.  Write the updated control block back to the caller.
      92             :          */
      93           0 :         ifc->ifc_len = total;
      94             : 
      95             :         /*
      96             :          *      Both BSD and Solaris return 0 here, so we do too.
      97             :          */
      98           0 :         return 0;
      99             : }
     100             : 
     101             : /*
     102             :  *      Perform the SIOCxIFxxx calls, inside rcu_read_lock()
     103             :  */
     104           9 : static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd)
     105             : {
     106           9 :         int err;
     107           9 :         struct net_device *dev = dev_get_by_name_rcu(net, ifr->ifr_name);
     108             : 
     109           9 :         if (!dev)
     110             :                 return -ENODEV;
     111             : 
     112           8 :         switch (cmd) {
     113           2 :         case SIOCGIFFLAGS:      /* Get interface flags */
     114           2 :                 ifr->ifr_flags = (short) dev_get_flags(dev);
     115           2 :                 return 0;
     116             : 
     117           0 :         case SIOCGIFMETRIC:     /* Get the metric on the interface
     118             :                                    (currently unused) */
     119           0 :                 ifr->ifr_metric = 0;
     120           0 :                 return 0;
     121             : 
     122           0 :         case SIOCGIFMTU:        /* Get the MTU of a device */
     123           0 :                 ifr->ifr_mtu = dev->mtu;
     124           0 :                 return 0;
     125             : 
     126             :         case SIOCGIFSLAVE:
     127             :                 err = -EINVAL;
     128             :                 break;
     129             : 
     130           0 :         case SIOCGIFMAP:
     131           0 :                 ifr->ifr_map.mem_start = dev->mem_start;
     132           0 :                 ifr->ifr_map.mem_end   = dev->mem_end;
     133           0 :                 ifr->ifr_map.base_addr = dev->base_addr;
     134           0 :                 ifr->ifr_map.irq       = dev->irq;
     135           0 :                 ifr->ifr_map.dma       = dev->dma;
     136           0 :                 ifr->ifr_map.port      = dev->if_port;
     137           0 :                 return 0;
     138             : 
     139           6 :         case SIOCGIFINDEX:
     140           6 :                 ifr->ifr_ifindex = dev->ifindex;
     141           6 :                 return 0;
     142             : 
     143           0 :         case SIOCGIFTXQLEN:
     144           0 :                 ifr->ifr_qlen = dev->tx_queue_len;
     145           0 :                 return 0;
     146             : 
     147             :         default:
     148             :                 /* dev_ioctl() should ensure this case
     149             :                  * is never reached
     150             :                  */
     151           0 :                 WARN_ON(1);
     152           0 :                 err = -ENOTTY;
     153           0 :                 break;
     154             : 
     155             :         }
     156             :         return err;
     157             : }
     158             : 
     159           0 : static int net_hwtstamp_validate(struct ifreq *ifr)
     160             : {
     161           0 :         struct hwtstamp_config cfg;
     162           0 :         enum hwtstamp_tx_types tx_type;
     163           0 :         enum hwtstamp_rx_filters rx_filter;
     164           0 :         int tx_type_valid = 0;
     165           0 :         int rx_filter_valid = 0;
     166             : 
     167           0 :         if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
     168             :                 return -EFAULT;
     169             : 
     170           0 :         if (cfg.flags) /* reserved for future extensions */
     171             :                 return -EINVAL;
     172             : 
     173           0 :         tx_type = cfg.tx_type;
     174           0 :         rx_filter = cfg.rx_filter;
     175             : 
     176           0 :         switch (tx_type) {
     177           0 :         case HWTSTAMP_TX_OFF:
     178             :         case HWTSTAMP_TX_ON:
     179             :         case HWTSTAMP_TX_ONESTEP_SYNC:
     180             :         case HWTSTAMP_TX_ONESTEP_P2P:
     181           0 :                 tx_type_valid = 1;
     182           0 :                 break;
     183             :         case __HWTSTAMP_TX_CNT:
     184             :                 /* not a real value */
     185             :                 break;
     186             :         }
     187             : 
     188           0 :         switch (rx_filter) {
     189           0 :         case HWTSTAMP_FILTER_NONE:
     190             :         case HWTSTAMP_FILTER_ALL:
     191             :         case HWTSTAMP_FILTER_SOME:
     192             :         case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
     193             :         case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
     194             :         case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
     195             :         case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
     196             :         case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
     197             :         case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
     198             :         case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
     199             :         case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
     200             :         case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
     201             :         case HWTSTAMP_FILTER_PTP_V2_EVENT:
     202             :         case HWTSTAMP_FILTER_PTP_V2_SYNC:
     203             :         case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
     204             :         case HWTSTAMP_FILTER_NTP_ALL:
     205           0 :                 rx_filter_valid = 1;
     206           0 :                 break;
     207             :         case __HWTSTAMP_FILTER_CNT:
     208             :                 /* not a real value */
     209             :                 break;
     210             :         }
     211             : 
     212           0 :         if (!tx_type_valid || !rx_filter_valid)
     213           0 :                 return -ERANGE;
     214             : 
     215             :         return 0;
     216             : }
     217             : 
     218           0 : static int dev_do_ioctl(struct net_device *dev,
     219             :                         struct ifreq *ifr, unsigned int cmd)
     220             : {
     221           0 :         const struct net_device_ops *ops = dev->netdev_ops;
     222           0 :         int err;
     223             : 
     224           0 :         err = dsa_ndo_do_ioctl(dev, ifr, cmd);
     225           0 :         if (err == 0 || err != -EOPNOTSUPP)
     226             :                 return err;
     227             : 
     228           0 :         if (ops->ndo_do_ioctl) {
     229           0 :                 if (netif_device_present(dev))
     230           0 :                         err = ops->ndo_do_ioctl(dev, ifr, cmd);
     231             :                 else
     232             :                         err = -ENODEV;
     233             :         }
     234             : 
     235           0 :         return err;
     236             : }
     237             : 
     238             : /*
     239             :  *      Perform the SIOCxIFxxx calls, inside rtnl_lock()
     240             :  */
     241           0 : static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
     242             : {
     243           0 :         int err;
     244           0 :         struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
     245           0 :         const struct net_device_ops *ops;
     246             : 
     247           0 :         if (!dev)
     248             :                 return -ENODEV;
     249             : 
     250           0 :         ops = dev->netdev_ops;
     251             : 
     252           0 :         switch (cmd) {
     253           0 :         case SIOCSIFFLAGS:      /* Set interface flags */
     254           0 :                 return dev_change_flags(dev, ifr->ifr_flags, NULL);
     255             : 
     256             :         case SIOCSIFMETRIC:     /* Set the metric on the interface
     257             :                                    (currently unused) */
     258             :                 return -EOPNOTSUPP;
     259             : 
     260           0 :         case SIOCSIFMTU:        /* Set the MTU of a device */
     261           0 :                 return dev_set_mtu(dev, ifr->ifr_mtu);
     262             : 
     263           0 :         case SIOCSIFHWADDR:
     264           0 :                 if (dev->addr_len > sizeof(struct sockaddr))
     265             :                         return -EINVAL;
     266           0 :                 return dev_set_mac_address_user(dev, &ifr->ifr_hwaddr, NULL);
     267             : 
     268           0 :         case SIOCSIFHWBROADCAST:
     269           0 :                 if (ifr->ifr_hwaddr.sa_family != dev->type)
     270             :                         return -EINVAL;
     271           0 :                 memcpy(dev->broadcast, ifr->ifr_hwaddr.sa_data,
     272           0 :                        min(sizeof(ifr->ifr_hwaddr.sa_data),
     273             :                            (size_t)dev->addr_len));
     274           0 :                 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
     275           0 :                 return 0;
     276             : 
     277           0 :         case SIOCSIFMAP:
     278           0 :                 if (ops->ndo_set_config) {
     279           0 :                         if (!netif_device_present(dev))
     280             :                                 return -ENODEV;
     281           0 :                         return ops->ndo_set_config(dev, &ifr->ifr_map);
     282             :                 }
     283             :                 return -EOPNOTSUPP;
     284             : 
     285           0 :         case SIOCADDMULTI:
     286           0 :                 if (!ops->ndo_set_rx_mode ||
     287           0 :                     ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
     288             :                         return -EINVAL;
     289           0 :                 if (!netif_device_present(dev))
     290             :                         return -ENODEV;
     291           0 :                 return dev_mc_add_global(dev, ifr->ifr_hwaddr.sa_data);
     292             : 
     293           0 :         case SIOCDELMULTI:
     294           0 :                 if (!ops->ndo_set_rx_mode ||
     295           0 :                     ifr->ifr_hwaddr.sa_family != AF_UNSPEC)
     296             :                         return -EINVAL;
     297           0 :                 if (!netif_device_present(dev))
     298             :                         return -ENODEV;
     299           0 :                 return dev_mc_del_global(dev, ifr->ifr_hwaddr.sa_data);
     300             : 
     301           0 :         case SIOCSIFTXQLEN:
     302           0 :                 if (ifr->ifr_qlen < 0)
     303             :                         return -EINVAL;
     304           0 :                 return dev_change_tx_queue_len(dev, ifr->ifr_qlen);
     305             : 
     306           0 :         case SIOCSIFNAME:
     307           0 :                 ifr->ifr_newname[IFNAMSIZ-1] = '\0';
     308           0 :                 return dev_change_name(dev, ifr->ifr_newname);
     309             : 
     310           0 :         case SIOCSHWTSTAMP:
     311           0 :                 err = net_hwtstamp_validate(ifr);
     312           0 :                 if (err)
     313             :                         return err;
     314           0 :                 fallthrough;
     315             : 
     316             :         /*
     317             :          *      Unknown or private ioctl
     318             :          */
     319             :         default:
     320           0 :                 if ((cmd >= SIOCDEVPRIVATE &&
     321           0 :                     cmd <= SIOCDEVPRIVATE + 15) ||
     322           0 :                     cmd == SIOCBONDENSLAVE ||
     323           0 :                     cmd == SIOCBONDRELEASE ||
     324             :                     cmd == SIOCBONDSETHWADDR ||
     325           0 :                     cmd == SIOCBONDSLAVEINFOQUERY ||
     326             :                     cmd == SIOCBONDINFOQUERY ||
     327           0 :                     cmd == SIOCBONDCHANGEACTIVE ||
     328           0 :                     cmd == SIOCGMIIPHY ||
     329           0 :                     cmd == SIOCGMIIREG ||
     330             :                     cmd == SIOCSMIIREG ||
     331           0 :                     cmd == SIOCBRADDIF ||
     332             :                     cmd == SIOCBRDELIF ||
     333           0 :                     cmd == SIOCSHWTSTAMP ||
     334           0 :                     cmd == SIOCGHWTSTAMP ||
     335             :                     cmd == SIOCWANDEV) {
     336           0 :                         err = dev_do_ioctl(dev, ifr, cmd);
     337             :                 } else
     338             :                         err = -EINVAL;
     339             : 
     340             :         }
     341             :         return err;
     342             : }
     343             : 
     344             : /**
     345             :  *      dev_load        - load a network module
     346             :  *      @net: the applicable net namespace
     347             :  *      @name: name of interface
     348             :  *
     349             :  *      If a network interface is not present and the process has suitable
     350             :  *      privileges this function loads the module. If module loading is not
     351             :  *      available in this kernel then it becomes a nop.
     352             :  */
     353             : 
     354          18 : void dev_load(struct net *net, const char *name)
     355             : {
     356          18 :         struct net_device *dev;
     357          18 :         int no_module;
     358             : 
     359          18 :         rcu_read_lock();
     360          18 :         dev = dev_get_by_name_rcu(net, name);
     361          18 :         rcu_read_unlock();
     362             : 
     363          18 :         no_module = !dev;
     364          18 :         if (no_module && capable(CAP_NET_ADMIN))
     365           1 :                 no_module = request_module("netdev-%s", name);
     366          18 :         if (no_module && capable(CAP_SYS_MODULE))
     367          18 :                 request_module("%s", name);
     368          18 : }
     369             : EXPORT_SYMBOL(dev_load);
     370             : 
     371             : /*
     372             :  *      This function handles all "interface"-type I/O control requests. The actual
     373             :  *      'doing' part of this is dev_ifsioc above.
     374             :  */
     375             : 
     376             : /**
     377             :  *      dev_ioctl       -       network device ioctl
     378             :  *      @net: the applicable net namespace
     379             :  *      @cmd: command to issue
     380             :  *      @ifr: pointer to a struct ifreq in user space
     381             :  *      @need_copyout: whether or not copy_to_user() should be called
     382             :  *
     383             :  *      Issue ioctl functions to devices. This is normally called by the
     384             :  *      user space syscall interfaces but can sometimes be useful for
     385             :  *      other purposes. The return value is the return from the syscall if
     386             :  *      positive or a negative errno code on error.
     387             :  */
     388             : 
     389          66 : int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout)
     390             : {
     391          66 :         int ret;
     392          66 :         char *colon;
     393             : 
     394          66 :         if (need_copyout)
     395          66 :                 *need_copyout = true;
     396          66 :         if (cmd == SIOCGIFNAME)
     397           3 :                 return dev_ifname(net, ifr);
     398             : 
     399          63 :         ifr->ifr_name[IFNAMSIZ-1] = 0;
     400             : 
     401          63 :         colon = strchr(ifr->ifr_name, ':');
     402          63 :         if (colon)
     403           0 :                 *colon = 0;
     404             : 
     405             :         /*
     406             :          *      See which interface the caller is talking about.
     407             :          */
     408             : 
     409          63 :         switch (cmd) {
     410           1 :         case SIOCGIFHWADDR:
     411           1 :                 dev_load(net, ifr->ifr_name);
     412           1 :                 ret = dev_get_mac_address(&ifr->ifr_hwaddr, net, ifr->ifr_name);
     413           1 :                 if (colon)
     414           0 :                         *colon = ':';
     415             :                 return ret;
     416             :         /*
     417             :          *      These ioctl calls:
     418             :          *      - can be done by all.
     419             :          *      - atomic and do not require locking.
     420             :          *      - return a value
     421             :          */
     422           9 :         case SIOCGIFFLAGS:
     423             :         case SIOCGIFMETRIC:
     424             :         case SIOCGIFMTU:
     425             :         case SIOCGIFSLAVE:
     426             :         case SIOCGIFMAP:
     427             :         case SIOCGIFINDEX:
     428             :         case SIOCGIFTXQLEN:
     429           9 :                 dev_load(net, ifr->ifr_name);
     430           9 :                 rcu_read_lock();
     431           9 :                 ret = dev_ifsioc_locked(net, ifr, cmd);
     432           9 :                 rcu_read_unlock();
     433           9 :                 if (colon)
     434           0 :                         *colon = ':';
     435             :                 return ret;
     436             : 
     437           8 :         case SIOCETHTOOL:
     438           8 :                 dev_load(net, ifr->ifr_name);
     439           8 :                 rtnl_lock();
     440           8 :                 ret = dev_ethtool(net, ifr);
     441           8 :                 rtnl_unlock();
     442           8 :                 if (colon)
     443           0 :                         *colon = ':';
     444             :                 return ret;
     445             : 
     446             :         /*
     447             :          *      These ioctl calls:
     448             :          *      - require superuser power.
     449             :          *      - require strict serialization.
     450             :          *      - return a value
     451             :          */
     452           0 :         case SIOCGMIIPHY:
     453             :         case SIOCGMIIREG:
     454             :         case SIOCSIFNAME:
     455           0 :                 dev_load(net, ifr->ifr_name);
     456           0 :                 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
     457             :                         return -EPERM;
     458           0 :                 rtnl_lock();
     459           0 :                 ret = dev_ifsioc(net, ifr, cmd);
     460           0 :                 rtnl_unlock();
     461           0 :                 if (colon)
     462           0 :                         *colon = ':';
     463             :                 return ret;
     464             : 
     465             :         /*
     466             :          *      These ioctl calls:
     467             :          *      - require superuser power.
     468             :          *      - require strict serialization.
     469             :          *      - do not return a value
     470             :          */
     471           0 :         case SIOCSIFMAP:
     472             :         case SIOCSIFTXQLEN:
     473           0 :                 if (!capable(CAP_NET_ADMIN))
     474             :                         return -EPERM;
     475           0 :                 fallthrough;
     476             :         /*
     477             :          *      These ioctl calls:
     478             :          *      - require local superuser power.
     479             :          *      - require strict serialization.
     480             :          *      - do not return a value
     481             :          */
     482             :         case SIOCSIFFLAGS:
     483             :         case SIOCSIFMETRIC:
     484             :         case SIOCSIFMTU:
     485             :         case SIOCSIFHWADDR:
     486             :         case SIOCSIFSLAVE:
     487             :         case SIOCADDMULTI:
     488             :         case SIOCDELMULTI:
     489             :         case SIOCSIFHWBROADCAST:
     490             :         case SIOCSMIIREG:
     491             :         case SIOCBONDENSLAVE:
     492             :         case SIOCBONDRELEASE:
     493             :         case SIOCBONDSETHWADDR:
     494             :         case SIOCBONDCHANGEACTIVE:
     495             :         case SIOCBRADDIF:
     496             :         case SIOCBRDELIF:
     497             :         case SIOCSHWTSTAMP:
     498           0 :                 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
     499             :                         return -EPERM;
     500           0 :                 fallthrough;
     501             :         case SIOCBONDSLAVEINFOQUERY:
     502             :         case SIOCBONDINFOQUERY:
     503           0 :                 dev_load(net, ifr->ifr_name);
     504           0 :                 rtnl_lock();
     505           0 :                 ret = dev_ifsioc(net, ifr, cmd);
     506           0 :                 rtnl_unlock();
     507           0 :                 if (need_copyout)
     508           0 :                         *need_copyout = false;
     509             :                 return ret;
     510             : 
     511             :         case SIOCGIFMEM:
     512             :                 /* Get the per device memory space. We can add this but
     513             :                  * currently do not support it */
     514             :         case SIOCSIFMEM:
     515             :                 /* Set the per device memory buffer space.
     516             :                  * Not applicable in our case */
     517             :         case SIOCSIFLINK:
     518             :                 return -ENOTTY;
     519             : 
     520             :         /*
     521             :          *      Unknown or private ioctl.
     522             :          */
     523          45 :         default:
     524          45 :                 if (cmd == SIOCWANDEV ||
     525          45 :                     cmd == SIOCGHWTSTAMP ||
     526          45 :                     (cmd >= SIOCDEVPRIVATE &&
     527             :                      cmd <= SIOCDEVPRIVATE + 15)) {
     528           0 :                         dev_load(net, ifr->ifr_name);
     529           0 :                         rtnl_lock();
     530           0 :                         ret = dev_ifsioc(net, ifr, cmd);
     531           0 :                         rtnl_unlock();
     532           0 :                         return ret;
     533             :                 }
     534             :                 return -ENOTTY;
     535             :         }
     536             : }

Generated by: LCOV version 1.14