From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Long Li <longli@microsoft.com>,
Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
Michael Kelley <mikelley@microsoft.com>,
Sasha Levin <sashal@kernel.org>,
linux-hyperv@vger.kernel.org, linux-pci@vger.kernel.org
Subject: [PATCH AUTOSEL 5.10 07/37] PCI: hv: Fix a race condition when removing the device
Date: Sat, 10 Jul 2021 19:49:45 -0400 [thread overview]
Message-ID: <20210710235016.3221124-7-sashal@kernel.org> (raw)
In-Reply-To: <20210710235016.3221124-1-sashal@kernel.org>
From: Long Li <longli@microsoft.com>
[ Upstream commit 94d22763207ac6633612b8d8e0ca4fba0f7aa139 ]
On removing the device, any work item (hv_pci_devices_present() or
hv_pci_eject_device()) scheduled on workqueue hbus->wq may still be running
and race with hv_pci_remove().
This can happen because the host may send PCI_EJECT or PCI_BUS_RELATIONS(2)
and decide to rescind the channel immediately after that.
Fix this by flushing/destroying the workqueue of hbus before doing hbus remove.
Link: https://lore.kernel.org/r/1620806800-30983-1-git-send-email-longli@linuxonhyperv.com
Signed-off-by: Long Li <longli@microsoft.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/pci/controller/pci-hyperv.c | 30 ++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index 03ed5cb1c4b2..4932d7677be2 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -444,7 +444,6 @@ enum hv_pcibus_state {
hv_pcibus_probed,
hv_pcibus_installed,
hv_pcibus_removing,
- hv_pcibus_removed,
hv_pcibus_maximum
};
@@ -3247,8 +3246,9 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
struct pci_packet teardown_packet;
u8 buffer[sizeof(struct pci_message)];
} pkt;
- struct hv_dr_state *dr;
struct hv_pci_compl comp_pkt;
+ struct hv_pci_dev *hpdev, *tmp;
+ unsigned long flags;
int ret;
/*
@@ -3260,9 +3260,16 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs)
if (!keep_devs) {
/* Delete any children which might still exist. */
- dr = kzalloc(sizeof(*dr), GFP_KERNEL);
- if (dr && hv_pci_start_relations_work(hbus, dr))
- kfree(dr);
+ spin_lock_irqsave(&hbus->device_list_lock, flags);
+ list_for_each_entry_safe(hpdev, tmp, &hbus->children, list_entry) {
+ list_del(&hpdev->list_entry);
+ if (hpdev->pci_slot)
+ pci_destroy_slot(hpdev->pci_slot);
+ /* For the two refs got in new_pcichild_device() */
+ put_pcichild(hpdev);
+ put_pcichild(hpdev);
+ }
+ spin_unlock_irqrestore(&hbus->device_list_lock, flags);
}
ret = hv_send_resources_released(hdev);
@@ -3305,13 +3312,23 @@ static int hv_pci_remove(struct hv_device *hdev)
hbus = hv_get_drvdata(hdev);
if (hbus->state == hv_pcibus_installed) {
+ tasklet_disable(&hdev->channel->callback_event);
+ hbus->state = hv_pcibus_removing;
+ tasklet_enable(&hdev->channel->callback_event);
+ destroy_workqueue(hbus->wq);
+ hbus->wq = NULL;
+ /*
+ * At this point, no work is running or can be scheduled
+ * on hbus-wq. We can't race with hv_pci_devices_present()
+ * or hv_pci_eject_device(), it's safe to proceed.
+ */
+
/* Remove the bus from PCI's point of view. */
pci_lock_rescan_remove();
pci_stop_root_bus(hbus->pci_bus);
hv_pci_remove_slots(hbus);
pci_remove_root_bus(hbus->pci_bus);
pci_unlock_rescan_remove();
- hbus->state = hv_pcibus_removed;
}
ret = hv_pci_bus_exit(hdev, false);
@@ -3326,7 +3343,6 @@ static int hv_pci_remove(struct hv_device *hdev)
irq_domain_free_fwnode(hbus->sysdata.fwnode);
put_hvpcibus(hbus);
wait_for_completion(&hbus->remove_event);
- destroy_workqueue(hbus->wq);
hv_put_dom_num(hbus->sysdata.domain);
--
2.30.2
next prev parent reply other threads:[~2021-07-10 23:51 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-07-10 23:49 [PATCH AUTOSEL 5.10 01/37] power: supply: sc27xx: Add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 02/37] power: supply: sc2731_charger: " Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 03/37] f2fs: fix to avoid racing on fsync_entry_slab by multi filesystem instances Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 04/37] pwm: spear: Don't modify HW state in .remove callback Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 05/37] PCI: ftpci100: Rename macro name collision Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 06/37] power: supply: ab8500: Avoid NULL pointers Sasha Levin
2021-07-10 23:49 ` Sasha Levin [this message]
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 08/37] power: supply: max17042: Do not enforce (incorrect) interrupt trigger type Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 09/37] power: reset: gpio-poweroff: add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 10/37] ARM: 9087/1: kprobes: test-thumb: fix for LLVM_IAS=1 Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 11/37] PCI/P2PDMA: Avoid pci_get_slot(), which may sleep Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 12/37] NFSv4: Fix delegation return in cases where we have to retry Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 13/37] PCI: pciehp: Ignore Link Down/Up caused by DPC Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 14/37] watchdog: Fix possible use-after-free in wdt_startup() Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 15/37] watchdog: sc520_wdt: Fix possible use-after-free in wdt_turnoff() Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 16/37] watchdog: Fix possible use-after-free by calling del_timer_sync() Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 17/37] watchdog: imx_sc_wdt: fix pretimeout Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 18/37] watchdog: iTCO_wdt: Account for rebooting on second timeout Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 19/37] x86/fpu: Return proper error codes from user access functions Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 20/37] remoteproc: core: Fix cdev remove and rproc del Sasha Levin
2021-07-10 23:49 ` [PATCH AUTOSEL 5.10 21/37] PCI: tegra: Add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 22/37] orangefs: fix orangefs df output Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 23/37] ceph: remove bogus checks and WARN_ONs from ceph_set_page_dirty Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 24/37] drm/gma500: Add the missed drm_gem_object_put() in psb_user_framebuffer_create() Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 25/37] NFS: nfs_find_open_context() may only select open files Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 26/37] power: supply: charger-manager: add missing MODULE_DEVICE_TABLE Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 27/37] power: supply: ab8500: " Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 28/37] drm/amdkfd: fix sysfs kobj leak Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 29/37] pwm: img: Fix PM reference leak in img_pwm_enable() Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 30/37] pwm: tegra: Don't modify HW state in .remove callback Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 31/37] ACPI: AMBA: Fix resource name in /proc/iomem Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 32/37] ACPI: video: Add quirk for the Dell Vostro 3350 Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 33/37] PCI: rockchip: Register IRQ handlers after device and data are ready Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 34/37] virtio-blk: Fix memory leak among suspend/resume procedure Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 35/37] virtio_net: Fix error handling in virtnet_restore() Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 36/37] virtio_console: Assure used length from device is limited Sasha Levin
2021-07-10 23:50 ` [PATCH AUTOSEL 5.10 37/37] virtio: fix up virtio_disable_cb Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210710235016.3221124-7-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=longli@microsoft.com \
--cc=lorenzo.pieralisi@arm.com \
--cc=mikelley@microsoft.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox