mirror of
https://github.com/torvalds/linux.git
synced 2026-06-01 19:13:47 +02:00
crypto: ccp - Fix a case where SNP_SHUTDOWN is missed
If page reclaim fails in sev_ioctl_do_snp_platform_status() and SNP was
moved from UNINIT to INIT for the function, SNP is not moved back to
UNINIT state. Additionally, SNP is not required to be initialized in order
to execute the SNP_PLATFORM_STATUS command, so don't attempt to move to
INIT state and let SNP_PLATFORM_STATUS report the status as is.
Fixes: ceac7fb89e ("crypto: ccp - Ensure implicit SEV/SNP init and shutdown in ioctls")
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Reviewed-by: Tycho Andersen (AMD) <tycho@kernel.org>
Reviewed-by: Alexey Kardashevskiy <aik@amd.com>
Signed-off-by: Tycho Andersen (AMD) <tycho@kernel.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
This commit is contained in:
parent
f7738c07b5
commit
551120148b
|
|
@ -2378,11 +2378,10 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)
|
||||||
static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
|
static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
|
||||||
{
|
{
|
||||||
struct sev_device *sev = psp_master->sev_data;
|
struct sev_device *sev = psp_master->sev_data;
|
||||||
bool shutdown_required = false;
|
|
||||||
struct sev_data_snp_addr buf;
|
struct sev_data_snp_addr buf;
|
||||||
struct page *status_page;
|
struct page *status_page;
|
||||||
int ret, error;
|
|
||||||
void *data;
|
void *data;
|
||||||
|
int ret;
|
||||||
|
|
||||||
if (!argp->data)
|
if (!argp->data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -2393,31 +2392,35 @@ static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
|
||||||
|
|
||||||
data = page_address(status_page);
|
data = page_address(status_page);
|
||||||
|
|
||||||
if (!sev->snp_initialized) {
|
|
||||||
ret = snp_move_to_init_state(argp, &shutdown_required);
|
|
||||||
if (ret)
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Firmware expects status page to be in firmware-owned state, otherwise
|
* SNP_PLATFORM_STATUS can be executed in any SNP state. But if executed
|
||||||
* it will report firmware error code INVALID_PAGE_STATE (0x1A).
|
* when SNP has been initialized, the status page must be firmware-owned.
|
||||||
|
*/
|
||||||
|
if (sev->snp_initialized) {
|
||||||
|
/*
|
||||||
|
* Firmware expects the status page to be in Firmware state,
|
||||||
|
* otherwise it will report an error INVALID_PAGE_STATE.
|
||||||
*/
|
*/
|
||||||
if (rmp_mark_pages_firmware(__pa(data), 1, true)) {
|
if (rmp_mark_pages_firmware(__pa(data), 1, true)) {
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
buf.address = __psp_pa(data);
|
buf.address = __psp_pa(data);
|
||||||
ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error);
|
ret = __sev_do_cmd_locked(SEV_CMD_SNP_PLATFORM_STATUS, &buf, &argp->error);
|
||||||
|
|
||||||
|
if (sev->snp_initialized) {
|
||||||
/*
|
/*
|
||||||
* Status page will be transitioned to Reclaim state upon success, or
|
* The status page will be in Reclaim state on success, or left
|
||||||
* left in Firmware state in failure. Use snp_reclaim_pages() to
|
* in Firmware state on failure. Use snp_reclaim_pages() to
|
||||||
* transition either case back to Hypervisor-owned state.
|
* transition either case back to Hypervisor-owned state.
|
||||||
*/
|
*/
|
||||||
if (snp_reclaim_pages(__pa(data), 1, true))
|
if (snp_reclaim_pages(__pa(data), 1, true)) {
|
||||||
|
snp_leak_pages(__page_to_pfn(status_page), 1);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
@ -2427,9 +2430,6 @@ static int sev_ioctl_do_snp_platform_status(struct sev_issue_cmd *argp)
|
||||||
ret = -EFAULT;
|
ret = -EFAULT;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (shutdown_required)
|
|
||||||
__sev_snp_shutdown_locked(&error, false);
|
|
||||||
|
|
||||||
__free_pages(status_page, 0);
|
__free_pages(status_page, 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user