Skip to content

Commit

Permalink
[NET]: Fix race condition about network device name allocation.
Browse files Browse the repository at this point in the history
Kenji Kaneshige found this race between device removal and
registration.  On unregister it is possible for the old device to
exist, because sysfs file is still open.  A new device with 'eth%d'
will select the same name, but sysfs kobject register will fial.

The following changes the shutdown order slightly. It hold a removes
the sysfs entries earlier (on unregister_netdevice), but holds a
kobject reference.  Then when todo runs the actual last put free
happens.

Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Stephen Hemminger authored and David S. Miller committed May 19, 2007
1 parent d8cf272 commit 9093bbb
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 5 deletions.
10 changes: 6 additions & 4 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3314,7 +3314,6 @@ void netdev_run_todo(void)
continue;
}

netdev_unregister_sysfs(dev);
dev->reg_state = NETREG_UNREGISTERED;

netdev_wait_allrefs(dev);
Expand All @@ -3325,11 +3324,11 @@ void netdev_run_todo(void)
BUG_TRAP(!dev->ip6_ptr);
BUG_TRAP(!dev->dn_ptr);

/* It must be the very last action,
* after this 'dev' may point to freed up memory.
*/
if (dev->destructor)
dev->destructor(dev);

/* Free network device */
kobject_put(&dev->dev.kobj);
}

out:
Expand Down Expand Up @@ -3480,6 +3479,9 @@ void unregister_netdevice(struct net_device *dev)
/* Notifier chain MUST detach us from master device. */
BUG_TRAP(!dev->master);

/* Remove entries from sysfs */
netdev_unregister_sysfs(dev);

/* Finish processing unregister after unlock */
net_set_todo(dev);

Expand Down
8 changes: 7 additions & 1 deletion net/core/net-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,9 +456,15 @@ static struct class net_class = {
#endif
};

/* Delete sysfs entries but hold kobject reference until after all
* netdev references are gone.
*/
void netdev_unregister_sysfs(struct net_device * net)
{
device_del(&(net->dev));
struct device *dev = &(net->dev);

kobject_get(&dev->kobj);
device_del(dev);
}

/* Create sysfs entries for network device. */
Expand Down

0 comments on commit 9093bbb

Please sign in to comment.