The current approach to enabling secure boot relies on providing -secure-boot and -boot-certificates options, which apply to all boot devices.
With the possibility of multiple boot devices, secure boot expects all provided devices to be supported and eligible (e.g., virtio-blk/virtio-scsi using the SCSI scheme). If multiple boot devices are provided and include an unsupported (e.g., ECKD, VFIO) or a non-eligible (e.g., Net) device, the boot process will terminate with an error logged to the console. Signed-off-by: Zhuoying Cai <zy...@linux.ibm.com> --- pc-bios/s390-ccw/bootmap.c | 28 +++++++++----- pc-bios/s390-ccw/main.c | 74 ++++++++++++++++++++++++++++++++++--- pc-bios/s390-ccw/s390-ccw.h | 1 + 3 files changed, 88 insertions(+), 15 deletions(-) diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c index a22061e1ad..285aae114f 100644 --- a/pc-bios/s390-ccw/bootmap.c +++ b/pc-bios/s390-ccw/bootmap.c @@ -1713,23 +1713,35 @@ int zipl_mode(void) } } +int zipl_check_scsi_mbr_magic(void) +{ + ScsiMbr *mbr = (void *)sec; + + /* Grab the MBR */ + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); + if (virtio_read(0, mbr)) { + puts("Cannot read block 0"); + return -EIO; + } + + if (!magic_match(mbr->magic, ZIPL_MAGIC)) { + return -1; + } + + return 0; +} + void zipl_load(void) { VDev *vdev = virtio_get_device(); if (vdev->is_cdrom) { - if (boot_mode == ZIPL_SECURE_AUDIT_MODE || boot_mode == ZIPL_SECURE_MODE) { - panic("Secure boot from ISO image is not supported!"); - } ipl_iso_el_torito(); puts("Failed to IPL this ISO image!"); return; } if (virtio_get_device_type() == VIRTIO_ID_NET) { - if (boot_mode == ZIPL_SECURE_AUDIT_MODE || boot_mode == ZIPL_SECURE_MODE) { - panic("Virtio net boot device does not support secure boot!"); - } netmain(); puts("Failed to IPL from this network!"); return; @@ -1740,10 +1752,6 @@ void zipl_load(void) return; } - if (boot_mode == ZIPL_SECURE_AUDIT_MODE || boot_mode == ZIPL_SECURE_MODE) { - panic("ECKD boot device does not support secure boot!"); - } - switch (virtio_get_device_type()) { case VIRTIO_ID_BLOCK: zipl_load_vblk(); diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c index 6189a5a7ba..30cb470ee4 100644 --- a/pc-bios/s390-ccw/main.c +++ b/pc-bios/s390-ccw/main.c @@ -271,8 +271,43 @@ static int virtio_setup(void) return ret; } -static void ipl_boot_device(void) +static void validate_secure_boot_device(void) +{ + switch (cutype) { + case CU_TYPE_DASD_3990: + case CU_TYPE_DASD_2107: + panic("Passthrough (vfio) device does not support secure boot!"); + break; + case CU_TYPE_VIRTIO: + if (virtio_setup() == 0) { + VDev *vdev = virtio_get_device(); + + if (vdev->is_cdrom) { + panic("Secure boot from ISO image is not supported!"); + } + + if (virtio_get_device_type() == VIRTIO_ID_NET) { + panic("Virtio net boot device does not support secure boot!"); + } + + if (zipl_check_scsi_mbr_magic()) { + panic("ECKD boot device does not support secure boot!"); + } + } + break; + default: + panic("Secure boot from unexpected device type is not supported!"); + } + + printf("SCSI boot device supports secure boot.\n"); +} + +static void check_secure_boot_support(void) { + bool have_iplb_copy; + IplParameterBlock *iplb_copy; + QemuIplParameters *qipl_copy; + if (boot_mode == 0) { boot_mode = zipl_mode(); } @@ -281,13 +316,40 @@ static void ipl_boot_device(void) panic("Need at least one certificate for secure boot!"); } + if (boot_mode == ZIPL_NORMAL_MODE) { + return; + } + + /* + * Store copies of have_iplb, iplb and qipl. + * They will be updated in load_next_iplb(). + */ + have_iplb_copy = have_iplb; + iplb_copy = malloc(sizeof(IplParameterBlock)); + qipl_copy = malloc(sizeof(QemuIplParameters)); + + memcpy(qipl_copy, &qipl, sizeof(QemuIplParameters)); + memcpy(iplb_copy, iplb, sizeof(IplParameterBlock)); + + while (have_iplb_copy) { + if (have_iplb_copy && find_boot_device()) { + validate_secure_boot_device(); + } + have_iplb_copy = load_next_iplb(); + } + + memcpy(&qipl, qipl_copy, sizeof(QemuIplParameters)); + memcpy(iplb, iplb_copy, sizeof(IplParameterBlock)); + + free(qipl_copy); + free(iplb_copy); +} + +static void ipl_boot_device(void) +{ switch (cutype) { case CU_TYPE_DASD_3990: case CU_TYPE_DASD_2107: - if (boot_mode == ZIPL_SECURE_AUDIT_MODE || boot_mode == ZIPL_SECURE_MODE) { - panic("Passthrough (vfio) device does not support secure boot!"); - } - dasd_ipl(blk_schid, cutype); break; case CU_TYPE_VIRTIO: @@ -337,6 +399,8 @@ void main(void) probe_boot_device(); } + check_secure_boot_support(); + while (have_iplb) { boot_setup(); if (have_iplb && find_boot_device()) { diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h index e8ff3f7883..23b903b9ae 100644 --- a/pc-bios/s390-ccw/s390-ccw.h +++ b/pc-bios/s390-ccw/s390-ccw.h @@ -88,6 +88,7 @@ void zipl_load(void); #define ZIPL_SECURE_INVALID_MODE -1 int zipl_mode(void); +int zipl_check_scsi_mbr_magic(void); /* jump2ipl.c */ void write_reset_psw(uint64_t psw); -- 2.49.0