aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/xen-netfront.c
diff options
context:
space:
mode:
authorDavid Vrabel <david.vrabel@citrix.com>2015-05-27 10:46:10 -0400
committerDavid S. Miller <davem@davemloft.net>2015-05-27 14:02:28 -0400
commitad0681185770716523c81b156c44b9804d7b8ed2 (patch)
treef2519cc3625d8d327a5e4eb8e7ca15ed4fd83274 /drivers/net/xen-netfront.c
parentf4ecf29fd78d19a9301e638eaa1419e5c8fbdce1 (diff)
xen-netfront: properly destroy queues when removing device
xennet_remove() freed the queues before freeing the netdevice which results in a use-after-free when free_netdev() tries to delete the napi instances that have already been freed. Fix this by fully destroy the queues (which includes deleting the napi instances) before freeing the netdevice. Signed-off-by: David Vrabel <david.vrabel@citrix.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/xen-netfront.c')
-rw-r--r--drivers/net/xen-netfront.c15
1 files changed, 2 insertions, 13 deletions
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 3f45afd4382e..e031c943286e 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -1698,6 +1698,7 @@ static void xennet_destroy_queues(struct netfront_info *info)
1698 1698
1699 if (netif_running(info->netdev)) 1699 if (netif_running(info->netdev))
1700 napi_disable(&queue->napi); 1700 napi_disable(&queue->napi);
1701 del_timer_sync(&queue->rx_refill_timer);
1701 netif_napi_del(&queue->napi); 1702 netif_napi_del(&queue->napi);
1702 } 1703 }
1703 1704
@@ -2102,9 +2103,6 @@ static const struct attribute_group xennet_dev_group = {
2102static int xennet_remove(struct xenbus_device *dev) 2103static int xennet_remove(struct xenbus_device *dev)
2103{ 2104{
2104 struct netfront_info *info = dev_get_drvdata(&dev->dev); 2105 struct netfront_info *info = dev_get_drvdata(&dev->dev);
2105 unsigned int num_queues = info->netdev->real_num_tx_queues;
2106 struct netfront_queue *queue = NULL;
2107 unsigned int i = 0;
2108 2106
2109 dev_dbg(&dev->dev, "%s\n", dev->nodename); 2107 dev_dbg(&dev->dev, "%s\n", dev->nodename);
2110 2108
@@ -2112,16 +2110,7 @@ static int xennet_remove(struct xenbus_device *dev)
2112 2110
2113 unregister_netdev(info->netdev); 2111 unregister_netdev(info->netdev);
2114 2112
2115 for (i = 0; i < num_queues; ++i) { 2113 xennet_destroy_queues(info);
2116 queue = &info->queues[i];
2117 del_timer_sync(&queue->rx_refill_timer);
2118 }
2119
2120 if (num_queues) {
2121 kfree(info->queues);
2122 info->queues = NULL;
2123 }
2124
2125 xennet_free_netdev(info->netdev); 2114 xennet_free_netdev(info->netdev);
2126 2115
2127 return 0; 2116 return 0;