File s390-tools-sles15sp2-zipl-check-for-valid-ipl-parmblock-lowcore-pointer.patch of Package s390-tools.16701

Subject: [PATCH] [BZ 186938] zipl: check for valid ipl parmblock lowcore pointer
From: Stefan Haberland <sth@linux.ibm.com>

Description:   zipl: check for valid ipl parmblock lowcore pointer
Symptom:       For CCW type IPL the IPL might fail.
Problem:       The lowcore parmblock pointer is not valid in every
               case. For example it is invalid for CCW type IPL.
Solution:      To have an indication if the pointer is valid do a
               diag308 to store the parmblock and check if secure boot
               is enabled. If it is enabled the lowcore pointer is
               valid and the ipl report that is needed for secure boot
               can be found right behind the ipl parmblock.
Reproduction:  IPL from CCW devices.
Upstream-ID:   ee9d606f800741eedeec1dcf1d2ddbfccbc21140
Problem-ID:    186938

Signed-off-by: Stefan Haberland <sth@linux.ibm.com>
---
 include/boot/ipl.h |    1 +
 zipl/boot/stage3.c |   24 ++++++++++++++++++++----
 2 files changed, 21 insertions(+), 4 deletions(-)

--- a/include/boot/ipl.h
+++ b/include/boot/ipl.h
@@ -18,6 +18,7 @@
 #define IPL_RB_COMPONENT_FLAG_SIGNED	0x80
 #define IPL_RB_COMPONENT_FLAG_VERIFIED	0x40
 
+#define IPL_MAX_SUPPORTED_VERSION	0
 #define IPL_PARM_BLOCK_VERSION		0x1
 
 /* IPL Types */
--- a/zipl/boot/stage3.c
+++ b/zipl/boot/stage3.c
@@ -26,6 +26,7 @@
 
 static const char *msg_sipl_inval = "Secure boot failure: invalid load address";
 static const char *msg_sipl_unverified = "Secure boot failure: unverified load address";
+static const char *msg_sipl_noparm = "Secure boot failure: unable to load ipl parameter";
 
 static inline void __noreturn start_kernel(void)
 {
@@ -54,6 +55,18 @@ static inline void __noreturn start_kern
 	while (1);
 }
 
+unsigned int store_ipl_parmblock(struct ipl_pl_hdr *pl_hdr)
+{
+	int rc;
+
+	rc = diag308(DIAG308_STORE, pl_hdr);
+	if (rc == DIAG308_RC_OK &&
+		pl_hdr->version <= IPL_MAX_SUPPORTED_VERSION)
+		return 0;
+
+	return 1;
+}
+
 unsigned int
 is_verified_address(unsigned long image_addr)
 {
@@ -104,12 +117,15 @@ unsigned int
 secure_boot_enabled()
 {
 	struct ipl_pl_hdr *pl_hdr;
-	unsigned long tmp;
+	unsigned int rc;
 
-	tmp = (unsigned long) S390_lowcore.ipl_parmblock_ptr;
-	pl_hdr = (struct ipl_pl_hdr *) tmp;
+	pl_hdr = (void *)get_zeroed_page();
+	if (!pl_hdr || store_ipl_parmblock(pl_hdr))
+		panic(ESECUREBOOT, "%s", msg_sipl_noparm);
+	rc = !!(pl_hdr->flags & IPL_FLAG_SECURE);
+	free_page((unsigned long) pl_hdr);
 
-	return pl_hdr->flags & IPL_FLAG_SECURE;
+	return rc;
 }
 
 void start(void)
openSUSE Build Service is sponsored by