Skip to content

Commit 970ab82

Browse files
committed
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) <[email protected]> Signed-off-by: Tom Lendacky <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent d6fd48e commit 970ab82

File tree

2 files changed

+32
-27
lines changed

2 files changed

+32
-27
lines changed

arch/x86/kernel/sev.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2209,15 +2209,16 @@ int snp_issue_guest_request(u64 exit_code, struct snp_req_data *input, unsigned
22092209
if (ret)
22102210
goto e_put;
22112211

2212+
*fw_err = ghcb->save.sw_exit_info_2;
22122213
if (ghcb->save.sw_exit_info_2) {
22132214
/* Number of expected pages are returned in RBX */
22142215
if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
2215-
ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN)
2216+
ghcb->save.sw_exit_info_2 == SNP_GUEST_REQ_INVALID_LEN) {
22162217
input->data_npages = ghcb_get_rbx(ghcb);
2217-
2218-
*fw_err = ghcb->save.sw_exit_info_2;
2219-
2220-
ret = -EIO;
2218+
ret = -ENOSPC;
2219+
} else {
2220+
ret = -EIO;
2221+
}
22212222
}
22222223

22232224
e_put:

drivers/virt/coco/sev-guest/sev-guest.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,8 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
322322
u8 type, void *req_buf, size_t req_sz, void *resp_buf,
323323
u32 resp_sz, __u64 *fw_err)
324324
{
325-
unsigned long err;
325+
unsigned long err, override_err = 0;
326+
unsigned int override_npages = 0;
326327
u64 seqno;
327328
int rc;
328329

@@ -338,6 +339,7 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
338339
if (rc)
339340
return rc;
340341

342+
retry_request:
341343
/*
342344
* Call firmware to process the request. In this function the encrypted
343345
* 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
346348
*/
347349
rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
348350

349-
/*
350-
* If the extended guest request fails due to having too small of a
351-
* certificate data buffer, retry the same guest request without the
352-
* extended data request in order to increment the sequence number
353-
* and thus avoid IV reuse.
354-
*/
355-
if (exit_code == SVM_VMGEXIT_EXT_GUEST_REQUEST &&
356-
err == SNP_GUEST_REQ_INVALID_LEN) {
357-
const unsigned int certs_npages = snp_dev->input.data_npages;
351+
switch (rc) {
352+
case -ENOSPC:
353+
/*
354+
* If the extended guest request fails due to having too
355+
* small of a certificate data buffer, retry the same
356+
* guest request without the extended data request in
357+
* order to increment the sequence number and thus avoid
358+
* IV reuse.
359+
*/
360+
override_npages = snp_dev->input.data_npages;
361+
exit_code = SVM_VMGEXIT_GUEST_REQUEST;
358362

359-
exit_code = SVM_VMGEXIT_GUEST_REQUEST;
363+
/*
364+
* Override the error to inform callers the given extended
365+
* request buffer size was too small and give the caller the
366+
* required buffer size.
367+
*/
368+
override_err = SNP_GUEST_REQ_INVALID_LEN;
360369

361370
/*
362371
* 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
366375
* of the VMPCK and the error code being propagated back to the
367376
* user as an ioctl() return code.
368377
*/
369-
rc = snp_issue_guest_request(exit_code, &snp_dev->input, &err);
370-
371-
/*
372-
* Override the error to inform callers the given extended
373-
* request buffer size was too small and give the caller the
374-
* required buffer size.
375-
*/
376-
err = SNP_GUEST_REQ_INVALID_LEN;
377-
snp_dev->input.data_npages = certs_npages;
378+
goto retry_request;
378379
}
379380

380381
/*
@@ -386,15 +387,18 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
386387
snp_inc_msg_seqno(snp_dev);
387388

388389
if (fw_err)
389-
*fw_err = err;
390+
*fw_err = override_err ?: err;
391+
392+
if (override_npages)
393+
snp_dev->input.data_npages = override_npages;
390394

391395
/*
392396
* If an extended guest request was issued and the supplied certificate
393397
* buffer was not large enough, a standard guest request was issued to
394398
* prevent IV reuse. If the standard request was successful, return -EIO
395399
* back to the caller as would have originally been returned.
396400
*/
397-
if (!rc && err == SNP_GUEST_REQ_INVALID_LEN)
401+
if (!rc && override_err == SNP_GUEST_REQ_INVALID_LEN)
398402
return -EIO;
399403

400404
if (rc) {

0 commit comments

Comments
 (0)