The patch titled Fix race condition about network device name allocation has been removed from the -mm tree. Its filename was fix-race-condition-about-network-device-name.patch This patch was dropped because an updated version will be merged ------------------------------------------------------ Subject: Fix race condition about network device name allocation From: Kenji Kaneshige <kaneshige.kenji@xxxxxxxxxxxxxx> Fix the race condition between dev_alloc_name() and net device unregistration. dev_alloc_name checks `dev_base' list to find a suitable ID. On the other hand, net devices are removed from that list on net device unregistration. Both of them are done with holding rtnl lock. However, removing sysfs entry is delayed until netdev_run_todo(), which doesn't acquire rtnl lock. Therefore, on dev_alloc_name(), device name could conflict with the device, which is unregistered, but its sysfs entry still exist. To fix this bug, change dev_alloc_name to check not only `dev_base' list but also todo list and snapshot list. Signed-off-by: Kenji Kaneshige <kaneshige.kenji@xxxxxxxxxxxxxx> Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> Signed-off-by: Andrew Morton <akpm@xxxxxxxxxxxxxxxxxxxx> --- net/core/dev.c | 50 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-) diff -puN net/core/dev.c~fix-race-condition-about-network-device-name net/core/dev.c --- a/net/core/dev.c~fix-race-condition-about-network-device-name +++ a/net/core/dev.c @@ -229,6 +229,11 @@ extern void netdev_unregister_sysfs(stru #define netdev_unregister_sysfs(dev) do { } while(0) #endif +/* Delayed registration/unregistration */ +static DEFINE_SPINLOCK(net_todo_list_lock); +static LIST_HEAD(net_todo_list); +static LIST_HEAD(net_todo_snapshot_list); + /******************************************************************************* @@ -713,13 +718,38 @@ int dev_alloc_name(struct net_device *de if (i < 0 || i >= max_netdevices) continue; - /* avoid cases where sscanf is not exact inverse of printf */ + /* avoid cases where sscanf is not exact inverse of printf */ snprintf(buf, sizeof(buf), name, i); if (!strncmp(buf, d->name, IFNAMSIZ)) set_bit(i, inuse); } + spin_lock(&net_todo_list_lock); + list_for_each_entry(d, &net_todo_list, todo_list) { + if (!sscanf(d->name, name, &i)) + continue; + if (i < 0 || i >= max_netdevices) + continue; + + /* avoid cases where sscanf is not exact inverse of printf */ + snprintf(buf, sizeof(buf), name, i); + if (!strncmp(buf, d->name, IFNAMSIZ)) + set_bit(i, inuse); + } + list_for_each_entry(d, &net_todo_snapshot_list, todo_list) { + if (!sscanf(d->name, name, &i)) + continue; + if (i < 0 || i >= max_netdevices) + continue; + + /* avoid cases where sscanf is not exact inverse of printf */ + snprintf(buf, sizeof(buf), name, i); + if (!strncmp(buf, d->name, IFNAMSIZ)) + set_bit(i, inuse); + } i = find_first_zero_bit(inuse, max_netdevices); + spin_unlock(&net_todo_list_lock); + free_page((unsigned long) inuse); } @@ -2970,10 +3000,6 @@ static int dev_new_index(void) static int dev_boot_phase = 1; -/* Delayed registration/unregisteration */ -static DEFINE_SPINLOCK(net_todo_list_lock); -static struct list_head net_todo_list = LIST_HEAD_INIT(net_todo_list); - static void net_set_todo(struct net_device *dev) { spin_lock(&net_todo_list_lock); @@ -3228,8 +3254,6 @@ static void netdev_wait_allrefs(struct n static DEFINE_MUTEX(net_todo_run_mutex); void netdev_run_todo(void) { - struct list_head list; - /* Need to guard against multiple cpu's getting out of order. */ mutex_lock(&net_todo_run_mutex); @@ -3243,13 +3267,13 @@ void netdev_run_todo(void) /* Snapshot list, allow later requests */ spin_lock(&net_todo_list_lock); - list_replace_init(&net_todo_list, &list); + list_replace_init(&net_todo_list, &net_todo_snapshot_list); spin_unlock(&net_todo_list_lock); - while (!list_empty(&list)) { + while (!list_empty(&net_todo_snapshot_list)) { struct net_device *dev - = list_entry(list.next, struct net_device, todo_list); - list_del(&dev->todo_list); + = list_entry(net_todo_snapshot_list.next, + struct net_device, todo_list); if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { printk(KERN_ERR "network todo '%s' but state %d\n", @@ -3269,6 +3293,10 @@ void netdev_run_todo(void) BUG_TRAP(!dev->ip6_ptr); BUG_TRAP(!dev->dn_ptr); + spin_lock(&net_todo_list_lock); + list_del(&dev->todo_list); + spin_unlock(&net_todo_list_lock); + /* It must be the very last action, * after this 'dev' may point to freed up memory. */ _ Patches currently in -mm which might be from kaneshige.kenji@xxxxxxxxxxxxxx are fix-race-condition-about-network-device-name.patch - To unsubscribe from this list: send the line "unsubscribe mm-commits" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html