Message ID | 20221121132935.2032325-1-lizetao1@huawei.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp1566030wrr; Mon, 21 Nov 2022 04:52:33 -0800 (PST) X-Google-Smtp-Source: AA0mqf4aK0p3ZtQZ8QA9o02PLH9syEh8LwG9/1WqNTTTaB12/YsXyd25LIoJ8HYJ53Qds7Ys5eTq X-Received: by 2002:a17:906:124d:b0:7ad:b822:d2e4 with SMTP id u13-20020a170906124d00b007adb822d2e4mr15288612eja.35.1669035153478; Mon, 21 Nov 2022 04:52:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1669035153; cv=none; d=google.com; s=arc-20160816; b=y/P039CwuODwtp/qxXniEkL5ppO5GFQVKuY9diX1HsPH1Vu9MazTPhB0qkXImCsZZl szVrp98jSmsSJyg3ZVA3ntPMyX0q9ST9XR3v4YK64Ru5T/col4fu1NhDDJoLtwYA1h73 pS/25V6iMn18IRV5tfRJ34QwLL+O9aYE6aRzhMVLyswd9toQWypa+qd2pwDP0V8DGYEq hOlsLWuCU1+onBaHOrDOCiT9uOMZsjf6mUmBIpOEF7jOG+pgMUv0F15HoUKod+++iD2g 9szs7aYtqU37JaBL+6h500y8OopMeKJAEkqKUGtfkukxkzKrsNDhU6CF8sZzAuFQyKDd 0g5w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :message-id:date:subject:cc:to:from; bh=NCOfz0tUqJj/j35B86yfUw6c9sZPLqTz6eWaj/iEgn4=; b=zpqcAEmKpaNFo6vBK4MyxPqD3k3t32N8GqufX0vTVMSWg8VF7KE2H0ZotSknVGsCYm fzhOqdJWxb/js7zIP/+g1Hc3IRzYsT4RKN7fVSVSSzXGSgCPXfqQ3w34TMI2sjM0L0kn GANhtyURPJhJ59hVUq8bad/2Okz+rnDamy/npZEPNRMVgiaSj4v5DDqSmcs4ke5QMx2u nKdtKOkJfahRCEfJexClKXL6XNOANN6FfBYUA3s2AmyD23Z1cezIJLtIIMpQ2iije81X WIJvp5A1V8+yha17W69RMQdM37AffEQaUAyVT0XYGpochXKGjJBfyvXBeFvmDeKp0T+5 uchA== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id xg2-20020a170907320200b007827639faffsi8666254ejb.760.2022.11.21.04.52.06; Mon, 21 Nov 2022 04:52:33 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=huawei.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230428AbiKUMla (ORCPT <rfc822;cjcooper78@gmail.com> + 99 others); Mon, 21 Nov 2022 07:41:30 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:33610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229664AbiKUMl3 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 21 Nov 2022 07:41:29 -0500 Received: from szxga02-in.huawei.com (szxga02-in.huawei.com [45.249.212.188]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A46D2B7000; Mon, 21 Nov 2022 04:41:27 -0800 (PST) Received: from kwepemi500012.china.huawei.com (unknown [172.30.72.53]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4NG6SL4zJ5zHvRd; Mon, 21 Nov 2022 20:40:50 +0800 (CST) Received: from huawei.com (10.67.175.21) by kwepemi500012.china.huawei.com (7.221.188.12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Mon, 21 Nov 2022 20:41:25 +0800 From: Li Zetao <lizetao1@huawei.com> To: <mst@redhat.com>, <jasowang@redhat.com>, <davem@davemloft.net>, <edumazet@google.com>, <kuba@kernel.org>, <pabeni@redhat.com> CC: <lizetao1@huawei.com>, <rusty@rustcorp.com.au>, <virtualization@lists.linux-foundation.org>, <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org> Subject: [PATCH] virtio_net: Fix probe failed when modprobe virtio_net Date: Mon, 21 Nov 2022 21:29:35 +0800 Message-ID: <20221121132935.2032325-1-lizetao1@huawei.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 7BIT Content-Type: text/plain; charset=US-ASCII X-Originating-IP: [10.67.175.21] X-ClientProxiedBy: dggems705-chm.china.huawei.com (10.3.19.182) To kwepemi500012.china.huawei.com (7.221.188.12) X-CFilter-Loop: Reflected X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_MED, SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1750110205064621017?= X-GMAIL-MSGID: =?utf-8?q?1750110205064621017?= |
Series |
virtio_net: Fix probe failed when modprobe virtio_net
|
|
Commit Message
Li Zetao
Nov. 21, 2022, 1:29 p.m. UTC
When doing the following test steps, an error was found:
step 1: modprobe virtio_net succeeded
# modprobe virtio_net <-- OK
step 2: fault injection in register_netdevice()
# modprobe -r virtio_net <-- OK
# ...
FAULT_INJECTION: forcing a failure.
name failslab, interval 1, probability 0, space 0, times 0
CPU: 0 PID: 3521 Comm: modprobe
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996),
Call Trace:
<TASK>
...
should_failslab+0xa/0x20
...
dev_set_name+0xc0/0x100
netdev_register_kobject+0xc2/0x340
register_netdevice+0xbb9/0x1320
virtnet_probe+0x1d72/0x2658 [virtio_net]
...
</TASK>
virtio_net: probe of virtio0 failed with error -22
step 3: modprobe virtio_net failed
# modprobe virtio_net <-- failed
virtio_net: probe of virtio0 failed with error -2
The root cause of the problem is that the queues are not
disable on the error handling path when register_netdevice()
fails in virtnet_probe(), resulting in an error "-ENOENT"
returned in the next modprobe call in setup_vq().
virtio_pci_modern_device uses virtqueues to send or
receive message, and "queue_enable" records whether the
queues are available. In vp_modern_find_vqs(), all queues
will be selected and activated, but once queues are enabled
there is no way to go back except reset.
Fix it by reset virtio device on error handling path.
Fixes: 1fcf0512c9c8 ("virtio_pci: modern driver")
Signed-off-by: Li Zetao <lizetao1@huawei.com>
---
drivers/net/virtio_net.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
Comments
On Mon, Nov 21, 2022 at 09:29:35PM +0800, Li Zetao wrote: > When doing the following test steps, an error was found: > step 1: modprobe virtio_net succeeded > # modprobe virtio_net <-- OK > > step 2: fault injection in register_netdevice() > # modprobe -r virtio_net <-- OK > # ... > FAULT_INJECTION: forcing a failure. > name failslab, interval 1, probability 0, space 0, times 0 > CPU: 0 PID: 3521 Comm: modprobe > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), > Call Trace: > <TASK> > ... > should_failslab+0xa/0x20 > ... > dev_set_name+0xc0/0x100 > netdev_register_kobject+0xc2/0x340 > register_netdevice+0xbb9/0x1320 > virtnet_probe+0x1d72/0x2658 [virtio_net] > ... > </TASK> > virtio_net: probe of virtio0 failed with error -22 > > step 3: modprobe virtio_net failed > # modprobe virtio_net <-- failed > virtio_net: probe of virtio0 failed with error -2 > > The root cause of the problem is that the queues are not > disable on the error handling path when register_netdevice() > fails in virtnet_probe(), resulting in an error "-ENOENT" > returned in the next modprobe call in setup_vq(). > > virtio_pci_modern_device uses virtqueues to send or > receive message, and "queue_enable" records whether the > queues are available. In vp_modern_find_vqs(), all queues > will be selected and activated, but once queues are enabled > there is no way to go back except reset. > > Fix it by reset virtio device on error handling path. > > Fixes: 1fcf0512c9c8 ("virtio_pci: modern driver") > Signed-off-by: Li Zetao <lizetao1@huawei.com> I would add to this: ------ This makes error handling follow the same order as normal device cleanup which does: static void remove_vq_common(struct virtnet_info *vi) { virtio_reset_device(vi->vdev); /* Free unused buffers in both send and recv, if any. */ free_unused_bufs(vi); free_receive_bufs(vi); free_receive_page_frags(vi); virtnet_del_vqs(vi); } static void virtnet_remove(struct virtio_device *vdev) { struct virtnet_info *vi = vdev->priv; virtnet_cpu_notif_remove(vi); /* Make sure no work handler is accessing the device. */ flush_work(&vi->config_work); unregister_netdev(vi->dev); net_failover_destroy(vi->failover); remove_vq_common(vi); free_netdev(vi->dev); } So unregister, destroy failover, then reset - and that flow is better tested than error handling so we can be reasonably sure it works well. ----- I would thus probably also include this tag instead: Fixes: 0246555550 ("virtio_net: fix use after free on allocation failure") this is what introduced the difference in cleanup order, modern driver just added hardware support. Besides extending the commit log Acked-by: Michael S. Tsirkin <mst@redhat.com> > --- > drivers/net/virtio_net.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c > index 7106932c6f88..86e52454b5b5 100644 > --- a/drivers/net/virtio_net.c > +++ b/drivers/net/virtio_net.c > @@ -3949,12 +3949,11 @@ static int virtnet_probe(struct virtio_device *vdev) > return 0; > > free_unregister_netdev: > - virtio_reset_device(vdev); > - > unregister_netdev(dev); > free_failover: > net_failover_destroy(vi->failover); > free_vqs: > + virtio_reset_device(vdev); > cancel_delayed_work_sync(&vi->refill); > free_receive_page_frags(vi); > virtnet_del_vqs(vi); > -- > 2.25.1
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 7106932c6f88..86e52454b5b5 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -3949,12 +3949,11 @@ static int virtnet_probe(struct virtio_device *vdev) return 0; free_unregister_netdev: - virtio_reset_device(vdev); - unregister_netdev(dev); free_failover: net_failover_destroy(vi->failover); free_vqs: + virtio_reset_device(vdev); cancel_delayed_work_sync(&vi->refill); free_receive_page_frags(vi); virtnet_del_vqs(vi);