
Exploit for CVE-2024-21980 targeting AMD SEV firmware to decrypt arbitrary memory of decommissioned SEV-SNP guests via a command buffer enforcement bypass.
This repo contains an exploit for a vulnerability in the SEV firmware. The exploit allows decrypting arbitrary memory of an SEV-SNP guest after it's been decommissioned.
Tested on version 1.55.16 (latest as of time of writing).
The SEV firmware has a table called master_handler_table containing function pointers for all commands with a few more properties relevant for the commands. Two of those additional properties are cmd_buf_type and snp_cmd_buf_enforcement. cmd_buf_type determines whether the command buffer should be copied to and/or from host memory. snp_cmd_buf_enforcement determines whether these copy operations should be subject to checks verifying that memory backing the command buffer is in the FIRMWARE or DEFAULT state. Commands for which cmd_buf_type is either CMD_BUF_OUTPUT_ONLY, CMD_BUF_INPUT_AND_OUTPUT, or CMD_BUF_INPUT_AND_OUTPUT_ERROR should all have snp_cmd_buf_enforcement be set to true. Otherwise writing back the command output could cause memory corruption inside the RMP covered area. snp_cmd_buf_enforcement is true for all such commands with one exception - SEV_MCMD_ID_ATTESTATION: This command has cmd_buf_type set to CMD_BUF_INPUT_AND_OUTPUT_ERROR, but also has snp_cmd_buf_enforcement set to false. As a result it's possible to execute SEV_MCMD_ID_ATTESTATION with a command buffer pointing at RMP-covered memory and have that memory be corrupted once the output is written back.
It don't see why SEV_MCMD_ID_ATTESTATION would need to be an exception, it seems plausible to me that this could be a typo/copy-paste mistake.
SEV_MCMD_ID_ATTESTATION only writes to a single field length (4 bytes) in the command buffer and so those are the only bytes we can use to corrupt memory. SEV_MCMD_ID_ATTESTATION always writes the same value - 0x000000d0. Fortunately there are no alignment requirements on the command buffer and so we can shift the command buffer repeatedly to corrupt a larger range of contigious memory. We'll use this to corrupt the first 16 bytes of a guest context page with a static pattern. Those first 16 bytes contain the UMC key seed and so by forcing it to a static value, we can force the guest's encryption key to a static value.
The exploit provided here is heavily based on the one I provided for SWPSIRT-2684/CVE-2023-31355.
To exploit the vulnerability we can execute the following steps:
SEV_MCMD_ID_ATTESTATION. Keep this guest running.0x2000 for the victim guest. Any other address in the RMP covered area would also do though a fixed address is useful for debugging.0x2000 for the attacker guest. This has to be the same address used in step 1.SNP_DBG_ENCRYPT command to decrypt the victim guest's memory using the attacker guest's context page. This will succeed because the victim guest and the attacker guest share a UMC key seed.The impact here should be at least the same as with SWPSIRT-2684. It's unclear to me at this time if this bug can be used to decrypt memory of a running guest before it's been decommissioned.
snp_cmd_buf_enforcement should be set to true for SEV_MCMD_ID_ATTESTATION.
Interestingly the Linux KVM host support patches do not need to be updates because they already list SEV_CMD_ATTESTATION_REPORT in sev_cmd_buf_writable as a command that requires its command buffer to be in the FIRMWARE state. Changes may or may not be needed for other hypervisors.