aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDaniel Lezcano <daniel.lezcano@free.fr>2010-05-19 06:12:19 -0400
committerDavid S. Miller <davem@davemloft.net>2010-05-24 02:24:36 -0400
commit8ce6cebc2f126f3ecf2d80746ea54245adf18057 (patch)
tree6efcd84b0a8d00aede2c52944bc8eaecc02e67de /net
parenta4ed89cb92f93d406ac45fe5507228a2475e32ba (diff)
net-2.6 : V2 - fix dev_get_valid_name
the commit: commit d90310243fd750240755e217c5faa13e24f41536 Author: Octavian Purdila <opurdila@ixiacom.com> Date: Wed Nov 18 02:36:59 2009 +0000 net: device name allocation cleanups introduced a bug when there is a hash collision making impossible to rename a device with eth%d. This bug is very hard to reproduce and appears rarely. The problem is coming from we don't pass a temporary buffer to __dev_alloc_name but 'dev->name' which is modified by the function. A detailed explanation is here: http://marc.info/?l=linux-netdev&m=127417784011987&w=2 Changelog: V2 : replaced strings comparison by pointers comparison Signed-off-by: Daniel Lezcano <daniel.lezcano@free.fr> Reviewed-by: Octavian Purdila <opurdila@ixiacom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 0aab66d68b19..07a48e2bf7db 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -954,18 +954,22 @@ int dev_alloc_name(struct net_device *dev, const char *name)
954} 954}
955EXPORT_SYMBOL(dev_alloc_name); 955EXPORT_SYMBOL(dev_alloc_name);
956 956
957static int dev_get_valid_name(struct net *net, const char *name, char *buf, 957static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt)
958 bool fmt)
959{ 958{
959 struct net *net;
960
961 BUG_ON(!dev_net(dev));
962 net = dev_net(dev);
963
960 if (!dev_valid_name(name)) 964 if (!dev_valid_name(name))
961 return -EINVAL; 965 return -EINVAL;
962 966
963 if (fmt && strchr(name, '%')) 967 if (fmt && strchr(name, '%'))
964 return __dev_alloc_name(net, name, buf); 968 return dev_alloc_name(dev, name);
965 else if (__dev_get_by_name(net, name)) 969 else if (__dev_get_by_name(net, name))
966 return -EEXIST; 970 return -EEXIST;
967 else if (buf != name) 971 else if (dev->name != name)
968 strlcpy(buf, name, IFNAMSIZ); 972 strlcpy(dev->name, name, IFNAMSIZ);
969 973
970 return 0; 974 return 0;
971} 975}
@@ -997,7 +1001,7 @@ int dev_change_name(struct net_device *dev, const char *newname)
997 1001
998 memcpy(oldname, dev->name, IFNAMSIZ); 1002 memcpy(oldname, dev->name, IFNAMSIZ);
999 1003
1000 err = dev_get_valid_name(net, newname, dev->name, 1); 1004 err = dev_get_valid_name(dev, newname, 1);
1001 if (err < 0) 1005 if (err < 0)
1002 return err; 1006 return err;
1003 1007
@@ -4965,7 +4969,7 @@ int register_netdevice(struct net_device *dev)
4965 } 4969 }
4966 } 4970 }
4967 4971
4968 ret = dev_get_valid_name(net, dev->name, dev->name, 0); 4972 ret = dev_get_valid_name(dev, dev->name, 0);
4969 if (ret) 4973 if (ret)
4970 goto err_uninit; 4974 goto err_uninit;
4971 4975
@@ -5574,7 +5578,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
5574 /* We get here if we can't use the current device name */ 5578 /* We get here if we can't use the current device name */
5575 if (!pat) 5579 if (!pat)
5576 goto out; 5580 goto out;
5577 if (dev_get_valid_name(net, pat, dev->name, 1)) 5581 if (dev_get_valid_name(dev, pat, 1))
5578 goto out; 5582 goto out;
5579 } 5583 }
5580 5584