LCOV - code coverage report
Current view: top level - net/core - dev_ioctl.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 60 174 34.5 %
Date: 2014-04-07 Functions: 4 8 50.0 %
Branches: 33 156 21.2 %

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

Generated by: LCOV version 1.9