Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp4617766pxj; Wed, 12 May 2021 09:20:22 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwEGIt1gynXnBd42XBQt2QfMcThV8VzQHCQf3er/AYcxwhQXX2Te/glVD0fJQeeH+lX7qrx X-Received: by 2002:a17:906:4a13:: with SMTP id w19mr38479586eju.533.1620836422297; Wed, 12 May 2021 09:20:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620836422; cv=none; d=google.com; s=arc-20160816; b=KDeAfCtKJbK8seWrITyUa/3yEDYwjIe9BMe7laAjU8SHojp1XCIU///BiGpG+mTtzs bwmfWjiHQVTtFinaIsiXwaxDd6dlDBzCfEMeYIDFbZQH55i0BdH0UGYGjrFiGjwQtvKz gDlroBzN1WnYXQI8A0T2PKxBJUDKAJb+5ZnMIK+CTCO0UYYWy0wz5UGxywsxQ89ObAeW RdW294RI0gtLaF6UFJZJ0mp6eHm9vZ206AqtK9uq2RxQRvRZ/ehVUAAMUEacu3ZKYnU8 MwGdfk/2DLcu1Ejw86q54+XRFiRr7O80nYE3e+usbe2nzuSNxmm83CQv8q3r1U5EoJkU Lxiw== 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 :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=CzCFSZZ7hTB/JVOqKUESeE/rb6b2zzxlLqLbJNQYU58=; b=WarmL9HRxhJKcbZh6R8AG5Z29K2wq1wBm11FEWf2gLmxy+/+pcTsZUkR/Ibe0uK21z P8sEY0VP4BDHuYmsoCwPcC58XZ3dpAL/eXdGiieAGk9Osx9dW/XB+nnlwO9dkCle+pQ0 r1xl19kls5HSF2L/fpsiRS5h781kjcP6ID/LU5seBlllV0MFJ16nEb1r/5ZzatmbrdlU C4wcA9tEaErnG0u+U7AVHWzbQ5waQqq1TQwAy4ujzr/WxHRbH/zDAHBTGlfdXEBtuDfY hOwFwTryvp+dFioGK2dX28CSbEUU8xBBBFMbzQYv9bfQP7j9BEdQ1PL0L2Gr3qW/Ccfh 8txw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=kHVYHXK1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id z6si213029ejf.385.2021.05.12.09.19.58; Wed, 12 May 2021 09:20:22 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=kHVYHXK1; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S239593AbhELQKN (ORCPT + 99 others); Wed, 12 May 2021 12:10:13 -0400 Received: from mail.kernel.org ([198.145.29.99]:45780 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233953AbhELP3R (ORCPT ); Wed, 12 May 2021 11:29:17 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id BEC3D61944; Wed, 12 May 2021 15:15:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1620832530; bh=3Pk2lkgWh10vXwhyJrqeHJbz72WF0ZStbKGVtucrE6I=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kHVYHXK1TCdJSbvgEazJ5jTUnucAV1kKX1j6fKKCooMj4cpzcz1d51AtnZKU3BP6a +PoiuXBVuzONvxSIukHL+AFmpfgE9lQp6SD5Pw75U7RwzaKT9+9L0l2FA2isu1BPTq +XAAk1lqB29V8QYEb2FeyKB+jUbYWxnad/r0/2as= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Christoph Hellwig , Kevin Tian , Max Gurtovoy , Cornelia Huck , Eric Auger , Jason Gunthorpe , Alex Williamson , Sasha Levin Subject: [PATCH 5.10 317/530] vfio/pci: Move VGA and VF initialization to functions Date: Wed, 12 May 2021 16:47:07 +0200 Message-Id: <20210512144830.223580086@linuxfoundation.org> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210512144819.664462530@linuxfoundation.org> References: <20210512144819.664462530@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jason Gunthorpe [ Upstream commit 61e90817482871b614133c0f20feb1aba2faec86 ] vfio_pci_probe() is quite complicated, with optional VF and VGA sub components. Move these into clear init/uninit functions and have a linear flow in probe/remove. This fixes a few little buglets: - vfio_pci_remove() is in the wrong order, vga_client_register() removes a notifier and is after kfree(vdev), but the notifier refers to vdev, so it can use after free in a race. - vga_client_register() can fail but was ignored Organize things so destruction order is the reverse of creation order. Fixes: ecaa1f6a0154 ("vfio-pci: Add VGA arbiter client") Reviewed-by: Christoph Hellwig Reviewed-by: Kevin Tian Reviewed-by: Max Gurtovoy Reviewed-by: Cornelia Huck Reviewed-by: Eric Auger Signed-off-by: Jason Gunthorpe Message-Id: <7-v3-225de1400dfc+4e074-vfio1_jgg@nvidia.com> Signed-off-by: Alex Williamson Signed-off-by: Sasha Levin --- drivers/vfio/pci/vfio_pci.c | 116 +++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 42 deletions(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 465f646e3329..f31aa25f361c 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -1926,6 +1926,68 @@ static int vfio_pci_bus_notifier(struct notifier_block *nb, return 0; } +static int vfio_pci_vf_init(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + int ret; + + if (!pdev->is_physfn) + return 0; + + vdev->vf_token = kzalloc(sizeof(*vdev->vf_token), GFP_KERNEL); + if (!vdev->vf_token) + return -ENOMEM; + + mutex_init(&vdev->vf_token->lock); + uuid_gen(&vdev->vf_token->uuid); + + vdev->nb.notifier_call = vfio_pci_bus_notifier; + ret = bus_register_notifier(&pci_bus_type, &vdev->nb); + if (ret) { + kfree(vdev->vf_token); + return ret; + } + return 0; +} + +static void vfio_pci_vf_uninit(struct vfio_pci_device *vdev) +{ + if (!vdev->vf_token) + return; + + bus_unregister_notifier(&pci_bus_type, &vdev->nb); + WARN_ON(vdev->vf_token->users); + mutex_destroy(&vdev->vf_token->lock); + kfree(vdev->vf_token); +} + +static int vfio_pci_vga_init(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + int ret; + + if (!vfio_pci_is_vga(pdev)) + return 0; + + ret = vga_client_register(pdev, vdev, NULL, vfio_pci_set_vga_decode); + if (ret) + return ret; + vga_set_legacy_decoding(pdev, vfio_pci_set_vga_decode(vdev, false)); + return 0; +} + +static void vfio_pci_vga_uninit(struct vfio_pci_device *vdev) +{ + struct pci_dev *pdev = vdev->pdev; + + if (!vfio_pci_is_vga(pdev)) + return; + vga_client_register(pdev, NULL, NULL, NULL); + vga_set_legacy_decoding(pdev, VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM | + VGA_RSRC_LEGACY_IO | + VGA_RSRC_LEGACY_MEM); +} + static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct vfio_pci_device *vdev; @@ -1979,28 +2041,12 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = vfio_pci_reflck_attach(vdev); if (ret) goto out_del_group_dev; - - if (pdev->is_physfn) { - vdev->vf_token = kzalloc(sizeof(*vdev->vf_token), GFP_KERNEL); - if (!vdev->vf_token) { - ret = -ENOMEM; - goto out_reflck; - } - - mutex_init(&vdev->vf_token->lock); - uuid_gen(&vdev->vf_token->uuid); - - vdev->nb.notifier_call = vfio_pci_bus_notifier; - ret = bus_register_notifier(&pci_bus_type, &vdev->nb); - if (ret) - goto out_vf_token; - } - - if (vfio_pci_is_vga(pdev)) { - vga_client_register(pdev, vdev, NULL, vfio_pci_set_vga_decode); - vga_set_legacy_decoding(pdev, - vfio_pci_set_vga_decode(vdev, false)); - } + ret = vfio_pci_vf_init(vdev); + if (ret) + goto out_reflck; + ret = vfio_pci_vga_init(vdev); + if (ret) + goto out_vf; vfio_pci_probe_power_state(vdev); @@ -2020,8 +2066,8 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) return ret; -out_vf_token: - kfree(vdev->vf_token); +out_vf: + vfio_pci_vf_uninit(vdev); out_reflck: vfio_pci_reflck_put(vdev->reflck); out_del_group_dev: @@ -2043,33 +2089,19 @@ static void vfio_pci_remove(struct pci_dev *pdev) if (!vdev) return; - if (vdev->vf_token) { - WARN_ON(vdev->vf_token->users); - mutex_destroy(&vdev->vf_token->lock); - kfree(vdev->vf_token); - } - - if (vdev->nb.notifier_call) - bus_unregister_notifier(&pci_bus_type, &vdev->nb); - + vfio_pci_vf_uninit(vdev); vfio_pci_reflck_put(vdev->reflck); + vfio_pci_vga_uninit(vdev); vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev); - kfree(vdev->region); - mutex_destroy(&vdev->ioeventfds_lock); if (!disable_idle_d3) vfio_pci_set_power_state(vdev, PCI_D0); + mutex_destroy(&vdev->ioeventfds_lock); + kfree(vdev->region); kfree(vdev->pm_save); kfree(vdev); - - if (vfio_pci_is_vga(pdev)) { - vga_client_register(pdev, NULL, NULL, NULL); - vga_set_legacy_decoding(pdev, - VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM | - VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM); - } } static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, -- 2.30.2