Jiri Bohac 340041
From: Jiri Bohac <jbohac@suse.cz>
Jiri Bohac 340041
Subject: net: make __dev_alloc_name consider all name nodes when looking for
Jiri Bohac 340041
References: bsc#1180103
Jiri Bohac 340041
Acked-by: Jiri Bohac <jbohac@suse.cz>
Jeff Mahoney bb0636
Git-commit: 6c015a2256801597fadcbc11d287774c9c512fa5
Jeff Mahoney bb0636
Patch-mainline: v5.12-rc5
Jiri Bohac 340041
Jiri Bohac 340041
__dev_alloc_name(), when supplied with a name containing '%d', will search for the first
Jiri Bohac 340041
available device number to filled in the name.
Jiri Bohac 340041
Jiri Bohac 340041
Since commit ff92741270bf8b6e78aa885f166b68c7a67ab13a ("net: introduce
Jiri Bohac 340041
name_node struct to be used in hashlist") network devices may have alternate
Jiri Bohac 340041
names.  __dev_alloc_name() does take these alternate names into account when looking
Jiri Bohac 340041
for the device number, possibly generating a name that is already taken, failing with
Jiri Bohac 340041
-ENFILE as a result.
Jiri Bohac 340041
Jiri Bohac 340041
This can easily be reproduced:
Jiri Bohac 340041
Jiri Bohac 340041
	# rmmod dummy 2>/dev/null
Jiri Bohac 340041
	# ip link property add dev lo altname dummy0
Jiri Bohac 340041
	# modprobe dummy num_dummies=1
Jiri Bohac 340041
	modprobe: ERROR: could not insert 'dummy': Too many open files in system
Jiri Bohac 340041
Jiri Bohac 340041
Instead of creating a device named dummy1, the operation fails.
Jiri Bohac 340041
Jiri Bohac 340041
Fix this by checking all the names in the dev->name_node list, not just dev->name.
Jiri Bohac 340041
Jiri Bohac 340041
Signed-off-by: Jiri Bohac <jbohac@suse.cz>
Jiri Bohac 340041
Fixes: ff92741270bf ("net: introduce name_node struct to be used in hashlist")
Jiri Bohac 340041
Jiri Bohac 340041
diff --git a/net/core/dev.c b/net/core/dev.c
Jiri Bohac 340041
index 6c5967e80132..7cbcd8d37e91 100644
Jiri Bohac 340041
--- a/net/core/dev.c
Jiri Bohac 340041
+++ b/net/core/dev.c
Jiri Bohac 340041
@@ -1184,6 +1184,18 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
Jiri Bohac 340041
 			return -ENOMEM;
Jiri Bohac 340041
 
Jiri Bohac 340041
 		for_each_netdev(net, d) {
Jiri Bohac 340041
+			struct netdev_name_node *name_node;
Jiri Bohac 340041
+			list_for_each_entry(name_node, &d->name_node->list, list) {
Jiri Bohac 340041
+				if (!sscanf(name_node->name, name, &i))
Jiri Bohac 340041
+					continue;
Jiri Bohac 340041
+				if (i < 0 || i >= max_netdevices)
Jiri Bohac 340041
+					continue;
Jiri Bohac 340041
+
Jiri Bohac 340041
+				/*  avoid cases where sscanf is not exact inverse of printf */
Jiri Bohac 340041
+				snprintf(buf, IFNAMSIZ, name, i);
Jiri Bohac 340041
+				if (!strncmp(buf, name_node->name, IFNAMSIZ))
Jiri Bohac 340041
+					set_bit(i, inuse);
Jiri Bohac 340041
+			}
Jiri Bohac 340041
 			if (!sscanf(d->name, name, &i))
Jiri Bohac 340041
 				continue;
Jiri Bohac 340041
 			if (i < 0 || i >= max_netdevices)
Jeff Mahoney bb0636