Skip to content

Commit 16f3b39

Browse files
aikopsiff
authored andcommitted
crypto: ccp - Fix locking on alloc failure handling
[ Upstream commit b4abeccb8d39db7d9b51cb0098d6458760b30a75 ] The __snp_alloc_firmware_pages() helper allocates pages in the firmware state (alloc + rmpupdate). In case of failed rmpupdate, it tries reclaiming pages with already changed state. This requires calling the PSP firmware and since there is sev_cmd_mutex to guard such calls, the helper takes a "locked" parameter so specify if the lock needs to be held. Most calls happen from snp_alloc_firmware_page() which executes without the lock. However commit 24512af ("crypto: ccp: Handle the legacy TMR allocation when SNP is enabled") switched sev_fw_alloc() from alloc_pages() (which does not call the PSP) to __snp_alloc_firmware_pages() (which does) but did not account for the fact that sev_fw_alloc() is called from __sev_platform_init_locked() (via __sev_platform_init_handle_tmr()) and executes with the lock held. Add a "locked" parameter to __snp_alloc_firmware_pages(). Make sev_fw_alloc() use the new parameter to prevent potential deadlock in rmp_mark_pages_firmware() if rmpupdate() failed. Fixes: 24512af ("crypto: ccp: Handle the legacy TMR allocation when SNP is enabled") Signed-off-by: Alexey Kardashevskiy <[email protected]> Reviewed-by: Tom Lendacky <[email protected]> Reviewed-by: Pratik R. Sampat <[email protected]> Signed-off-by: Herbert Xu <[email protected]> Signed-off-by: Sasha Levin <[email protected]> (cherry picked from commit 155c1d4c49079f24a4b5b0c51ceb94e73cacd7ac)
1 parent 0f51763 commit 16f3b39

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

drivers/crypto/ccp/sev-dev.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ static int rmp_mark_pages_firmware(unsigned long paddr, unsigned int npages, boo
424424
return rc;
425425
}
426426

427-
static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order)
427+
static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order, bool locked)
428428
{
429429
unsigned long npages = 1ul << order, paddr;
430430
struct sev_device *sev;
@@ -443,7 +443,7 @@ static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order)
443443
return page;
444444

445445
paddr = __pa((unsigned long)page_address(page));
446-
if (rmp_mark_pages_firmware(paddr, npages, false))
446+
if (rmp_mark_pages_firmware(paddr, npages, locked))
447447
return NULL;
448448

449449
return page;
@@ -453,7 +453,7 @@ void *snp_alloc_firmware_page(gfp_t gfp_mask)
453453
{
454454
struct page *page;
455455

456-
page = __snp_alloc_firmware_pages(gfp_mask, 0);
456+
page = __snp_alloc_firmware_pages(gfp_mask, 0, false);
457457

458458
return page ? page_address(page) : NULL;
459459
}
@@ -488,7 +488,7 @@ static void *sev_fw_alloc(unsigned long len)
488488
{
489489
struct page *page;
490490

491-
page = __snp_alloc_firmware_pages(GFP_KERNEL, get_order(len));
491+
page = __snp_alloc_firmware_pages(GFP_KERNEL, get_order(len), true);
492492
if (!page)
493493
return NULL;
494494

0 commit comments

Comments
 (0)