qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Cornelia Huck <cornelia.huck@de.ibm.com>
To: peter.maydell@linaro.org
Cc: qemu-devel@nongnu.org, agraf@suse.de, borntraeger@de.ibm.com,
	jfrei@linux.vnet.ibm.com,
	Maxim Samoylov <max7255@linux.vnet.ibm.com>,
	Cornelia Huck <cornelia.huck@de.ibm.com>
Subject: [Qemu-devel] [PULL for-2.5 10/15] pc-bios/s390-ccw: El Torito 16-bit boot image size field workaround
Date: Wed, 11 Nov 2015 18:56:28 +0100	[thread overview]
Message-ID: <1447264593-14625-11-git-send-email-cornelia.huck@de.ibm.com> (raw)
In-Reply-To: <1447264593-14625-1-git-send-email-cornelia.huck@de.ibm.com>

From: Maxim Samoylov <max7255@linux.vnet.ibm.com>

Because of El Torito spec flaw boot image size needs to be verified.

Boot catalog entry size field has 16-bit width, and specifies size
in 512-byte units.

Thus, boot image size cannot exceed 32M.

We actually search for the file to get the file size.

This is done by scanning the ISO directory tree for the ISO block number
and reading the file size from the directory entry.

Signed-off-by: Maxim Samoylov <max7255@linux.vnet.ibm.com>
Reviewed-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
---
 pc-bios/s390-ccw/bootmap.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++
 pc-bios/s390-ccw/bootmap.h |  7 ++++
 2 files changed, 97 insertions(+)

diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c
index 82cca9c..415508b 100644
--- a/pc-bios/s390-ccw/bootmap.c
+++ b/pc-bios/s390-ccw/bootmap.c
@@ -462,6 +462,87 @@ static bool is_iso_bc_entry_compatible(IsoBcSection *s)
     return !_memcmp(magic_sec + 8, linux_s390_magic, 24);
 }
 
