From: "Andrea Parri (Microsoft)" <parri.andrea@gmail.com>
To: KY Srinivasan <kys@microsoft.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Stephen Hemminger <sthemmin@microsoft.com>,
Wei Liu <wei.liu@kernel.org>, Dexuan Cui <decui@microsoft.com>,
Michael Kelley <mikelley@microsoft.com>,
Wei Hu <weh@microsoft.com>,
Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>,
Rob Herring <robh@kernel.org>,
Krzysztof Wilczynski <kw@linux.com>,
Bjorn Helgaas <bhelgaas@google.com>
Cc: linux-pci@vger.kernel.org, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org,
"Andrea Parri (Microsoft)" <parri.andrea@gmail.com>
Subject: [PATCH 2/2] PCI: hv: Fix synchronization between channel callback and hv_compose_msi_msg()
Date: Fri, 18 Mar 2022 18:48:48 +0100 [thread overview]
Message-ID: <20220318174848.290621-3-parri.andrea@gmail.com> (raw)
In-Reply-To: <20220318174848.290621-1-parri.andrea@gmail.com>
Dexuan wrote:
"[...] when we disable AccelNet, the host PCI VSP driver sends a
PCI_EJECT message first, and the channel callback may set
hpdev->state to hv_pcichild_ejecting on a different CPU. This can
cause hv_compose_msi_msg() to exit from the loop and 'return', and
the on-stack variable 'ctxt' is invalid. Now, if the response
message from the host arrives, the channel callback will try to
access the invalid 'ctxt' variable, and this may cause a crash."
Schematically:
Hyper-V sends PCI_EJECT msg
hv_pci_onchannelcallback()
state = hv_pcichild_ejecting
hv_compose_msi_msg()
alloc and init comp_pkt
state == hv_pcichild_ejecting
Hyper-V sends VM_PKT_COMP msg
hv_pci_onchannelcallback()
retrieve address of comp_pkt
'free' comp_pkt and return
comp_pkt->completion_func()
Dexuan also showed how the crash can be triggered after introducing
suitable delays in the driver code, thus validating the 'assumption'
that the host can still normally respond to the guest's compose_msi
request after the host has started to eject the PCI device.
Fix the synchronization by leveraging the IDR lock. Retrieve the
address of the completion packet *and call the completion function
within a same critical section: if an address (request ID) is found
in the channel callback, the critical section precedes the removal
of the address in hv_compose_msi_msg().
Fixes: de0aa7b2f97d3 ("PCI: hv: Fix 2 hang issues in hv_compose_msi_msg()")
Reported-by: Wei Hu <weh@microsoft.com>
Reported-by: Dexuan Cui <decui@microsoft.com>
Suggested-by: Michael Kelley <mikelley@microsoft.com>
Signed-off-by: Andrea Parri (Microsoft) <parri.andrea@gmail.com>
---
drivers/pci/controller/pci-hyperv.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c
index fbc62aab08fdc..dddd7e4d0352d 100644
--- a/drivers/pci/controller/pci-hyperv.c
+++ b/drivers/pci/controller/pci-hyperv.c
@@ -495,7 +495,8 @@ struct hv_pcibus_device {
spinlock_t device_list_lock; /* Protect lists below */
void __iomem *cfg_addr;
- spinlock_t idr_lock; /* Serialize accesses to the IDR */
+ /* Serialize accesses to the IDR; see also hv_pci_onchannelcallback(). */
+ spinlock_t idr_lock;
struct idr idr; /* Map guest memory addresses */
struct list_head children;
@@ -2797,16 +2798,24 @@ static void hv_pci_onchannelcallback(void *context)
}
spin_lock_irqsave(&hbus->idr_lock, flags);
comp_packet = (struct pci_packet *)idr_find(&hbus->idr, req_id);
- spin_unlock_irqrestore(&hbus->idr_lock, flags);
if (!comp_packet) {
+ spin_unlock_irqrestore(&hbus->idr_lock, flags);
dev_warn_ratelimited(&hbus->hdev->device,
"Request ID not found\n");
break;
}
response = (struct pci_response *)buffer;
+ /*
+ * Call ->completion_func() within the critical section to make
+ * sure that the packet pointer is still valid during the call:
+ * here 'valid' means that there's a task still waiting for the
+ * completion, and that the packet data is still on the waiting
+ * task's stack/has not already been freed by the waiting task.
+ */
comp_packet->completion_func(comp_packet->compl_ctxt,
response,
bytes_recvd);
+ spin_unlock_irqrestore(&hbus->idr_lock, flags);
break;
case VM_PKT_DATA_INBAND:
--
2.25.1
prev parent reply other threads:[~2022-03-18 17:49 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-18 17:48 [PATCH 0/2] PCI: hv: Miscellaneous changes Andrea Parri (Microsoft)
2022-03-18 17:48 ` [PATCH 1/2] PCI: hv: Use IDR to generate transaction IDs for VMBus hardening Andrea Parri (Microsoft)
2022-03-19 7:47 ` [EXTERNAL] " Saurabh Singh Sengar
2022-03-19 15:59 ` Andrea Parri
2022-03-20 5:53 ` Saurabh Singh Sengar
2022-03-19 16:20 ` Michael Kelley (LINUX)
2022-03-20 14:58 ` Andrea Parri
2022-03-21 18:23 ` Michael Kelley (LINUX)
2022-03-22 12:51 ` Andrea Parri
2022-03-18 17:48 ` Andrea Parri (Microsoft) [this message]
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=20220318174848.290621-3-parri.andrea@gmail.com \
--to=parri.andrea@gmail.com \
--cc=bhelgaas@google.com \
--cc=decui@microsoft.com \
--cc=haiyangz@microsoft.com \
--cc=kw@linux.com \
--cc=kys@microsoft.com \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=lorenzo.pieralisi@arm.com \
--cc=mikelley@microsoft.com \
--cc=robh@kernel.org \
--cc=sthemmin@microsoft.com \
--cc=weh@microsoft.com \
--cc=wei.liu@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