]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.2-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Mar 2023 13:24:57 +0000 (14:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 20 Mar 2023 13:24:57 +0000 (14:24 +0100)
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

queue-6.2/series
queue-6.2/virt-coco-sev-guest-add-throttling-awareness.patch [new file with mode: 0644]
queue-6.2/virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch [new file with mode: 0644]
queue-6.2/virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch [new file with mode: 0644]
queue-6.2/virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch [new file with mode: 0644]
queue-6.2/virt-coco-sev-guest-do-some-code-style-cleanups.patch [new file with mode: 0644]
queue-6.2/virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch [new file with mode: 0644]
queue-6.2/virt-coco-sev-guest-simplify-extended-guest-request-handling.patch [new file with mode: 0644]

index 7a8f76184bff0d5e3c03a5e924465cc12b179152..e86bbae28ee5b225cb41daf6d8e34568f60bea66 100644 (file)
@@ -202,3 +202,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.2/virt-coco-sev-guest-add-throttling-awareness.patch b/queue-6.2/virt-coco-sev-guest-add-throttling-awareness.patch
new file mode 100644 (file)
index 0000000..01650ba
--- /dev/null
@@ -0,0 +1,138 @@
+From 72f7754dcf31c87c92c0c353dcf747814cc5ce10 Mon Sep 17 00:00:00 2001
+From: Dionna Glaze <dionnaglaze@google.com>
+Date: Thu, 16 Feb 2023 11:08:02 +0100
+Subject: virt/coco/sev-guest: Add throttling awareness
+
+From: Dionna Glaze <dionnaglaze@google.com>
+
+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 <dionnaglaze@google.com>
+Co-developed-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: <stable@kernel.org> # d6fd48eff750 ("virt/coco/sev-guest: Check SEV_SNP attribute at probe time")
+Cc: <stable@kernel.org> # 970ab823743f (" virt/coco/sev-guest: Simplify extended guest request handling")
+Cc: <stable@kernel.org> # c5a338274bdb ("virt/coco/sev-guest: Remove the disable_vmpck label in handle_guest_request()")
+Cc: <stable@kernel.org> # 0fdb6cc7c89c ("virt/coco/sev-guest: Carve out the request issuing logic into a helper")
+Cc: <stable@kernel.org> # d25bae7dc7b0 ("virt/coco/sev-guest: Do some code style cleanups")
+Cc: <stable@kernel.org> # 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 <gregkh@linuxfoundation.org>
+---
+ 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;
+@@ -320,7 +323,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;
+@@ -360,6 +364,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.2/virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch b/queue-6.2/virt-coco-sev-guest-carve-out-the-request-issuing-logic-into-a-helper.patch
new file mode 100644 (file)
index 0000000..b14f7b8
--- /dev/null
@@ -0,0 +1,97 @@
+From 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+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) <bp@alien8.de>
+
+commit 0fdb6cc7c89cb5e0cbc45dbdbafb8e3fb92ddc95 upstream.
+
+This makes the code flow a lot easier to follow.
+
+No functional changes.
+
+  [ Tom: touchups. ]
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230307192449.24732-6-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -318,27 +318,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
+@@ -347,7 +332,6 @@ retry_request:
+        * prevent reuse of the IV.
+        */
+       rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
+-
+       switch (rc) {
+       case -ENOSPC:
+               /*
+@@ -401,7 +385,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.2/virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch b/queue-6.2/virt-coco-sev-guest-check-sev_snp-attribute-at-probe-time.patch
new file mode 100644 (file)
index 0000000..89e8c46
--- /dev/null
@@ -0,0 +1,48 @@
+From d6fd48eff7506bb866a54e40369df8899f2078a9 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+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) <bp@alien8.de>
+
+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) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-3-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -703,6 +703,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.2/virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch b/queue-6.2/virt-coco-sev-guest-convert-the-sw_exit_info_2-checking-to-a-switch-case.patch
new file mode 100644 (file)
index 0000000..b3d0176
--- /dev/null
@@ -0,0 +1,54 @@
+From fa4ae42cc60a7dea30e8f2db444b808d80862345 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+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) <bp@alien8.de>
+
+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) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-8-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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.2/virt-coco-sev-guest-do-some-code-style-cleanups.patch b/queue-6.2/virt-coco-sev-guest-do-some-code-style-cleanups.patch
new file mode 100644 (file)
index 0000000..9417a15
--- /dev/null
@@ -0,0 +1,44 @@
+From d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Feb 2023 11:54:59 +0100
+Subject: virt/coco/sev-guest: Do some code style cleanups
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+commit d25bae7dc7b0668cb2a1325c64eb32d5fea4e5a9 upstream.
+
+Remove unnecessary linebreaks, make the code more compact.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-7-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -412,18 +412,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.2/virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch b/queue-6.2/virt-coco-sev-guest-remove-the-disable_vmpck-label-in-handle_guest_request.patch
new file mode 100644 (file)
index 0000000..fa25ece
--- /dev/null
@@ -0,0 +1,50 @@
+From c5a338274bdb894f088767bea856be344d0ccaef Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+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) <bp@alien8.de>
+
+commit c5a338274bdb894f088767bea856be344d0ccaef upstream.
+
+Call the function directly instead.
+
+No functional changes.
+
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
+Link: https://lore.kernel.org/r/20230307192449.24732-5-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -405,7 +405,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);
+@@ -413,14 +414,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.2/virt-coco-sev-guest-simplify-extended-guest-request-handling.patch b/queue-6.2/virt-coco-sev-guest-simplify-extended-guest-request-handling.patch
new file mode 100644 (file)
index 0000000..2c72e2f
--- /dev/null
@@ -0,0 +1,144 @@
+From 970ab823743fb54b42002ec76c51481f67436444 Mon Sep 17 00:00:00 2001
+From: "Borislav Petkov (AMD)" <bp@alien8.de>
+Date: Wed, 15 Feb 2023 11:39:41 +0100
+Subject: virt/coco/sev-guest: Simplify extended guest request handling
+
+From: Borislav Petkov (AMD) <bp@alien8.de>
+
+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) <bp@alien8.de>
+Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Link: https://lore.kernel.org/r/20230307192449.24732-4-bp@alien8.de
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -322,7 +322,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;
+@@ -338,6 +339,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
+@@ -346,17 +348,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
+@@ -366,15 +375,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;
+       }
+       /*
+@@ -386,7 +387,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
+@@ -394,7 +398,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) {