Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 76bb5db5 authored by stephen hemminger's avatar stephen hemminger Committed by David S. Miller
Browse files

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: default avatarStephen Hemminger <sthemmin@microsoft.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dfb05553
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -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);
+6 −3
Original line number Diff line number Diff line
@@ -1009,13 +1009,16 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)

	/* Set the channel before opening.*/
	nvchan->channel = new_sc;
	netif_napi_add(ndev, &nvchan->napi,
		       netvsc_poll, NAPI_POLL_WEIGHT);

	ret = vmbus_open(new_sc, nvscdev->ring_size * PAGE_SIZE,
			 nvscdev->ring_size * PAGE_SIZE, NULL, 0,
			 netvsc_channel_cb, nvchan);


	if (ret == 0)
		napi_enable(&nvchan->napi);
	else
		netdev_err(ndev, "sub channel open failed (%d)\n", ret);

	if (refcount_dec_and_test(&nvscdev->sc_offered))
		complete(&nvscdev->channel_init_wait);