Skip to content

Commit 9650061

Browse files
deeglazebp3tk0v
authored andcommitted
virt/coco/sev-guest: Double-buffer messages
The encryption algorithms read and write directly to shared unencrypted memory, which may leak information as well as permit the host to tamper with the message integrity. Instead, copy whole messages in or out as needed before doing any computation on them. Fixes: d5af44d ("x86/sev: Provide support for SNP guest request NAEs") Signed-off-by: Dionna Glaze <dionnaglaze@google.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Link: https://lore.kernel.org/r/20230214164638.1189804-3-dionnaglaze@google.com
1 parent dbf07b5 commit 9650061

1 file changed

Lines changed: 23 additions & 4 deletions

File tree

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,15 @@ struct snp_guest_dev {
4646

4747
void *certs_data;
4848
struct snp_guest_crypto *crypto;
49+
/* request and response are in unencrypted memory */
4950
struct snp_guest_msg *request, *response;
51+
52+
/*
53+
* Avoid information leakage by double-buffering shared messages
54+
* in fields that are in regular encrypted memory.
55+
*/
56+
struct snp_guest_msg secret_request, secret_response;
57+
5058
struct snp_secrets_page_layout *layout;
5159
struct snp_req_data input;
5260
u32 *os_area_msg_seqno;
@@ -266,14 +274,17 @@ static int dec_payload(struct snp_guest_dev *snp_dev, struct snp_guest_msg *msg,
266274
static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload, u32 sz)
267275
{
268276
struct snp_guest_crypto *crypto = snp_dev->crypto;
269-
struct snp_guest_msg *resp = snp_dev->response;
270-
struct snp_guest_msg *req = snp_dev->request;
277+
struct snp_guest_msg *resp = &snp_dev->secret_response;
278+
struct snp_guest_msg *req = &snp_dev->secret_request;
271279
struct snp_guest_msg_hdr *req_hdr = &req->hdr;
272280
struct snp_guest_msg_hdr *resp_hdr = &resp->hdr;
273281

274282
dev_dbg(snp_dev->dev, "response [seqno %lld type %d version %d sz %d]\n",
275283
resp_hdr->msg_seqno, resp_hdr->msg_type, resp_hdr->msg_version, resp_hdr->msg_sz);
276284

285+
/* Copy response from shared memory to encrypted memory. */
286+
memcpy(resp, snp_dev->response, sizeof(*resp));
287+
277288
/* Verify that the sequence counter is incremented by 1 */
278289
if (unlikely(resp_hdr->msg_seqno != (req_hdr->msg_seqno + 1)))
279290
return -EBADMSG;
@@ -297,7 +308,7 @@ static int verify_and_dec_payload(struct snp_guest_dev *snp_dev, void *payload,
297308
static int enc_payload(struct snp_guest_dev *snp_dev, u64 seqno, int version, u8 type,
298309
void *payload, size_t sz)
299310
{
300-
struct snp_guest_msg *req = snp_dev->request;
311+
struct snp_guest_msg *req = &snp_dev->secret_request;
301312
struct snp_guest_msg_hdr *hdr = &req->hdr;
302313

303314
memset(req, 0, sizeof(*req));
@@ -417,13 +428,21 @@ static int handle_guest_request(struct snp_guest_dev *snp_dev, u64 exit_code, in
417428
if (!seqno)
418429
return -EIO;
419430

431+
/* Clear shared memory's response for the host to populate. */
420432
memset(snp_dev->response, 0, sizeof(struct snp_guest_msg));
421433

422-
/* Encrypt the userspace provided payload */
434+
/* Encrypt the userspace provided payload in snp_dev->secret_request. */
423435
rc = enc_payload(snp_dev, seqno, msg_ver, type, req_buf, req_sz);
424436
if (rc)
425437
return rc;
426438

439+
/*
440+
* Write the fully encrypted request to the shared unencrypted
441+
* request page.
442+
*/
443+
memcpy(snp_dev->request, &snp_dev->secret_request,
444+
sizeof(snp_dev->secret_request));
445+
427446
rc = __handle_guest_request(snp_dev, exit_code, fw_err);
428447
if (rc) {
429448
if (rc == -EIO && *fw_err == SNP_GUEST_REQ_INVALID_LEN)

0 commit comments

Comments
 (0)