aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorstephen hemminger <stephen@networkplumber.org>2017-04-19 18:22:02 -0400
committerDavid S. Miller <davem@davemloft.net>2017-04-21 13:59:57 -0400
commit76bb5db5c749dfe19d779aac076133e821b859dd (patch)
treed844c765fe7dcdf2cafb136bcaa2f3cfb3569250 /drivers/net
parentdfb05553a55d89e6daae9cb9abfdf4751e14d72d (diff)
netvsc: fix use after free on module removal
The NAPI data structure is embedded in the netvsc_device structure and is freed when device is closed. There is still a reference (in NAPI list) to this which causes a crash in netif_napi_del when device is removed. Fix by managing NAPI instances correctly. Signed-off-by: Stephen Hemminger <sthemmin@microsoft.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/hyperv/netvsc.c9
-rw-r--r--drivers/net/hyperv/rndis_filter.c9
2 files changed, 11 insertions, 7 deletions
diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c
index 967843ba03fa..f99651c03e0a 100644
--- a/drivers/net/hyperv/netvsc.c
+++ b/drivers/net/hyperv/netvsc.c
@@ -584,8 +584,9 @@ void netvsc_device_remove(struct hv_device *device)
584 /* Now, we can close the channel safely */ 584 /* Now, we can close the channel safely */
585 vmbus_close(device->channel); 585 vmbus_close(device->channel);
586 586
587 /* And dissassociate NAPI context from device */
587 for (i = 0; i < net_device->num_chn; i++) 588 for (i = 0; i < net_device->num_chn; i++)
588 napi_disable(&net_device->chan_table[i].napi); 589 netif_napi_del(&net_device->chan_table[i].napi);
589 590
590 /* Release all resources */ 591 /* Release all resources */
591 free_netvsc_device_rcu(net_device); 592 free_netvsc_device_rcu(net_device);
@@ -1320,8 +1321,6 @@ int netvsc_device_add(struct hv_device *device,
1320 struct netvsc_channel *nvchan = &net_device->chan_table[i]; 1321 struct netvsc_channel *nvchan = &net_device->chan_table[i];
1321 1322
1322 nvchan->channel = device->channel; 1323 nvchan->channel = device->channel;
1323 netif_napi_add(ndev, &nvchan->napi,
1324 netvsc_poll, NAPI_POLL_WEIGHT);
1325 } 1324 }
1326 1325
1327 /* Open the channel */ 1326 /* Open the channel */
@@ -1339,6 +1338,8 @@ int netvsc_device_add(struct hv_device *device,
1339 netdev_dbg(ndev, "hv_netvsc channel opened successfully\n"); 1338 netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");
1340 1339
1341 /* Enable NAPI handler for init callbacks */ 1340 /* Enable NAPI handler for init callbacks */
1341 netif_napi_add(ndev, &net_device->chan_table[0].napi,
1342 netvsc_poll, NAPI_POLL_WEIGHT);
1342 napi_enable(&net_device->chan_table[0].napi); 1343 napi_enable(&net_device->chan_table[0].napi);
1343 1344
1344 /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is 1345 /* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
@@ -1357,7 +1358,7 @@ int netvsc_device_add(struct hv_device *device,
1357 return ret; 1358 return ret;
1358 1359
1359close: 1360close:
1360 napi_disable(&net_device->chan_table[0].napi); 1361 netif_napi_del(&net_device->chan_table[0].napi);
1361 1362
1362 /* Now, we can close the channel safely */ 1363 /* Now, we can close the channel safely */
1363 vmbus_close(device->channel); 1364 vmbus_close(device->channel);
diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c
index 1e9445bc4539..ab92c3c95951 100644
--- a/drivers/net/hyperv/rndis_filter.c
+++ b/drivers/net/hyperv/rndis_filter.c
@@ -1009,13 +1009,16 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
1009 1009
1010 /* Set the channel before opening.*/ 1010 /* Set the channel before opening.*/
1011 nvchan->channel = new_sc; 1011 nvchan->channel = new_sc;
1012 netif_napi_add(ndev, &nvchan->napi,
1013 netvsc_poll, NAPI_POLL_WEIGHT);
1012 1014
1013 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE, 1015 ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
1014 nvscdev->ring_size * PAGE_SIZE, NULL, 0, 1016 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
1015 netvsc_channel_cb, nvchan); 1017 netvsc_channel_cb, nvchan);
1016 1018 if (ret == 0)
1017 1019 napi_enable(&nvchan->napi);
1018 napi_enable(&nvchan->napi); 1020 else
1021 netdev_err(ndev, "sub channel open failed (%d)\n", ret);
1019 1022
1020 if (refcount_dec_and_test(&nvscdev->sc_offered)) 1023 if (refcount_dec_and_test(&nvscdev->sc_offered))
1021 complete(&nvscdev->channel_init_wait); 1024 complete(&nvscdev->channel_init_wait);