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: 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
This commit is contained in:
parent
d6fd48eff7
commit
970ab82374
@ -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:
|
||||
|
@ -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,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
|
||||
* 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 snp_guest_dev *snp_dev, u64 exit_code, in
|
||||
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 snp_guest_dev *snp_dev, u64 exit_code, in
|
||||
* 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) {
|
||||
|
Loading…
Reference in New Issue
Block a user