LCOV - code coverage report
Current view: top level - net/core - dev_ioctl.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 54 187 28.9 %
Date: 2022-03-28 15:32:58 Functions: 4 6 66.7 %
Branches: 22 123 17.9 %

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

Generated by: LCOV version 1.14