From: Greg Kroah-Hartman Date: Mon, 20 Mar 2023 13:24:42 +0000 (+0100) Subject: 6.1-stable patches X-Git-Tag: v4.14.311~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d7625282e6b0b7a4713b78e863a000ab0d4f24c8;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: virt-coco-sev-guest-add-throttling-awareness.patch virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch virt-coco-sev-guest-do-some-code-style-cleanups.patch virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch virt-coco-sev-guest-simplify-extended-guest-request-handling.patch --- diff --git a/queue-6.1/series b/queue-6.1/series index c8224780330..ee7293a4d74 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -188,3 +188,10 @@ x86-mce-make-sure-logged-mces-are-processed-after-sysfs-update.patch x86-mm-fix-use-of-uninitialized-buffer-in-sme_enable.patch x86-resctrl-clear-staged_config-before-and-after-it-is-used.patch powerpc-pass-correct-cpu-reference-to-assembler.patch +virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch +virt-coco-sev-guest-simplify-extended-guest-request-handling.patch +virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch +virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch +virt-coco-sev-guest-do-some-code-style-cleanups.patch +virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch +virt-coco-sev-guest-add-throttling-awareness.patch diff --git a/queue-6.1/virt-coco-sev-guest-add-throttling-awareness.patch b/queue-6.1/virt-coco-sev-guest-add-throttling-awareness.patch new file mode 100644 index 00000000000..729639a1a83 --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-add-throttling-awareness.patch @@ -0,0 +1,138 @@ +From 72f7754dcf31c87c92c0c353dcf747814cc5ce10 Mon Sep 17 00:00:00 2001 +From: Dionna Glaze +Date: Thu, 16 Feb 2023 11:08:02 +0100 +Subject: virt/coco/sev-guest: Add throttling awareness + +From: Dionna Glaze + +commit 72f7754dcf31c87c92c0c353dcf747814cc5ce10 upstream. + +A potentially malicious SEV guest can constantly hammer the hypervisor +using this driver to send down requests and thus prevent or at least +considerably hinder other guests from issuing requests to the secure +processor which is a shared platform resource. + +Therefore, the host is permitted and encouraged to throttle such guest +requests. + +Add the capability to handle the case when the hypervisor throttles +excessive numbers of requests issued by the guest. Otherwise, the VM +platform communication key will be disabled, preventing the guest from +attesting itself. + +Realistically speaking, a well-behaved guest should not even care about +throttling. During its lifetime, it would end up issuing a handful of +requests which the hardware can easily handle. + +This is more to address the case of a malicious guest. Such guest should +get throttled and if its VMPCK gets disabled, then that's its own +wrongdoing and perhaps that guest even deserves it. + +To the implementation: the hypervisor signals with SNP_GUEST_REQ_ERR_BUSY +that the guest requests should be throttled. That error code is returned +in the upper 32-bit half of exitinfo2 and this is part of the GHCB spec +v2. + +So the guest is given a throttling period of 1 minute in which it +retries the request every 2 seconds. This is a good default but if it +turns out to not pan out in practice, it can be tweaked later. + +For safety, since the encryption algorithm in GHCBv2 is AES_GCM, control +must remain in the kernel to complete the request with the current +sequence number. Returning without finishing the request allows the +guest to make another request but with different message contents. This +is IV reuse, and breaks cryptographic protections. + + [ bp: + - Rewrite commit message and do a simplified version. + - The stable tags are supposed to denote that a cleanup should go + upfront before backporting this so that any future fixes to this + can preserve the sanity of the backporter(s). ] + +Fixes: d5af44dde546 ("x86/sev: Provide support for SNP guest request NAEs") +Signed-off-by: Dionna Glaze +Co-developed-by: Borislav Petkov (AMD) +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Tom Lendacky +Cc: # d6fd48eff750 ("virt/coco/sev-guest: Check SEV_SNP attribute at probe time") +Cc: # 970ab823743f (" virt/coco/sev-guest: Simplify extended guest request handling") +Cc: # c5a338274bdb ("virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request()") +Cc: # 0fdb6cc7c89c ("virt/coco/sev-guest: Carve out the request issuing logic into a helper") +Cc: # d25bae7dc7b0 ("virt/coco/sev-guest: Do some code style cleanups") +Cc: # fa4ae42cc60a ("virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case") +Link: https://lore.kernel.org/r/20230214164638.1189804-2-dionnaglaze@google.com +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/sev-common.h | 3 ++- + arch/x86/kernel/sev.c | 4 ++++ + drivers/virt/coco/sev-guest/sev-guest.c | 19 ++++++++++++++++++- + 3 files changed, 24 insertions(+), 2 deletions(-) + +--- a/arch/x86/include/asm/sev-common.h ++++ b/arch/x86/include/asm/sev-common.h +@@ -128,8 +128,9 @@ struct snp_psc_desc { + struct psc_entry entries[VMGEXIT_PSC_MAX_ENTRY]; + } __packed; + +-/* Guest message request error code */ ++/* Guest message request error codes */ + #define SNP_GUEST_REQ_INVALID_LEN BIT_ULL(32) ++#define SNP_GUEST_REQ_ERR_BUSY BIT_ULL(33) + + #define GHCB_MSR_TERM_REQ 0x100 + #define GHCB_MSR_TERM_REASON_SET_POS 12 +--- a/arch/x86/kernel/sev.c ++++ b/arch/x86/kernel/sev.c +@@ -2214,6 +2214,10 @@ int snp_issue_guest_request(u64 exit_cod + case 0: + break; + ++ case SNP_GUEST_REQ_ERR_BUSY: ++ ret = -EAGAIN; ++ break; ++ + case SNP_GUEST_REQ_INVALID_LEN: + /* Number of expected pages are returned in RBX */ + if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -31,6 +31,9 @@ + #define AAD_LEN 48 + #define MSG_HDR_VER 1 + ++#define SNP_REQ_MAX_RETRY_DURATION (60*HZ) ++#define SNP_REQ_RETRY_DELAY (2*HZ) ++ + struct snp_guest_crypto { + struct crypto_aead *tfm; + u8 *iv, *authtag; +@@ -322,7 +325,8 @@ static int enc_payload(struct snp_guest_ + + static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err) + { +- unsigned long err, override_err = 0; ++ unsigned long err = 0xff, override_err = 0; ++ unsigned long req_start = jiffies; + unsigned int override_npages = 0; + int rc; + +@@ -362,6 +366,19 @@ retry_request: + * user as an ioctl() return code. + */ + goto retry_request; ++ ++ /* ++ * The host may return SNP_GUEST_REQ_ERR_EBUSY if the request has been ++ * throttled. Retry in the driver to avoid returning and reusing the ++ * message sequence number on a different message. ++ */ ++ case -EAGAIN: ++ if (jiffies - req_start > SNP_REQ_MAX_RETRY_DURATION) { ++ rc = -ETIMEDOUT; ++ break; ++ } ++ schedule_timeout_killable(SNP_REQ_RETRY_DELAY); ++ goto retry_request; + } + + /* diff --git a/queue-6.1/virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch b/queue-6.1/virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch new file mode 100644 index 00000000000..22f8ca3afc8 --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch @@ -0,0 +1,97 @@ +From 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Tue, 7 Mar 2023 09:19:19 -0600 +Subject: virt/coco/sev-guest: Carve out the request issuing logic into a helper + +From: Borislav Petkov (AMD) + +commit 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 upstream. + +This makes the code flow a lot easier to follow. + +No functional changes. + + [ Tom: touchups. ] + +Signed-off-by: Borislav Petkov (AMD) +Signed-off-by: Tom Lendacky +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230307192449.24732-6-bp@alien8.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/virt/coco/sev-guest/sev-guest.c | 44 +++++++++++++++++++------------- + 1 file changed, 27 insertions(+), 17 deletions(-) + +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -320,27 +320,12 @@ static int enc_payload(struct snp_guest_ + return __enc_payload(snp_dev, req, payload, sz); + } + +-static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver, +- u8 type, void *req_buf, size_t req_sz, void *resp_buf, +- u32 resp_sz, __u64 *fw_err) ++static int __handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, __u64 *fw_err) + { + unsigned long err, override_err = 0; + unsigned int override_npages = 0; +- u64 seqno; + int rc; + +- /* Get message sequence and verify that its a non-zero */ +- seqno = snp_get_msg_seqno(snp_dev); +- if (!seqno) +- return -EIO; +- +- memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); +- +- /* Encrypt the userspace provided payload */ +- rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz); +- if (rc) +- return rc; +- + retry_request: + /* + * Call firmware to process the request. In this function the encrypted +@@ -349,7 +334,6 @@ retry_request: + * prevent reuse of the IV. + */ + rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); +- + switch (rc) { + case -ENOSPC: + /* +@@ -403,7 +387,33 @@ retry_request: + if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN) + return -EIO; + ++ return rc; ++} ++ ++static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, int msg_ver, ++ u8 type, void *req_buf, size_t req_sz, void *resp_buf, ++ u32 resp_sz, __u64 *fw_err) ++{ ++ u64 seqno; ++ int rc; ++ ++ /* Get message sequence and verify that its a non-zero */ ++ seqno = snp_get_msg_seqno(snp_dev); ++ if (!seqno) ++ return -EIO; ++ ++ memset(snp_dev->response, 0, sizeof(struct snp_guest_msg)); ++ ++ /* Encrypt the userspace provided payload */ ++ rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz); ++ if (rc) ++ return rc; ++ ++ rc = __handle_guest_request(snp_dev, exit_code, fw_err); + if (rc) { ++ if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN) ++ return rc; ++ + dev_alert(snp_dev->dev, + "Detected error from ASP request. rc: %d, fw_err: %llu\n", + rc, *fw_err); diff --git a/queue-6.1/virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch b/queue-6.1/virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch new file mode 100644 index 00000000000..852060141d1 --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch @@ -0,0 +1,48 @@ +From d6fd48eff7506bb866a54e40369df8899f2078a9 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Wed, 15 Feb 2023 11:01:42 +0100 +Subject: virt/coco/sev-guest: Check SEV_SNP attribute at probe time + +From: Borislav Petkov (AMD) + +commit d6fd48eff7506bb866a54e40369df8899f2078a9 upstream. + +No need to check it on every ioctl. And yes, this is a common SEV driver +but it does only SNP-specific operations currently. This can be +revisited later, when more use cases appear. + +No functional changes. + +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Tom Lendacky +Link: https://lore.kernel.org/r/20230307192449.24732-3-bp@alien8.de +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/sev.c | 3 --- + drivers/virt/coco/sev-guest/sev-guest.c | 3 +++ + 2 files changed, 3 insertions(+), 3 deletions(-) + +--- a/arch/x86/kernel/sev.c ++++ b/arch/x86/kernel/sev.c +@@ -2183,9 +2183,6 @@ int snp_issue_guest_request(u64 exit_cod + struct ghcb *ghcb; + int ret; + +- if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) +- return -ENODEV; +- + if (!fw_err) + return -EINVAL; + +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -705,6 +705,9 @@ static int __init sev_guest_probe(struct + void __iomem *mapping; + int ret; + ++ if (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP)) ++ return -ENODEV; ++ + if (!dev->platform_data) + return -ENODEV; + diff --git a/queue-6.1/virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch b/queue-6.1/virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch new file mode 100644 index 00000000000..b3d01768dac --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch @@ -0,0 +1,54 @@ +From fa4ae42cc60a7dea30e8f2db444b808d80862345 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Thu, 16 Feb 2023 10:50:11 +0100 +Subject: virt/coco/sev-guest: Convert the sw_exit_info_2 checking to a switch-case + +From: Borislav Petkov (AMD) + +commit fa4ae42cc60a7dea30e8f2db444b808d80862345 upstream. + +snp_issue_guest_request() checks the value returned by the hypervisor in +sw_exit_info_2 and returns a different error depending on it. + +Convert those checks into a switch-case to make it more readable when +more error values are going to be checked in the future. + +No functional changes. + +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Tom Lendacky +Link: https://lore.kernel.org/r/20230307192449.24732-8-bp@alien8.de +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/sev.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +--- a/arch/x86/kernel/sev.c ++++ b/arch/x86/kernel/sev.c +@@ -2210,15 +2210,21 @@ int snp_issue_guest_request(u64 exit_cod + goto e_put; + + *fw_err = ghcb->save.sw_exit_info_2; +- if (ghcb->save.sw_exit_info_2) { ++ switch (*fw_err) { ++ case 0: ++ break; ++ ++ case SNP_GUEST_REQ_INVALID_LEN: + /* 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) { ++ if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST) { + input->data_npages = ghcb_get_rbx(ghcb); + ret = -ENOSPC; +- } else { +- ret = -EIO; ++ break; + } ++ fallthrough; ++ default: ++ ret = -EIO; ++ break; + } + + e_put: diff --git a/queue-6.1/virt-coco-sev-guest-do-some-code-style-cleanups.patch b/queue-6.1/virt-coco-sev-guest-do-some-code-style-cleanups.patch new file mode 100644 index 00000000000..a855bb1a65f --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-do-some-code-style-cleanups.patch @@ -0,0 +1,44 @@ +From d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Wed, 15 Feb 2023 11:54:59 +0100 +Subject: virt/coco/sev-guest: Do some code style cleanups + +From: Borislav Petkov (AMD) + +commit d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 upstream. + +Remove unnecessary linebreaks, make the code more compact. + +No functional changes. + +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Tom Lendacky +Link: https://lore.kernel.org/r/20230307192449.24732-7-bp@alien8.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/virt/coco/sev-guest/sev-guest.c | 8 ++------ + 1 file changed, 2 insertions(+), 6 deletions(-) + +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -414,18 +414,14 @@ static int handle_guest_request(struct s + if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN) + return rc; + +- dev_alert(snp_dev->dev, +- "Detected error from ASP request. rc: %d, fw_err: %llu\n", +- rc, *fw_err); ++ dev_alert(snp_dev->dev, "Detected error from ASP request. rc: %d, fw_err: %llu\n", rc, *fw_err); + snp_disable_vmpck(snp_dev); + return rc; + } + + rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz); + if (rc) { +- dev_alert(snp_dev->dev, +- "Detected unexpected decode failure from ASP. rc: %d\n", +- rc); ++ dev_alert(snp_dev->dev, "Detected unexpected decode failure from ASP. rc: %d\n", rc); + snp_disable_vmpck(snp_dev); + return rc; + } diff --git a/queue-6.1/virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch b/queue-6.1/virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch new file mode 100644 index 00000000000..c816bb95254 --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch @@ -0,0 +1,50 @@ +From c5a338274bdb894f088767bea856be344d0ccaef Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Wed, 15 Feb 2023 11:43:43 +0100 +Subject: virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request() + +From: Borislav Petkov (AMD) + +commit c5a338274bdb894f088767bea856be344d0ccaef upstream. + +Call the function directly instead. + +No functional changes. + +Signed-off-by: Borislav Petkov (AMD) +Reviewed-by: Tom Lendacky +Link: https://lore.kernel.org/r/20230307192449.24732-5-bp@alien8.de +Signed-off-by: Greg Kroah-Hartman +--- + drivers/virt/coco/sev-guest/sev-guest.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -407,7 +407,8 @@ retry_request: + dev_alert(snp_dev->dev, + "Detected error from ASP request. rc: %d, fw_err: %llu\n", + rc, *fw_err); +- goto disable_vmpck; ++ snp_disable_vmpck(snp_dev); ++ return rc; + } + + rc = verify_and_dec_payload(snp_dev, resp_buf, resp_sz); +@@ -415,14 +416,11 @@ retry_request: + dev_alert(snp_dev->dev, + "Detected unexpected decode failure from ASP. rc: %d\n", + rc); +- goto disable_vmpck; ++ snp_disable_vmpck(snp_dev); ++ return rc; + } + + return 0; +- +-disable_vmpck: +- snp_disable_vmpck(snp_dev); +- return rc; + } + + static int get_report(struct snp_guest_dev *snp_dev, struct snp_guest_request_ioctl *arg) diff --git a/queue-6.1/virt-coco-sev-guest-simplify-extended-guest-request-handling.patch b/queue-6.1/virt-coco-sev-guest-simplify-extended-guest-request-handling.patch new file mode 100644 index 00000000000..e6ab6b05514 --- /dev/null +++ b/queue-6.1/virt-coco-sev-guest-simplify-extended-guest-request-handling.patch @@ -0,0 +1,144 @@ +From 970ab823743fb54b42002ec76c51481f67436444 Mon Sep 17 00:00:00 2001 +From: "Borislav Petkov (AMD)" +Date: Wed, 15 Feb 2023 11:39:41 +0100 +Subject: virt/coco/sev-guest: Simplify extended guest request handling + +From: Borislav Petkov (AMD) + +commit 970ab823743fb54b42002ec76c51481f67436444 upstream. + +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. + + [ Tom: check override_err instead of err. ] + +Signed-off-by: Borislav Petkov (AMD) +Signed-off-by: Tom Lendacky +Signed-off-by: Borislav Petkov (AMD) +Link: https://lore.kernel.org/r/20230307192449.24732-4-bp@alien8.de +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kernel/sev.c | 11 ++++--- + drivers/virt/coco/sev-guest/sev-guest.c | 48 +++++++++++++++++--------------- + 2 files changed, 32 insertions(+), 27 deletions(-) + +--- a/arch/x86/kernel/sev.c ++++ b/arch/x86/kernel/sev.c +@@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_cod + 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: +--- a/drivers/virt/coco/sev-guest/sev-guest.c ++++ b/drivers/virt/coco/sev-guest/sev-guest.c +@@ -324,7 +324,8 @@ static int handle_guest_request(struct s + 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; + +@@ -340,6 +341,7 @@ static int handle_guest_request(struct s + 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 +@@ -348,17 +350,24 @@ static int handle_guest_request(struct s + */ + 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 +@@ -368,15 +377,7 @@ static int handle_guest_request(struct s + * 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; + } + + /* +@@ -388,7 +389,10 @@ static int handle_guest_request(struct s + snp_inc_msg_seqno(snp_dev); + + if (fw_err) +- *fw_err = err; ++ *fw_err = override_err ?: err; ++ ++ if (override_npages) ++ snp_dev->input.data_npages = override_npages; + + /* + * If an extended guest request was issued and the supplied certificate +@@ -396,7 +400,7 @@ static int handle_guest_request(struct s + * prevent IV reuse. If the standard request was successful, return -EIO + * back to the caller as would have originally been returned. + */ +- if (!rc && err == SNP_GUEST_REQ_INVALID_LEN) ++ if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN) + return -EIO; + + if (rc) {