diff -Nru a/net/core/dev.c b/net/core/dev.c --- a/net/core/dev.c Tue Jan 13 14:20:51 2004 +++ b/net/core/dev.c Tue Jan 13 14:20:51 2004 @@ -621,6 +621,21 @@ } /** + * 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 * @name: name format string @@ -660,6 +675,41 @@ 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 @@ -2359,20 +2409,8 @@ 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 @@ -2505,6 +2543,7 @@ */ case SIOCGMIIPHY: case SIOCGMIIREG: + case SIOCSIFNAME: if (!capable(CAP_NET_ADMIN)) return -EPERM; dev_load(ifr.ifr_name); @@ -2536,7 +2575,6 @@ case SIOCDELMULTI: case SIOCSIFHWBROADCAST: case SIOCSIFTXQLEN: - case SIOCSIFNAME: case SIOCSMIIREG: case SIOCBONDENSLAVE: case SIOCBONDRELEASE: @@ -2685,6 +2723,11 @@ ret = -EIO; goto out_err; } + } + + if (!dev_valid_name(dev->name)) { + ret = -EINVAL; + goto out_err; } dev->ifindex = dev_new_index();