KVM: SEV: Add KVM_SEV_SNP_ENABLE_REQ_CERTS command

Introduce a new command for KVM_MEMORY_ENCRYPT_OP ioctl that can be used
to enable fetching of endorsement key certificates from userspace via
the new KVM_EXIT_SNP_REQ_CERTS exit type. Also introduce a new
KVM_X86_SEV_SNP_REQ_CERTS KVM device attribute so that userspace can
query whether the kernel supports the new command/exit.

Suggested-by: Sean Christopherson <seanjc@google.com>
Reviewed-by: Liam Merwick <liam.merwick@oracle.com>
Tested-by: Liam Merwick <liam.merwick@oracle.com>
Signed-off-by: Michael Roth <michael.roth@amd.com>
Link: https://patch.msgid.link/20260109231732.1160759-3-michael.roth@amd.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
Michael Roth
2026-01-09 17:17:33 -06:00
committed by Sean Christopherson
parent fa9893fadb
commit 20c3c4108d
3 changed files with 69 additions and 1 deletions

View File

@@ -572,6 +572,52 @@ Returns: 0 on success, -negative on error
See SNP_LAUNCH_FINISH in the SEV-SNP specification [snp-fw-abi]_ for further
details on the input parameters in ``struct kvm_sev_snp_launch_finish``.
21. KVM_SEV_SNP_ENABLE_REQ_CERTS
--------------------------------
The KVM_SEV_SNP_ENABLE_REQ_CERTS command will configure KVM to exit to
userspace with a ``KVM_EXIT_SNP_REQ_CERTS`` exit type as part of handling
a guest attestation report, which will to allow userspace to provide a
certificate corresponding to the endorsement key used by firmware to sign
that attestation report.
Returns: 0 on success, -negative on error
NOTE: The endorsement key used by firmware may change as a result of
management activities like updating SEV-SNP firmware or loading new
endorsement keys, so some care should be taken to keep the returned
certificate data in sync with the actual endorsement key in use by
firmware at the time the attestation request is sent to SNP firmware. The
recommended scheme to do this is to use file locking (e.g. via fcntl()'s
F_OFD_SETLK) in the following manner:
- Prior to obtaining/providing certificate data as part of servicing an
exit type of ``KVM_EXIT_SNP_REQ_CERTS``, the VMM should obtain a
shared/read or exclusive/write lock on the certificate blob file before
reading it and returning it to KVM, and continue to hold the lock until
the attestation request is actually sent to firmware. To facilitate
this, the VMM can set the ``immediate_exit`` flag of kvm_run just after
supplying the certificate data, and just before resuming the vCPU.
This will ensure the vCPU will exit again to userspace with ``-EINTR``
after it finishes fetching the attestation request from firmware, at
which point the VMM can safely drop the file lock.
- Tools/libraries that perform updates to SNP firmware TCB values or
endorsement keys (e.g. via /dev/sev interfaces such as ``SNP_COMMIT``,
``SNP_SET_CONFIG``, or ``SNP_VLEK_LOAD``, see
Documentation/virt/coco/sev-guest.rst for more details) in such a way
that the certificate blob needs to be updated, should similarly take an
exclusive lock on the certificate blob for the duration of any updates
to endorsement keys or the certificate blob contents to ensure that
VMMs using the above scheme will not return certificate blob data that
is out of sync with the endorsement key used by firmware at the time
the attestation request is actually issued.
This scheme is recommended so that tools can use a fairly generic/natural
approach to synchronizing firmware/certificate updates via file-locking,
which should make it easier to maintain interoperability across
tools/VMMs/vendors.
Device attribute API
====================
@@ -579,11 +625,15 @@ Attributes of the SEV implementation can be retrieved through the
``KVM_HAS_DEVICE_ATTR`` and ``KVM_GET_DEVICE_ATTR`` ioctls on the ``/dev/kvm``
device node, using group ``KVM_X86_GRP_SEV``.
Currently only one attribute is implemented:
The following attributes are currently implemented:
* ``KVM_X86_SEV_VMSA_FEATURES``: return the set of all bits that
are accepted in the ``vmsa_features`` of ``KVM_SEV_INIT2``.
* ``KVM_X86_SEV_SNP_REQ_CERTS``: return a value of 1 if the kernel supports the
``KVM_EXIT_SNP_REQ_CERTS`` exit, which allows for fetching endorsement key
certificates from userspace for each SNP attestation request the guest issues.
Firmware Management
===================

View File

@@ -503,6 +503,7 @@ struct kvm_sync_regs {
#define KVM_X86_GRP_SEV 1
# define KVM_X86_SEV_VMSA_FEATURES 0
# define KVM_X86_SNP_POLICY_BITS 1
# define KVM_X86_SEV_SNP_REQ_CERTS 2
struct kvm_vmx_nested_state_data {
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
@@ -743,6 +744,7 @@ enum sev_cmd_id {
KVM_SEV_SNP_LAUNCH_START = 100,
KVM_SEV_SNP_LAUNCH_UPDATE,
KVM_SEV_SNP_LAUNCH_FINISH,
KVM_SEV_SNP_ENABLE_REQ_CERTS,
KVM_SEV_NR_MAX,
};

View File

@@ -2158,6 +2158,9 @@ int sev_dev_get_attr(u32 group, u64 attr, u64 *val)
*val = snp_supported_policy_bits;
return 0;
case KVM_X86_SEV_SNP_REQ_CERTS:
*val = sev_snp_enabled ? 1 : 0;
return 0;
default:
return -ENXIO;
}
@@ -2574,6 +2577,16 @@ e_free:
return ret;
}
static int snp_enable_certs(struct kvm *kvm)
{
if (kvm->created_vcpus || !sev_snp_guest(kvm))
return -EINVAL;
to_kvm_sev_info(kvm)->snp_certs_enabled = true;
return 0;
}
int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
{
struct kvm_sev_cmd sev_cmd;
@@ -2679,6 +2692,9 @@ int sev_mem_enc_ioctl(struct kvm *kvm, void __user *argp)
case KVM_SEV_SNP_LAUNCH_FINISH:
r = snp_launch_finish(kvm, &sev_cmd);
break;
case KVM_SEV_SNP_ENABLE_REQ_CERTS:
r = snp_enable_certs(kvm);
break;
default:
r = -EINVAL;
goto out;