[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230221113428.19324-4-bp@alien8.de>
Date: Tue, 21 Feb 2023 12:34:20 +0100
From: Borislav Petkov <bp@...en8.de>
To: LKML <linux-kernel@...r.kernel.org>
Cc: Dionna Glaze <dionnaglaze@...gle.com>,
Joerg Roedel <jroedel@...e.de>,
Michael Roth <michael.roth@....com>,
Nikunj A Dadhania <nikunj@....com>,
Peter Gonda <pgonda@...gle.com>,
Tom Lendacky <Thomas.Lendacky@....com>,
linux-coco@...ts.linux.dev, x86@...nel.org
Subject: [PATCH -v2 03/11] virt/coco/sev-guest: Simplify extended guest request handling
From: "Borislav Petkov (AMD)" <bp@...en8.de>
Return a specific error code - -ENOSPC - to signal the too small cert
data buffer instead of checking exit code and exitinfo2.
While at it, hoist the *fw_err assignment in snp_issue_guest_request()
so that a proper error value is returned to the callers.
Signed-off-by: Borislav Petkov (AMD) <bp@...en8.de>
---
arch/x86/kernel/sev.c | 11 +++---
drivers/virt/coco/sev-guest/sev-guest.c | 46 ++++++++++++++-----------
2 files changed, 31 insertions(+), 26 deletions(-)
diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index c644c34372e8..6a3e1425ba17 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
if (ret)
goto e_put;
+ *fw_err = ghcb->save.sw_exit_info_2;
if (ghcb->save.sw_exit_info_2) {
/* Number of expected pages are returned in RBX */
if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
- ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN)
+ ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) {
input->data_npages = ghcb_get_rbx(ghcb);
-
- *fw_err = ghcb->save.sw_exit_info_2;
-
- ret = -EIO;
+ ret = -ENOSPC;
+ } else {
+ ret = -EIO;
+ }
}
e_put:
diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
index edaf6031c6d9..5b4cddf44a3a 100644
--- a/drivers/virt/coco/sev-guest/sev-guest.c
+++ b/drivers/virt/coco/sev-guest/sev-guest.c
@@ -322,7 +322,8 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
u8 type, void *req_buf, size_t req_sz, void *resp_buf,
u32 resp_sz, __u64 *fw_err)
{
- unsigned long err;
+ unsigned long err, override_err = 0;
+ unsigned int override_npages = 0;
u64 seqno;
int rc;
@@ -338,6 +339,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
if (rc)
return rc;
+retry_request:
/*
* Call firmware to process the request. In this function the encrypted
* message enters shared memory with the host. So after this call the
@@ -346,17 +348,24 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
*/
rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
- /*
- * If the extended guest request fails due to having too small of a
- * certificate data buffer, retry the same guest request without the
- * extended data request in order to increment the sequence number
- * and thus avoid IV reuse.
- */
- if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
- err == SNP_GUEST_REQ_INVALID_LEN) {
- const unsigned int certs_npages = snp_dev->input.data_npages;
+ switch (rc) {
+ case -ENOSPC:
+ /*
+ * If the extended guest request fails due to having too
+ * small of a certificate data buffer, retry the same
+ * guest request without the extended data request in
+ * order to increment the sequence number and thus avoid
+ * IV reuse.
+ */
+ override_npages = snp_dev->input.data_npages;
+ exit_code = SVM_VMGEXIT_GUEST_REQUEST;
- exit_code = SVM_VMGEXIT_GUEST_REQUEST;
+ /*
+ * Override the error to inform callers the given extended
+ * request buffer size was too small and give the caller the
+ * required buffer size.
+ */
+ override_err = SNP_GUEST_REQ_INVALID_LEN;
/*
* If this call to the firmware succeeds, the sequence number can
@@ -366,19 +375,14 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
* of the VMPCK and the error code being propagated back to the
* user as an ioctl() return code.
*/
- rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
-
- /*
- * Override the error to inform callers the given extended
- * request buffer size was too small and give the caller the
- * required buffer size.
- */
- err = SNP_GUEST_REQ_INVALID_LEN;
- snp_dev->input.data_npages = certs_npages;
+ goto retry_request;
}
if (fw_err)
- *fw_err = err;
+ *fw_err = override_err ?: err;
+
+ if (override_npages)
+ snp_dev->input.data_npages = override_npages;
if (rc) {
dev_alert(snp_dev->dev,
--
2.35.1
Powered by blists - more mailing lists