diff mbox series

[v3,2/2] x86/sev: generate SEV kernel loader hashes in x86_load_linux

Message ID 20210825073538.959525-3-dovmurik@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series x86/sev: Measured Linux SEV guest with kernel/initrd/cmdline | expand

Commit Message

Dov Murik Aug. 25, 2021, 7:35 a.m. UTC
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(-)

Comments

Daniel P. Berrangé Sept. 27, 2021, 5:03 p.m. UTC | #1
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
Dov Murik Sept. 29, 2021, 9:42 a.m. UTC | #2
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 mbox series

Patch

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";