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