Thanks to visit codestin.com
Credit goes to github.com

Skip to content

vmm, hypervisor: Add support for embedding kernel hashes to a CVM's launch digest - #8084

Closed
CookieComputing wants to merge 8 commits into
cloud-hypervisor:mainfrom
CookieComputing:sev-snp-kernel-hashes
Closed

CookieComputing wants to merge 8 commits into
cloud-hypervisor:mainfrom
CookieComputing:sev-snp-kernel-hashes

Conversation

@CookieComputing

Copy link
Copy Markdown
Contributor

Context

I am adding kernel hash support for SEV-SNP in Cloud Hypervisor. The idea behind this is to embed an extra page of data containing a table detailing the kernel, initrd, and kernel cmdline so that these are part of the launch digest, ensuring that all of these components are embedded as part of the TCB. Prior to this, a launch digest only represented the contents of the OVMF binary and the other existing VMSA data.

This is an existing concept from QEMU and OVMF, see this documentation. I'm simply porting this over to enable support here .

The idea is that this is a GUID table that resembles a struct like:

  0x10c00  +-------------------------------------------------------------+
           | PaddedSevHashTable (0x0b0 = 176 bytes)                      |
           |                                                             |
           |  SevHashTable (0x0a8 = 168 bytes)                           |
           |  0x000  table.guid   [16]  SEV_HASH_TABLE_GUID              |
           |  0x010  table.len    [ 2]  0x00a8                           |
           |                                                             |
           |  0x012  cmdline entry (0x32 = 50 bytes)                     |
           |         - guid     [16]  SEV_CMDLINE_HASH_GUID              |
           |         - len      [ 2]  0x0032                             |
           |         - hash     [32]  sha256(cmdline + trailing NUL)     |
           |                                                             |
           |  0x044  initrd entry  (0x32 = 50 bytes)                     |
           |         - guid     [16]  SEV_INITRD_HASH_GUID               |
           |         - len      [ 2]  0x0032                             |
           |         - hash     [32]  sha256(initrd) or sha256(empty)    |
           |                                                             |
           |  0x076  kernel entry  (0x32 = 50 bytes)                     |
           |         - guid     [16]  SEV_KERNEL_HASH_GUID               |
           |         - len      [ 2]  0x0032                             |
           |         - hash     [32]  sha256(setup_data || kernel_body)  |
           |                                                             |
           |  0x0aa  padding [8]  zeroes to align table to 16 bytes      |
  0x10cb0  +-------------------------------------------------------------+
           | remaining hash block bytes                                  |
           | zero-filled: 0x350 bytes (848)                              |
  0x11000  +-------------------------------------------------------------+

