Commit 970ab823 authored by Borislav Petkov (AMD)'s avatar Borislav Petkov (AMD)

virt/coco/sev-guest: Simplify extended guest request handling

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: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: default avatarTom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: default avatarBorislav Petkov (AMD) <bp@alien8.de>
Link: https://lore.kernel.org/r/20230307192449.24732-4-bp@alien8.de
parent d6fd48ef
...@@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned ...@@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
if (ret) if (ret)
goto e_put; goto e_put;
*fw_err = ghcb->save.sw_exit_info_2;
if (ghcb->save.sw_exit_info_2) { if (ghcb->save.sw_exit_info_2) {
/* Number of expected pages are returned in RBX */ /* Number of expected pages are returned in RBX */
if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && 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); input->data_npages = ghcb_get_rbx(ghcb);
ret = -ENOSPC;
*fw_err = ghcb->save.sw_exit_info_2; } else {
ret = -EIO;
ret = -EIO; }
} }
e_put: e_put:
......
...@@ -322,7 +322,8 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in ...@@ -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, u8 type, void *req_buf, size_t req_sz, void *resp_buf,
u32 resp_sz, __u64 *fw_err) u32 resp_sz, __u64 *fw_err)
{ {
unsigned long err; unsigned long err, override_err = 0;
unsigned int override_npages = 0;
u64 seqno; u64 seqno;
int rc; int rc;
...@@ -338,6 +339,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in ...@@ -338,6 +339,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
if (rc) if (rc)
return rc; return rc;
retry_request:
/* /*
* Call firmware to process the request. In this function the encrypted * Call firmware to process the request. In this function the encrypted
* message enters shared memory with the host. So after this call the * 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 ...@@ -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); rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
/* switch (rc) {
* If the extended guest request fails due to having too small of a case -ENOSPC:
* certificate data buffer, retry the same guest request without the /*
* extended data request in order to increment the sequence number * If the extended guest request fails due to having too
* and thus avoid IV reuse. * small of a certificate data buffer, retry the same
*/ * guest request without the extended data request in
if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST && * order to increment the sequence number and thus avoid
err == SNP_GUEST_REQ_INVALID_LEN) { * IV reuse.
const unsigned int certs_npages = snp_dev->input.data_npages; */
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 * If this call to the firmware succeeds, the sequence number can
...@@ -366,15 +375,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in ...@@ -366,15 +375,7 @@ 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 * of the VMPCK and the error code being propagated back to the
* user as an ioctl() return code. * user as an ioctl() return code.
*/ */
rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err); goto retry_request;
/*
* 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;
} }
/* /*
...@@ -386,7 +387,10 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in ...@@ -386,7 +387,10 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
snp_inc_msg_seqno(snp_dev); snp_inc_msg_seqno(snp_dev);
if (fw_err) 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 * If an extended guest request was issued and the supplied certificate
...@@ -394,7 +398,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in ...@@ -394,7 +398,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
* prevent IV reuse. If the standard request was successful, return -EIO * prevent IV reuse. If the standard request was successful, return -EIO
* back to the caller as would have originally been returned. * 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; return -EIO;
if (rc) { if (rc) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment