summaryrefslogtreecommitdiffstats
path: root/drivers/net/hyperv/netvsc.c
diff options
context:
space:
mode:
authorstephen hemminger <stephen@networkplumber.org>2017-04-20 00:22:02 +0200
committerDavid S. Miller <davem@davemloft.net>2017-04-21 19:59:57 +0200
commit76bb5db5c749dfe19d779aac076133e821b859dd (patch)
treed844c765fe7dcdf2cafb136bcaa2f3cfb3569250 /drivers/net/hyperv/netvsc.c
parentMerge branch 'tc-filter-cleanup-destroy-delete' (diff)
downloadlinux-76bb5db5c749dfe19d779aac076133e821b859dd.tar.xz
linux-76bb5db5c749dfe19d779aac076133e821b859dd.zip
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/hyperv/netvsc.c')
-rw-r--r--drivers/net/hyperv/netvsc.c9
1 files changed, 5 insertions, 4 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)
/* Now, we can close the channel safely */
vmbus_close(device->channel);
+ /* And dissassociate NAPI context from device */
for (i = 0; i < net_device->num_chn; i++)
- napi_disable(&net_device->chan_table[i].napi);
+ netif_napi_del(&net_device->chan_table[i].napi);
/* Release all resources */
free_netvsc_device_rcu(net_device);
@@ -1320,8 +1321,6 @@ int netvsc_device_add(struct hv_device *device,
struct netvsc_channel *nvchan = &net_device->chan_table[i];
nvchan->channel = device->channel;
- netif_napi_add(ndev, &nvchan->napi,
- netvsc_poll, NAPI_POLL_WEIGHT);
}
/* Open the channel */
@@ -1339,6 +1338,8 @@ int netvsc_device_add(struct hv_device *device,
netdev_dbg(ndev, "hv_netvsc channel opened successfully\n");
/* Enable NAPI handler for init callbacks */
+ netif_napi_add(ndev, &net_device->chan_table[0].napi,
+ netvsc_poll, NAPI_POLL_WEIGHT);
napi_enable(&net_device->chan_table[0].napi);
/* Writing nvdev pointer unlocks netvsc_send(), make sure chn_table is
@@ -1357,7 +1358,7 @@ int netvsc_device_add(struct hv_device *device,
return ret;
close:
- napi_disable(&net_device->chan_table[0].napi);
+ netif_napi_del(&net_device->chan_table[0].napi);
/* Now, we can close the channel safely */
vmbus_close(device->channel);