Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756184AbbBCRA6 (ORCPT ); Tue, 3 Feb 2015 12:00:58 -0500 Received: from mx1.redhat.com ([209.132.183.28]:50642 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754570AbbBCRAy (ORCPT ); Tue, 3 Feb 2015 12:00:54 -0500 From: Vitaly Kuznetsov To: "K. Y. Srinivasan" , devel@linuxdriverproject.org Cc: Haiyang Zhang , linux-kernel@vger.kernel.org, Dexuan Cui , Jason Wang Subject: [PATCH 4/4] hyperv: netvsc: improve protection against rescind offer Date: Tue, 3 Feb 2015 18:00:39 +0100 Message-Id: <1422982839-3948-5-git-send-email-vkuznets@redhat.com> In-Reply-To: <1422982839-3948-1-git-send-email-vkuznets@redhat.com> References: <1422982839-3948-1-git-send-email-vkuznets@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1884 Lines: 55 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 Signed-off-by: Vitaly Kuznetsov --- 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 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/