Skip to content

Commit 440b5e3

Browse files
dcuiliuw
authored andcommitted
PCI: hv: Fix a race condition bug in hv_pci_query_relations()
Since day 1 of the driver, there has been a race between hv_pci_query_relations() and survey_child_resources(): during fast device hotplug, hv_pci_query_relations() may error out due to device-remove and the stack variable 'comp' is no longer valid; however, pci_devices_present_work() -> survey_child_resources() -> complete() may be running on another CPU and accessing the no-longer-valid 'comp'. Fix the race by flushing the workqueue before we exit from hv_pci_query_relations(). Fixes: 4daace0 ("PCI: hv: Add paravirtual PCI front-end for Microsoft Hyper-V VMs") Signed-off-by: Dexuan Cui <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Acked-by: Lorenzo Pieralisi <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]>
1 parent 52ae076 commit 440b5e3

File tree

1 file changed

+18
-0
lines changed

1 file changed

+18
-0
lines changed

drivers/pci/controller/pci-hyperv.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3401,6 +3401,24 @@ static int hv_pci_query_relations(struct hv_device *hdev)
34013401
if (!ret)
34023402
ret = wait_for_response(hdev, &comp);
34033403

3404+
/*
3405+
* In the case of fast device addition/removal, it's possible that
3406+
* vmbus_sendpacket() or wait_for_response() returns -ENODEV but we
3407+
* already got a PCI_BUS_RELATIONS* message from the host and the
3408+
* channel callback already scheduled a work to hbus->wq, which can be
3409+
* running pci_devices_present_work() -> survey_child_resources() ->
3410+
* complete(&hbus->survey_event), even after hv_pci_query_relations()
3411+
* exits and the stack variable 'comp' is no longer valid; as a result,
3412+
* a hang or a page fault may happen when the complete() calls
3413+
* raw_spin_lock_irqsave(). Flush hbus->wq before we exit from
3414+
* hv_pci_query_relations() to avoid the issues. Note: if 'ret' is
3415+
* -ENODEV, there can't be any more work item scheduled to hbus->wq
3416+
* after the flush_workqueue(): see vmbus_onoffer_rescind() ->
3417+
* vmbus_reset_channel_cb(), vmbus_rescind_cleanup() ->
3418+
* channel->rescind = true.
3419+
*/
3420+
flush_workqueue(hbus->wq);
3421+
34043422
return ret;
34053423
}
34063424

0 commit comments

Comments
 (0)