The check added in commit c3582a2c4d0b ("hyperv: Add support for vNIC hot removal") is incomplete as there is no synchronization between vmbus_onoffer_rescind() and netvsc_send(). In case we get the offer after we checked out_channel->rescind and before netvsc_send() finishes its job we can get a crash as we'll be dealing with already freed channel. Make netvsc_send() take additional reference to the channel with newly introduced vmbus_get_channel(), this guarantees we won't lose the channel. We can still get rescind while we're processing but this won't cause a crash. Reported-by: Jason Wang <jasowang@xxxxxxxxxx> Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx> --- drivers/net/hyperv/netvsc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/net/hyperv/netvsc.c b/drivers/net/hyperv/netvsc.c index 9f49c01..d9b13a1 100644 --- a/drivers/net/hyperv/netvsc.c +++ b/drivers/net/hyperv/netvsc.c @@ -763,11 +763,16 @@ int netvsc_send(struct hv_device *device, out_channel = net_device->chn_table[packet->q_idx]; if (out_channel == NULL) out_channel = device->channel; - packet->channel = out_channel; + packet->channel = vmbus_get_channel(out_channel); - if (out_channel->rescind) + if (!packet->channel) return -ENODEV; + if (out_channel->rescind) { + vmbus_put_channel(out_channel); + return -ENODEV; + } + if (packet->page_buf_cnt) { ret = vmbus_sendpacket_pagebuffer(out_channel, packet->page_buf, @@ -810,6 +815,7 @@ int netvsc_send(struct hv_device *device, packet, ret); } + vmbus_put_channel(packet->channel); return ret; } -- 1.9.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel