Commit a937e1e4 authored by Stephen Hemminger's avatar Stephen Hemminger

[NET]: Add SIOCSIGNAME wildcarding and name validation, with help from Jean Tourrilhes.

parent 424e8db5
......@@ -620,6 +620,21 @@ struct net_device *__dev_get_by_flags(unsigned short if_flags, unsigned short ma
return NULL;
}
/**
* dev_valid_name - check if name is okay for network device
* @name: name string
*
* Network device names need to be valid file names to
* to allow sysfs to work
*/
int dev_valid_name(const char *name)
{
return !(*name == '\0'
|| !strcmp(name, ".")
|| !strcmp(name, "..")
|| strchr(name, '/'));
}
/**
* dev_alloc_name - allocate a name for a device
* @dev: device
......@@ -660,6 +675,41 @@ int dev_alloc_name(struct net_device *dev, const char *name)
return -ENFILE; /* Over 100 of the things .. bail out! */
}
/**
* dev_change_name - change name of a device
* @dev: device
* @name: name (or format string) must be at least IFNAMSIZ
*
* Change name of a device, can pass format strings "eth%d".
* for wildcarding.
*/
int dev_change_name(struct net_device *dev, char *newname)
{
ASSERT_RTNL();
if (dev->flags & IFF_UP)
return -EBUSY;
if (!dev_valid_name(newname))
return -EINVAL;
if (strchr(newname, '%')) {
int err = dev_alloc_name(dev, newname);
if (err)
return err;
strcpy(newname, dev->name);
}
else if (__dev_get_by_name(newname))
return -EEXIST;
else
strlcpy(dev->name, newname, IFNAMSIZ);
class_device_rename(&dev->class_dev, dev->name);
notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
return 0;
}
/**
* dev_alloc - allocate a network device and name
* @name: name format string
......@@ -2341,20 +2391,8 @@ static int dev_ifsioc(struct ifreq *ifr, unsigned int cmd)
return 0;
case SIOCSIFNAME:
if (dev->flags & IFF_UP)
return -EBUSY;
ifr->ifr_newname[IFNAMSIZ-1] = '\0';
if (__dev_get_by_name(ifr->ifr_newname))
return -EEXIST;
err = class_device_rename(&dev->class_dev,
ifr->ifr_newname);
if (!err) {
strlcpy(dev->name, ifr->ifr_newname, IFNAMSIZ);
notifier_call_chain(&netdev_chain,
NETDEV_CHANGENAME, dev);
}
return err;
return dev_change_name(dev, ifr->ifr_newname);
/*
* Unknown or private ioctl
......@@ -2487,6 +2525,7 @@ int dev_ioctl(unsigned int cmd, void *arg)
*/
case SIOCGMIIPHY:
case SIOCGMIIREG:
case SIOCSIFNAME:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
dev_load(ifr.ifr_name);
......@@ -2518,7 +2557,6 @@ int dev_ioctl(unsigned int cmd, void *arg)
case SIOCDELMULTI:
case SIOCSIFHWBROADCAST:
case SIOCSIFTXQLEN:
case SIOCSIFNAME:
case SIOCSMIIREG:
case SIOCBONDENSLAVE:
case SIOCBONDRELEASE:
......@@ -2668,6 +2706,11 @@ int register_netdevice(struct net_device *dev)
goto out_err;
}
}
if (!dev_valid_name(dev->name)) {
ret = -EINVAL;
goto out_err;
}
dev->ifindex = dev_new_index();
if (dev->iflink == -1)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment