Skip to content

Commit fd948c3

Browse files
00xcbp3tk0v
authored andcommitted
virt: sev-guest: Explicitly leak pages in unknown state
When set_memory_{encrypted,decrypted}() fail, the user cannot know at which point the function failed, meaning that the pages are left in an unknown state from the point of view of the caller. Since the pages may be left in an unencrypted state, they are not suitable for general use, and cannot be returned safely to the buddy allocator. Avoid the issue by never freeing the pages, and then do the proper accounting by calling snp_leak_pages(). Fixes: 3e385c0 ("virt: sev-guest: Move SNP Guest Request data pages handling under snp_cmd_mutex") Signed-off-by: Carlos López <clopez@suse.de> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Cc: stable@kernel.org
1 parent 4412634 commit fd948c3

1 file changed

Lines changed: 7 additions & 3 deletions

File tree

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

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
176176
struct snp_guest_req req = {};
177177
int ret, npages = 0, resp_len;
178178
sockptr_t certs_address;
179+
u64 pfn;
179180

180181
if (sockptr_is_null(io->req_data) || sockptr_is_null(io->resp_data))
181182
return -EINVAL;
@@ -215,10 +216,11 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
215216
if (!req.certs_data)
216217
return -ENOMEM;
217218

219+
pfn = PHYS_PFN(virt_to_phys(req.certs_data));
218220
ret = set_memory_decrypted((unsigned long)req.certs_data, npages);
219221
if (ret) {
220222
pr_err("failed to mark page shared, ret=%d\n", ret);
221-
free_pages_exact(req.certs_data, npages << PAGE_SHIFT);
223+
snp_leak_pages(pfn, npages);
222224
return -EFAULT;
223225
}
224226

@@ -272,10 +274,12 @@ static int get_ext_report(struct snp_guest_dev *snp_dev, struct snp_guest_reques
272274
kfree(report_resp);
273275
e_free_data:
274276
if (npages) {
275-
if (set_memory_encrypted((unsigned long)req.certs_data, npages))
277+
if (set_memory_encrypted((unsigned long)req.certs_data, npages)) {
276278
WARN_ONCE(ret, "failed to restore encryption mask (leak it)\n");
277-
else
279+
snp_leak_pages(pfn, npages);
280+
} else {
278281
free_pages_exact(req.certs_data, npages << PAGE_SHIFT);
282+
}
279283
}
280284
return ret;
281285
}

0 commit comments

Comments
 (0)