Skip to content

Commit 7f03de1

Browse files
committed
crypto: ccp - Fix locking on alloc failure handling
JIRA: https://issues.redhat.com/browse/RHEL-106909 JIRA: https://issues.redhat.com/browse/RHEL-107608 Upstream Status: merged into the linux.git commit b4abecc Author: Alexey Kardashevskiy <[email protected]> Date: Tue Jun 17 19:43:54 2025 +1000 crypto: ccp - Fix locking on alloc failure handling 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: Vladis Dronov <[email protected]>
1 parent 7b20e62 commit 7f03de1

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
@@ -433,7 +433,7 @@ static int rmp_mark_pages_firmware(unsigned long paddr, unsigned int npages, boo
433433
return rc;
434434
}
435435

436-
static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order)
436+
static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order, bool locked)
437437
{
438438
unsigned long npages = 1ul << order, paddr;
439439
struct sev_device *sev;
@@ -452,7 +452,7 @@ static struct page *__snp_alloc_firmware_pages(gfp_t gfp_mask, int order)
452452
return page;
453453

454454
paddr = __pa((unsigned long)page_address(page));
455-
if (rmp_mark_pages_firmware(paddr, npages, false))
455+
if (rmp_mark_pages_firmware(paddr, npages, locked))
456456
return NULL;
457457

458458
return page;
@@ -462,7 +462,7 @@ void *snp_alloc_firmware_page(gfp_t gfp_mask)
462462
{
463463
struct page *page;
464464

465-
page = __snp_alloc_firmware_pages(gfp_mask, 0);
465+
page = __snp_alloc_firmware_pages(gfp_mask, 0, false);
466466

467467
return page ? page_address(page) : NULL;
468468
}
@@ -497,7 +497,7 @@ static void *sev_fw_alloc(unsigned long len)
497497
{
498498
struct page *page;
499499

500-
page = __snp_alloc_firmware_pages(GFP_KERNEL, get_order(len));
500+
page = __snp_alloc_firmware_pages(GFP_KERNEL, get_order(len), true);
501501
if (!page)
502502
return NULL;
503503

0 commit comments

Comments
 (0)