Blob Blame History Raw
From: Jiri Bohac <jbohac@suse.cz>
Subject: net: make __dev_alloc_name consider all name nodes when looking for
References: bsc#1180103
Acked-by: Jiri Bohac <jbohac@suse.cz>
Git-commit: 6c015a2256801597fadcbc11d287774c9c512fa5
Patch-mainline: v5.12-rc5

__dev_alloc_name(), when supplied with a name containing '%d', will search for the first
available device number to filled in the name.

Since commit ff92741270bf8b6e78aa885f166b68c7a67ab13a ("net: introduce
name_node struct to be used in hashlist") network devices may have alternate
names.  __dev_alloc_name() does take these alternate names into account when looking
for the device number, possibly generating a name that is already taken, failing with
-ENFILE as a result.

This can easily be reproduced:

	# rmmod dummy 2>/dev/null
	# ip link property add dev lo altname dummy0
	# modprobe dummy num_dummies=1
	modprobe: ERROR: could not insert 'dummy': Too many open files in system

Instead of creating a device named dummy1, the operation fails.

Fix this by checking all the names in the dev->name_node list, not just dev->name.

Signed-off-by: Jiri Bohac <jbohac@suse.cz>
Fixes: ff92741270bf ("net: introduce name_node struct to be used in hashlist")

diff --git a/net/core/dev.c b/net/core/dev.c
index 6c5967e80132..7cbcd8d37e91 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1184,6 +1184,18 @@ static int __dev_alloc_name(struct net *net, const char *name, char *buf)
 			return -ENOMEM;
 
 		for_each_netdev(net, d) {
+			struct netdev_name_node *name_node;
+			list_for_each_entry(name_node, &d->name_node->list, list) {
+				if (!sscanf(name_node->name, name, &i))
+					continue;
+				if (i < 0 || i >= max_netdevices)
+					continue;
+
+				/*  avoid cases where sscanf is not exact inverse of printf */
+				snprintf(buf, IFNAMSIZ, name, i);
+				if (!strncmp(buf, name_node->name, IFNAMSIZ))
+					set_bit(i, inuse);
+			}
 			if (!sscanf(d->name, name, &i))
 				continue;
 			if (i < 0 || i >= max_netdevices)