+/* Location of the current sector of the directory */
+static uint32_t sec_loc[ISO9660_MAX_DIR_DEPTH];
+/* Offset in the current sector of the directory */
+static uint32_t sec_offset[ISO9660_MAX_DIR_DEPTH];
+/* Remained directory space in bytes */
+static uint32_t dir_rem[ISO9660_MAX_DIR_DEPTH];
+
+static inline uint32_t iso_get_file_size(uint32_t load_rba)
+{
+    IsoVolDesc *vd = (IsoVolDesc *)sec;
+    IsoDirHdr *cur_record = &vd->vd.primary.rootdir;
+    uint8_t *temp = sec + ISO_SECTOR_SIZE;
+    int level = 0;
+
+    read_iso_sector(ISO_PRIMARY_VD_SECTOR, sec,
+                    "Failed to read ISO primary descriptor");
+    sec_loc[0] = iso_733_to_u32(cur_record->ext_loc);
+    dir_rem[0] = 0;
+    sec_offset[0] = 0;
+
+    while (level >= 0) {
+        IPL_assert(sec_offset[level] <= ISO_SECTOR_SIZE,
+                   "Directory tree structure violation");
+
+        cur_record = (IsoDirHdr *)(temp + sec_offset[level]);
+
+        if (sec_offset[level] == 0) {
+            read_iso_sector(sec_loc[level], temp,
+                            "Failed to read ISO directory");
+            if (dir_rem[level] == 0) {
+                /* Skip self and parent records */
+                dir_rem[level] = iso_733_to_u32(cur_record->data_len) -
+                                 cur_record->dr_len;
+                sec_offset[level] += cur_record->dr_len;
+
+                cur_record = (IsoDirHdr *)(temp + sec_offset[level]);
+                dir_rem[level] -= cur_record->dr_len;
+                sec_offset[level] += cur_record->dr_len;
+                continue;
+            }
+        }
+
+        if (!cur_record->dr_len || sec_offset[level] == ISO_SECTOR_SIZE) {
+            /* Zero-padding and/or the end of current sector */
+            dir_rem[level] -= ISO_SECTOR_SIZE - sec_offset[level];
+            sec_offset[level] = 0;
+            sec_loc[level]++;
+        } else {
+            /* The directory record is valid */
+            if (load_rba == iso_733_to_u32(cur_record->ext_loc)) {
+                return iso_733_to_u32(cur_record->data_len);
+            }
+
+            dir_rem[level] -= cur_record->dr_len;
+            sec_offset[level] += cur_record->dr_len;
+
+            if (cur_record->file_flags & 0x2) {
+                /* Subdirectory */
+                if (level == ISO9660_MAX_DIR_DEPTH - 1) {
+                    sclp_print("ISO-9660 directory depth limit exceeded\n");
+                } else {
+                    level++;
+                    sec_loc[level] = iso_733_to_u32(cur_record->ext_loc);
+                    sec_offset[level] = 0;
+                    dir_rem[level] = 0;
+                    continue;
+                }
+            }
+        }
+
+        if (dir_rem[level] == 0) {
+            /* Nothing remaining */
+            level--;
+            read_iso_sector(sec_loc[level], temp,
+                            "Failed to read ISO directory");
+        }
+    }
+
+    return 0;
+}
+
 static void load_iso_bc_entry(IsoBcSection *load)
 {
     IsoBcSection s = *load;
@@ -470,6 +551,15 @@ static void load_iso_bc_entry(IsoBcSection *load)
      * is padded and ISO_SECTOR_SIZE bytes aligned
      */
     uint32_t blks_to_load = bswap16(s.sector_count) >> ET_SECTOR_SHIFT;
+    uint32_t real_size = iso_get_file_size(bswap32(s.load_rba));
+
+    if (real_size) {
+        /* Round up blocks to load */
+        blks_to_load = (real_size + ISO_SECTOR_SIZE - 1) / ISO_SECTOR_SIZE;
+        sclp_print("ISO boot image size verified\n");
+    } else {
+        sclp_print("ISO boot image size could not be verified\n");
+    }
 
     read_iso_boot_image(bswap32(s.load_rba),
                         (void *)((uint64_t)bswap16(s.load_segment)),
diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h
index cc77fd7..f98765b 100644
--- a/pc-bios/s390-ccw/bootmap.h
+++ b/pc-bios/s390-ccw/bootmap.h
@@ -381,6 +381,11 @@ static inline uint64_t bswap64(uint64_t x)
            ((x & 0xff00000000000000ULL) >> 56);
 }
 
+static inline uint32_t iso_733_to_u32(uint64_t x)
+{
+    return (uint32_t)x;
+}
+
 #define ISO_SECTOR_SIZE 2048
 /* El Torito specifies boot image size in 512 byte blocks */
 #define ET_SECTOR_SHIFT 2
@@ -407,6 +412,8 @@ static inline void read_iso_boot_image(uint32_t block_offset, void *load_addr,
 const uint8_t el_torito_magic[] = "EL TORITO SPECIFICATION"
                                   "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
 
+#define ISO9660_MAX_DIR_DEPTH 8
+
 typedef struct IsoDirHdr {
     uint8_t dr_len;
     uint8_t ear_len;
-- 
2.6.3

  parent reply	other threads:[~2015-11-11 17:57 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-11 17:56 [Qemu-devel] [PULL for-2.5 00/15] s390x patches for 2.5 Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 01/15] s390x/css: sense data endianness Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 02/15] s390x/pci : fix up s390 pci iommu translation function Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 03/15] MAINTAINERS: update s390 file patterns Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 04/15] MAINTAINERS: update virtio-ccw/s390 git tree Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 05/15] s390x: switch to memory_region_allocate_system_memory Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 06/15] s390x/kvm: don't enable CMMA when hugetlbfs will be used Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 07/15] pc-bios/s390-ccw: Always adjust virtio sector count Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 08/15] pc-bios/s390-ccw: ISO-9660 El Torito boot implementation Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 09/15] pc-bios/s390-ccw: El Torito s390x boot entry check Cornelia Huck
2015-11-11 17:56 ` Cornelia Huck [this message]
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 11/15] pc-bios/s390-ccw: rebuild image Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 12/15] qdev: provide qdev_reset_all_fn() Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 13/15] s390x/ipl: clean up qom definitions and turn into TYPE_DEVICE Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 14/15] s390x/ipl: switch error reporting to error_setg Cornelia Huck
2015-11-11 17:56 ` [Qemu-devel] [PULL for-2.5 15/15] s390: deprecate the non-ccw machine in 2.5 Cornelia Huck
2015-11-11 23:19 ` [Qemu-devel] [PULL for-2.5 00/15] s390x patches for 2.5 Peter Maydell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1447264593-14625-11-git-send-email-cornelia.huck@de.ibm.com \
    --to=cornelia.huck@de.ibm.com \
    --cc=agraf@suse.de \
    --cc=borntraeger@de.ibm.com \
    --cc=jfrei@linux.vnet.ibm.com \
    --cc=max7255@linux.vnet.ibm.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).