Skip to content

Commit f599c64

Browse files
rosslagerwalljgross1
authored andcommitted
xen-netfront: Fix race between device setup and open
When a netfront device is set up it registers a netdev fairly early on, before it has set up the queues and is actually usable. A userspace tool like NetworkManager will immediately try to open it and access its state as soon as it appears. The bug can be reproduced by hotplugging VIFs until the VM runs out of grant refs. It registers the netdev but fails to set up any queues (since there are no more grant refs). In the meantime, NetworkManager opens the device and the kernel crashes trying to access the queues (of which there are none). Fix this in two ways: * For initial setup, register the netdev much later, after the queues are setup. This avoids the race entirely. * During a suspend/resume cycle, the frontend reconnects to the backend and the queues are recreated. It is possible (though highly unlikely) to race with something opening the device and accessing the queues after they have been destroyed but before they have been recreated. Extend the region covered by the rtnl semaphore to protect against this race. There is a possibility that we fail to recreate the queues so check for this in the open function. Signed-off-by: Ross Lagerwall <[email protected]> Reviewed-by: Boris Ostrovsky <[email protected]> Signed-off-by: Juergen Gross <[email protected]>
1 parent 3ac7292 commit f599c64

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

drivers/net/xen-netfront.c

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,9 @@ static int xennet_open(struct net_device *dev)
351351
unsigned int i = 0;
352352
struct netfront_queue *queue = NULL;
353353

354+
if (!np->queues)
355+
return -ENODEV;
356+
354357
for (i = 0; i < num_queues; ++i) {
355358
queue = &np->queues[i];
356359
napi_enable(&queue->napi);
@@ -1358,18 +1361,8 @@ static int netfront_probe(struct xenbus_device *dev,
13581361
#ifdef CONFIG_SYSFS
13591362
info->netdev->sysfs_groups[0] = &xennet_dev_group;
13601363
#endif
1361-
err = register_netdev(info->netdev);
1362-
if (err) {
1363-
pr_warn("%s: register_netdev err=%d\n", __func__, err);
1364-
goto fail;
1365-
}
13661364

13671365
return 0;
1368-
1369-
fail:
1370-
xennet_free_netdev(netdev);
1371-
dev_set_drvdata(&dev->dev, NULL);
1372-
return err;
13731366
}
13741367

13751368
static void xennet_end_access(int ref, void *page)
@@ -1737,8 +1730,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
17371730
{
17381731
unsigned int i;
17391732

1740-
rtnl_lock();
1741-
17421733
for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
17431734
struct netfront_queue *queue = &info->queues[i];
17441735

@@ -1747,8 +1738,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
17471738
netif_napi_del(&queue->napi);
17481739
}
17491740

1750-
rtnl_unlock();
1751-
17521741
kfree(info->queues);
17531742
info->queues = NULL;
17541743
}
@@ -1764,8 +1753,6 @@ static int xennet_create_queues(struct netfront_info *info,
17641753
if (!info->queues)
17651754
return -ENOMEM;
17661755

1767-
rtnl_lock();
1768-
17691756
for (i = 0; i < *num_queues; i++) {
17701757
struct netfront_queue *queue = &info->queues[i];
17711758

@@ -1774,7 +1761,7 @@ static int xennet_create_queues(struct netfront_info *info,
17741761

17751762
ret = xennet_init_queue(queue);
17761763
if (ret < 0) {
1777-
dev_warn(&info->netdev->dev,
1764+
dev_warn(&info->xbdev->dev,
17781765
"only created %d queues\n", i);
17791766
*num_queues = i;
17801767
break;
@@ -1788,10 +1775,8 @@ static int xennet_create_queues(struct netfront_info *info,
17881775

17891776
netif_set_real_num_tx_queues(info->netdev, *num_queues);
17901777

1791-
rtnl_unlock();
1792-
17931778
if (*num_queues == 0) {
1794-
dev_err(&info->netdev->dev, "no queues\n");
1779+
dev_err(&info->xbdev->dev, "no queues\n");
17951780
return -EINVAL;
17961781
}
17971782
return 0;
@@ -1828,6 +1813,7 @@ static int talk_to_netback(struct xenbus_device *dev,
18281813
goto out;
18291814
}
18301815

1816+
rtnl_lock();
18311817
if (info->queues)
18321818
xennet_destroy_queues(info);
18331819

@@ -1838,6 +1824,7 @@ static int talk_to_netback(struct xenbus_device *dev,
18381824
info->queues = NULL;
18391825
goto out;
18401826
}
1827+
rtnl_unlock();
18411828

18421829
/* Create shared ring, alloc event channel -- for each queue */
18431830
for (i = 0; i < num_queues; ++i) {
@@ -1934,8 +1921,10 @@ static int talk_to_netback(struct xenbus_device *dev,
19341921
xenbus_transaction_end(xbt, 1);
19351922
destroy_ring:
19361923
xennet_disconnect_backend(info);
1924+
rtnl_lock();
19371925
xennet_destroy_queues(info);
19381926
out:
1927+
rtnl_unlock();
19391928
device_unregister(&dev->dev);
19401929
return err;
19411930
}
@@ -1965,6 +1954,15 @@ static int xennet_connect(struct net_device *dev)
19651954
netdev_update_features(dev);
19661955
rtnl_unlock();
19671956

1957+
if (dev->reg_state == NETREG_UNINITIALIZED) {
1958+
err = register_netdev(dev);
1959+
if (err) {
1960+
pr_warn("%s: register_netdev err=%d\n", __func__, err);
1961+
device_unregister(&np->xbdev->dev);
1962+
return err;
1963+
}
1964+
}
1965+
19681966
/*
19691967
* All public and private state should now be sane. Get
19701968
* ready to start sending and receiving packets and give the driver
@@ -2150,10 +2148,14 @@ static int xennet_remove(struct xenbus_device *dev)
21502148

21512149
xennet_disconnect_backend(info);
21522150

2153-
unregister_netdev(info->netdev);
2151+
if (info->netdev->reg_state == NETREG_REGISTERED)
2152+
unregister_netdev(info->netdev);
21542153

2155-
if (info->queues)
2154+
if (info->queues) {
2155+
rtnl_lock();
21562156
xennet_destroy_queues(info);
2157+
rtnl_unlock();
2158+
}
21572159
xennet_free_netdev(info->netdev);
21582160

21592161
return 0;

0 commit comments

Comments
 (0)