When this table is added in to the launch digest via SNP_LAUNCH_UPDATE, we can then enforce via the bootloader that we are launching the correct initrd, kernel, and kernel cmdline (see my changes in project-oak/oak#5073). Tying this together, we get a Launch Digest which represents the bootloader, initrd, kernel, kernel hashes, and VMSA (+ any other fields).

Test Plan

Tested this on an SEV-SNP capable AMD Bergamo host.
I generated buildigvm using the PRs I've added in 7, 8, and 9. This makes the buildigvm tooling deterministic and matches the behavior of sev-snp-measure.

$ ./buildigvm sev-snp --firmware stage0_bin --output stage0.igvm --cpucount 4 --vcpu-sig 0x800f12 

Launch parameters:

$ ./cloud-hypervisor --platform sev_snp=on --igvm stage0.igvm --kernel /cvm/launch/cvm_vmlinuz --cpus boot=4 --memory size=4G,shared=on --disk path=./rootfs.qcow2,image_type=qcow2 --serial tty --console off --initramfs /cvm/launch/layer_no_integrity.cpio.gz --fw-cfg-config kernel=on,cmdline=on,initramfs=on --cmdline "console=ttyS0 root=/dev/vda1 rw rw_overlay_size=1024"

When using snpguest, I get the following measurement from the CVM:

Measurement:                  
7d eb f2 63 da be b4 3d 10 4a a3 88 b7 8c 0d e3 
cc d3 bb 13 62 67 53 c9 50 4c 1d 0f f9 79 7f 05 
53 ed e3 db f7 69 78 0d a1 4f 23 f1 07 64 76 f6

Using the sev-snp-measure tool from VirTEE, I get this:

$ ./sev-snp-measure.par --vcpus 4 --vcpu-type EPYC-v4 --ovmf /tmp/stage0_bin --kernel /cvm/launch/cvm_vmlinuz --initrd /cvm/launch/layer_no_integrity.cpio.gz --append "console=ttyS0 root=/dev/vda1 rw rw_overlay_size=1024" --mode snp
7debf263dabeb43d104aa388b78c0de3ccd3bb13626753c9504c1d0ff9797f0553ede3dbf769780da14f23f1076476f6

So, at least with this original set of changes we have a consistent measurement with existing tooling (IGVM measurement tooling pending conversation with SVSM folks).

@CookieComputing
CookieComputing requested a review from a team as a code owner April 22, 2026 21:53
@CookieComputing CookieComputing changed the title sev-snp: Add support for embedding kernel hashes to a CVM's launch digest hypervisor: Add support for embedding kernel hashes to a CVM's launch digest Apr 23, 2026
@CookieComputing CookieComputing changed the title hypervisor: Add support for embedding kernel hashes to a CVM's launch digest vmm, hypervisor: Add support for embedding kernel hashes to a CVM's launch digest Apr 23, 2026
Comment thread vmm/src/igvm/igvm_loader.rs Outdated
This introduces the kernel hashes measured boot table into
cloud hypervisor if a cmdline and kernel is passed into an
SEV-SNP CVM, incorporating a kernel/cmdline/optional initrd
into a memory page that is measured into the launch digest
of a SEV-SNP CVM. If both --kernel and --cmdline are not
provided, we do not insert this data page

Signed-off-by: Kevin Hui <[email protected]>
Introduce the KVM_SNP_PAGE_TYPE_ZERO page type for ZERO
pages. AMD SEV SNP can accept ZERO pages as a page in which
the page memory is functionally just zeroes

Signed-off-by: Kevin Hui <[email protected]>
IGVM has an opinionated way of deterministically loading
pages. We should prefer to follow the ordering that IGVM
has instead of modifying this page order

Signed-off-by: Kevin Hui <[email protected]>
Previous builds were failing because measured_boot concepts rely on
fw_cfg, which wasn't provided at the time

Signed-off-by: Kevin Hui <[email protected]>
Signed-off-by: Kevin Hui <[email protected]>
self.kernel
.read_exact_at(&mut setup_data, 0)
.map_err(Self::measured_boot_io)?;
setup_data[..setup_header.len()].copy_from_slice(&setup_header);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already read the whole of setup_data on line 156 which should already contain the bytes covered by setup_header, so do we need to copy setup_header on this line again?

Comment on lines +753 to +755
// Preserve the original IGVM import order for SNP launch updates.
// The launch digest is order-sensitive, so only coalesce adjacent pages
// that already share the same page type and size.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For my understanding, this is not gated by KVM, so it also applied to MSHV. Was the original MSHV code incorrect? Launch digest being order-sensitive should not be specific to hypervisor IIUC.

@CookieComputing CookieComputing Apr 28, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I might be missing some context for the MSHV stuff, but maybe this comment should be above, where we previously sort the GPAs...

I'm guessing that we can coalesce to reduce hypercalls for MSHV, which functionally doesn't affect the launch digest because they're just coalescing the pages, but we definitely don't want to modify page order from IGVM

Comment on lines +319 to +324
#[cfg(all(
feature = "kvm",
feature = "sev_snp",
feature = "fw_cfg",
target_arch = "x86_64"
))]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like there are a bit too many of these chunky cfgs scattered around load_igvm that it becomes a bit difficult to follow what's happening.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I agree, these cfgs are getting too bloated... I wonder if there's a good way to extract some of these components (e.g. make it such that the fw_cfg cfg is only used to define which method is to used to fetch the kernel/initrd/cmdline components)

@rbradford
rbradford marked this pull request as draft April 29, 2026 07:16
@rbradford

Copy link
Copy Markdown
Member

Drafting as there are some basic CI check failures.

@rbradford

Copy link
Copy Markdown
Member

Replaced by #8123

@rbradford rbradford closed this May 1, 2026
@CookieComputing
CookieComputing deleted the sev-snp-kernel-hashes branch July 10, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants