Skip to content

Commit 6be4fe8

Browse files
rosslagerwallgregkh
authored andcommitted
xen-netfront: Fix race between device setup and open
[ Upstream commit f599c64 ] 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 <ross.lagerwall@citrix.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Juergen Gross <jgross@suse.com> Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 492917f commit 6be4fe8

File tree

1 file changed

+24
-22
lines changed

1 file changed

+24
-22
lines changed

drivers/net/xen-netfront.c

+24-22
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ static int xennet_open(struct net_device *dev)
342342
unsigned int i = 0;
343343
struct netfront_queue *queue = NULL;
344344

345+
if (!np->queues)
346+
return -ENODEV;
347+
345348
for (i = 0; i < num_queues; ++i) {
346349
queue = &np->queues[i];
347350
napi_enable(&queue->napi);
@@ -1363,18 +1366,8 @@ static int netfront_probe(struct xenbus_device *dev,
13631366
#ifdef CONFIG_SYSFS
13641367
info->netdev->sysfs_groups[0] = &xennet_dev_group;
13651368
#endif
1366-
err = register_netdev(info->netdev);
1367-
if (err) {
1368-
pr_warn("%s: register_netdev err=%d\n", __func__, err);
1369-
goto fail;
1370-
}
13711369

13721370
return 0;
1373-
1374-
fail:
1375-
xennet_free_netdev(netdev);
1376-
dev_set_drvdata(&dev->dev, NULL);
1377-
return err;
13781371
}
13791372

13801373
static void xennet_end_access(int ref, void *page)
@@ -1743,8 +1736,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
17431736
{
17441737
unsigned int i;
17451738

1746-
rtnl_lock();
1747-
17481739
for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
17491740
struct netfront_queue *queue = &info->queues[i];
17501741

@@ -1753,8 +1744,6 @@ static void xennet_destroy_queues(struct netfront_info *info)
17531744
netif_napi_del(&queue->napi);
17541745
}
17551746

1756-
rtnl_unlock();
1757-
17581747
kfree(info->queues);
17591748
info->queues = NULL;
17601749
}
@@ -1770,8 +1759,6 @@ static int xennet_create_queues(struct netfront_info *info,
17701759
if (!info->queues)
17711760
return -ENOMEM;
17721761

1773-
rtnl_lock();
1774-
17751762
for (i = 0; i < *num_queues; i++) {
17761763
struct netfront_queue *queue = &info->queues[i];
17771764

@@ -1780,7 +1767,7 @@ static int xennet_create_queues(struct netfront_info *info,
17801767

17811768
ret = xennet_init_queue(queue);
17821769
if (ret < 0) {
1783-
dev_warn(&info->netdev->dev,
1770+
dev_warn(&info->xbdev->dev,
17841771
"only created %d queues\n", i);
17851772
*num_queues = i;
17861773
break;
@@ -1794,10 +1781,8 @@ static int xennet_create_queues(struct netfront_info *info,
17941781

17951782
netif_set_real_num_tx_queues(info->netdev, *num_queues);
17961783

1797-
rtnl_unlock();
1798-
17991784
if (*num_queues == 0) {
1800-
dev_err(&info->netdev->dev, "no queues\n");
1785+
dev_err(&info->xbdev->dev, "no queues\n");
18011786
return -EINVAL;
18021787
}
18031788
return 0;
@@ -1839,6 +1824,7 @@ static int talk_to_netback(struct xenbus_device *dev,
18391824
goto out;
18401825
}
18411826

1827+
rtnl_lock();
18421828
if (info->queues)
18431829
xennet_destroy_queues(info);
18441830

@@ -1849,6 +1835,7 @@ static int talk_to_netback(struct xenbus_device *dev,
18491835
info->queues = NULL;
18501836
goto out;
18511837
}
1838+
rtnl_unlock();
18521839

18531840
/* Create shared ring, alloc event channel -- for each queue */
18541841
for (i = 0; i < num_queues; ++i) {
@@ -1945,8 +1932,10 @@ static int talk_to_netback(struct xenbus_device *dev,
19451932
xenbus_transaction_end(xbt, 1);
19461933
destroy_ring:
19471934
xennet_disconnect_backend(info);
1935+
rtnl_lock();
19481936
xennet_destroy_queues(info);
19491937
out:
1938+
rtnl_unlock();
19501939
device_unregister(&dev->dev);
19511940
return err;
19521941
}
@@ -1982,6 +1971,15 @@ static int xennet_connect(struct net_device *dev)
19821971
netdev_update_features(dev);
19831972
rtnl_unlock();
19841973

1974+
if (dev->reg_state == NETREG_UNINITIALIZED) {
1975+
err = register_netdev(dev);
1976+
if (err) {
1977+
pr_warn("%s: register_netdev err=%d\n", __func__, err);
1978+
device_unregister(&np->xbdev->dev);
1979+
return err;
1980+
}
1981+
}
1982+
19851983
/*
19861984
* All public and private state should now be sane. Get
19871985
* ready to start sending and receiving packets and give the driver
@@ -2172,10 +2170,14 @@ static int xennet_remove(struct xenbus_device *dev)
21722170

21732171
xennet_disconnect_backend(info);
21742172

2175-
unregister_netdev(info->netdev);
2173+
if (info->netdev->reg_state == NETREG_REGISTERED)
2174+
unregister_netdev(info->netdev);
21762175

2177-
if (info->queues)
2176+
if (info->queues) {
2177+
rtnl_lock();
21782178
xennet_destroy_queues(info);
2179+
rtnl_unlock();
2180+
}
21792181
xennet_free_netdev(info->netdev);
21802182

21812183
return 0;

0 commit comments

Comments
 (0)