Message ID | 20210825073538.959525-3-dovmurik@linux.ibm.com |
---|---|
State | New |
Headers | show |
Series | x86/sev: Measured Linux SEV guest with kernel/initrd/cmdline | expand |
On Wed, Aug 25, 2021 at 07:35:38AM +0000, Dov Murik wrote: > If SEV is enabled and a kernel is passed via -kernel, pass the hashes of > kernel/initrd/cmdline in an encrypted guest page to OVMF for SEV > measured boot. > > Co-developed-by: James Bottomley <jejb@linux.ibm.com> > Signed-off-by: James Bottomley <jejb@linux.ibm.com> > Signed-off-by: Dov Murik <dovmurik@linux.ibm.com> > Reviewed-by: Connor Kuehl <ckuehl@redhat.com> > --- > hw/i386/x86.c | 25 ++++++++++++++++++++++++- > 1 file changed, 24 insertions(+), 1 deletion(-) > > diff --git a/hw/i386/x86.c b/hw/i386/x86.c > index 00448ed55a..4044104cfe 100644 > --- a/hw/i386/x86.c > +++ b/hw/i386/x86.c > @@ -45,6 +45,7 @@ > #include "hw/i386/fw_cfg.h" > #include "hw/intc/i8259.h" > #include "hw/rtc/mc146818rtc.h" > +#include "target/i386/sev_i386.h" > > #include "hw/acpi/cpu_hotplug.h" > #include "hw/irq.h" > @@ -778,6 +779,7 @@ void x86_load_linux(X86MachineState *x86ms, > const char *initrd_filename = machine->initrd_filename; > const char *dtb_filename = machine->dtb; > const char *kernel_cmdline = machine->kernel_cmdline; > + KernelLoaderContext kernel_loader_context = {}; I think the variable name is overly verbose but could also benefit from a 'sev_' prefix. eg how about just calling the var 'sev_context'. In any case, its functionally fine, so can add Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Regards, Daniel
On 27/09/2021 20:03, Daniel P. Berrangé wrote: > On Wed, Aug 25, 2021 at 07:35:38AM +0000, Dov Murik wrote: >> If SEV is enabled and a kernel is passed via -kernel, pass the hashes of >> kernel/initrd/cmdline in an encrypted guest page to OVMF for SEV >> measured boot. >> >> Co-developed-by: James Bottomley <jejb@linux.ibm.com> >> Signed-off-by: James Bottomley <jejb@linux.ibm.com> >> Signed-off-by: Dov Murik <dovmurik@linux.ibm.com> >> Reviewed-by: Connor Kuehl <ckuehl@redhat.com> >> --- >> hw/i386/x86.c | 25 ++++++++++++++++++++++++- >> 1 file changed, 24 insertions(+), 1 deletion(-) >> >> diff --git a/hw/i386/x86.c b/hw/i386/x86.c >> index 00448ed55a..4044104cfe 100644 >> --- a/hw/i386/x86.c >> +++ b/hw/i386/x86.c >> @@ -45,6 +45,7 @@ >> #include "hw/i386/fw_cfg.h" >> #include "hw/intc/i8259.h" >> #include "hw/rtc/mc146818rtc.h" >> +#include "target/i386/sev_i386.h" >> >> #include "hw/acpi/cpu_hotplug.h" >> #include "hw/irq.h" >> @@ -778,6 +779,7 @@ void x86_load_linux(X86MachineState *x86ms, >> const char *initrd_filename = machine->initrd_filename; >> const char *dtb_filename = machine->dtb; >> const char *kernel_cmdline = machine->kernel_cmdline; >> + KernelLoaderContext kernel_loader_context = {}; > > I think the variable name is overly verbose but could also benefit > from a 'sev_' prefix. eg how about just calling the var 'sev_context'. I'll consider a rename which includes 'sev_' and is a bit shorter. > > In any case, its functionally fine, so can add > > Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> > Thanks! -Dov > > Regards, > Daniel >
diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 00448ed55a..4044104cfe 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -45,6 +45,7 @@ #include "hw/i386/fw_cfg.h" #include "hw/intc/i8259.h" #include "hw/rtc/mc146818rtc.h" +#include "target/i386/sev_i386.h" #include "hw/acpi/cpu_hotplug.h" #include "hw/irq.h" @@ -778,6 +779,7 @@ void x86_load_linux(X86MachineState *x86ms, const char *initrd_filename = machine->initrd_filename; const char *dtb_filename = machine->dtb; const char *kernel_cmdline = machine->kernel_cmdline; + KernelLoaderContext kernel_loader_context = {}; /* Align to 16 bytes as a paranoia measure */ cmdline_size = (strlen(kernel_cmdline) + 16) & ~15; @@ -924,6 +926,8 @@ void x86_load_linux(X86MachineState *x86ms, fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(kernel_cmdline) + 1); fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, kernel_cmdline); + kernel_loader_context.cmdline_data = (char *)kernel_cmdline; + kernel_loader_context.cmdline_size = strlen(kernel_cmdline) + 1; if (protocol >= 0x202) { stl_p(header + 0x228, cmdline_addr); @@ -1005,6 +1009,8 @@ void x86_load_linux(X86MachineState *x86ms, fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_INITRD_DATA, initrd_data, initrd_size); + kernel_loader_context.initrd_data = initrd_data; + kernel_loader_context.initrd_size = initrd_size; stl_p(header + 0x218, initrd_addr); stl_p(header + 0x21c, initrd_size); @@ -1063,15 +1069,32 @@ void x86_load_linux(X86MachineState *x86ms, load_image_size(dtb_filename, setup_data->data, dtb_size); } - memcpy(setup, header, MIN(sizeof(header), setup_size)); + /* + * If we're starting an encrypted VM, it will be OVMF based, which uses the + * efi stub for booting and doesn't require any values to be placed in the + * kernel header. We therefore don't update the header so the hash of the + * kernel on the other side of the fw_cfg interface matches the hash of the + * file the user passed in. + */ + if (!sev_enabled()) { + memcpy(setup, header, MIN(sizeof(header), setup_size)); + } fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); + kernel_loader_context.kernel_data = (char *)kernel; + kernel_loader_context.kernel_size = kernel_size; fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size); + kernel_loader_context.setup_data = (char *)setup; + kernel_loader_context.setup_size = setup_size; + + if (sev_enabled()) { + sev_add_kernel_loader_hashes(&kernel_loader_context, &error_fatal); + } option_rom[nb_option_roms].bootindex = 0; option_rom[nb_option_roms].name = "linuxboot.bin";