5d360b
From abead8461f6c8c50cdc8dedc43e4821a7e1d5e33 Mon Sep 17 00:00:00 2001
12e206
From: Bandan Das <bsd@redhat.com>
12e206
Date: Thu, 26 Oct 2017 10:03:48 +0200
5d360b
Subject: [PATCH 1/2] multiboot: validate multiboot header address values
12e206
12e206
RH-Author: Bandan Das <bsd@redhat.com>
12e206
Message-id: <jpgefpqw7i3.fsf@linux.bootlegged.copy>
12e206
Patchwork-id: 77443
12e206
O-Subject: [RHEL-7.5 qemu-kvm PATCH] multiboot: validate multiboot header address values
5d360b
Bugzilla: 1501121
12e206
RH-Acked-by: Thomas Huth <thuth@redhat.com>
12e206
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
12e206
RH-Acked-by: Peter Xu <peterx@redhat.com>
12e206
12e206
While loading kernel via multiboot-v1 image, (flags & 0x00010000)
12e206
indicates that multiboot header contains valid addresses to load
12e206
the kernel image. These addresses are used to compute kernel
12e206
size and kernel text offset in the OS image. Validate these
12e206
address values to avoid an OOB access issue.
12e206
12e206
This is CVE-2017-14167.
12e206
12e206
Reported-by: Thomas Garnier <thgarnie@google.com>
12e206
Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
12e206
Message-Id: <20170907063256.7418-1-ppandit@redhat.com>
12e206
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
12e206
(cherry picked from commit ed4f86e8b6eff8e600c69adee68c7cd34dd2cccb)
12e206
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
12e206
---
12e206
 hw/i386/multiboot.c | 19 +++++++++++++++++++
12e206
 1 file changed, 19 insertions(+)
12e206
12e206
diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c
12e206
index 09211e0..7eec230 100644
12e206
--- a/hw/i386/multiboot.c
12e206
+++ b/hw/i386/multiboot.c
12e206
@@ -200,15 +200,34 @@ int load_multiboot(FWCfgState *fw_cfg,
12e206
         uint32_t mh_header_addr = ldl_p(header+i+12);
12e206
         uint32_t mh_load_end_addr = ldl_p(header+i+20);
12e206
         uint32_t mh_bss_end_addr = ldl_p(header+i+24);
12e206
+
12e206
         mh_load_addr = ldl_p(header+i+16);
12e206
+        if (mh_header_addr < mh_load_addr) {
12e206
+            fprintf(stderr, "invalid mh_load_addr address\n");
12e206
+            exit(1);
12e206
+        }
12e206
+
12e206
         uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
12e206
         uint32_t mb_load_size = 0;
12e206
         mh_entry_addr = ldl_p(header+i+28);
12e206
 
12e206
         if (mh_load_end_addr) {
12e206
+            if (mh_bss_end_addr < mh_load_addr) {
12e206
+                fprintf(stderr, "invalid mh_bss_end_addr address\n");
12e206
+                exit(1);
12e206
+            }
12e206
             mb_kernel_size = mh_bss_end_addr - mh_load_addr;
12e206
+
12e206
+            if (mh_load_end_addr < mh_load_addr) {
12e206
+                fprintf(stderr, "invalid mh_load_end_addr address\n");
12e206
+                exit(1);
12e206
+            }
12e206
             mb_load_size = mh_load_end_addr - mh_load_addr;
12e206
         } else {
12e206
+            if (kernel_file_size < mb_kernel_text_offset) {
12e206
+                fprintf(stderr, "invalid kernel_file_size\n");
12e206
+                exit(1);
12e206
+            }
12e206
             mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
12e206
             mb_load_size = mb_kernel_size;
12e206
         }
12e206
-- 
12e206
1.8.3.1
12e206