28f7f8
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
28f7f8
From: Sebastian Krahmer <krahmer@suse.com>
28f7f8
Date: Tue, 28 Nov 2017 17:24:38 +0800
28f7f8
Subject: [PATCH] AUDIT-0: http boot tracker bug
28f7f8
28f7f8
Fixing a memory leak in case of error, and a integer overflow, leading to a
28f7f8
heap overflow due to overly large chunk sizes.
28f7f8
28f7f8
We need to check against some maximum value, otherwise values like 0xffffffff
28f7f8
will eventually lead in the allocation functions to small sized buffers, since
28f7f8
the len is rounded up to the next reasonable alignment. The following memcpy
28f7f8
will then smash the heap, leading to RCE.
28f7f8
28f7f8
This is no big issue for pure http boot, since its going to execute an
28f7f8
untrusted kernel anyway, but it will break trusted boot scenarios, where only
28f7f8
signed code is allowed to be executed.
28f7f8
28f7f8
Signed-off-by: Michael Chang <mchang@suse.com>
28f7f8
---
28f7f8
 grub-core/net/efi/net.c | 4 +++-
28f7f8
 grub-core/net/http.c    | 5 ++++-
28f7f8
 2 files changed, 7 insertions(+), 2 deletions(-)
28f7f8
28f7f8
diff --git a/grub-core/net/efi/net.c b/grub-core/net/efi/net.c
28f7f8
index 9e0078ac1c6..2bf15447fd5 100644
28f7f8
--- a/grub-core/net/efi/net.c
28f7f8
+++ b/grub-core/net/efi/net.c
28f7f8
@@ -645,8 +645,10 @@ grub_efihttp_chunk_read (grub_file_t file, char *buf,
28f7f8
 
28f7f8
       rd = efi_net_interface (read, file, chunk, sz);
28f7f8
 
28f7f8
-      if (rd <= 0)
28f7f8
+      if (rd <= 0) {
28f7f8
+	grub_free (chunk);
28f7f8
 	return rd;
28f7f8
+      }
28f7f8
 
28f7f8
       if (buf)
28f7f8
 	{
28f7f8
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
28f7f8
index 2b46e4672fc..82515f352dd 100644
28f7f8
--- a/grub-core/net/http.c
28f7f8
+++ b/grub-core/net/http.c
28f7f8
@@ -31,7 +31,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
28f7f8
 
28f7f8
 enum
28f7f8
   {
28f7f8
-    HTTP_PORT = 80
28f7f8
+    HTTP_PORT = 80,
28f7f8
+    HTTP_MAX_CHUNK_SIZE = 0x80000000
28f7f8
   };
28f7f8
 
28f7f8
 
28f7f8
@@ -78,6 +79,8 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
28f7f8
   if (data->in_chunk_len == 2)
28f7f8
     {
28f7f8
       data->chunk_rem = grub_strtoul (ptr, 0, 16);
28f7f8
+      if (data->chunk_rem > HTTP_MAX_CHUNK_SIZE)
28f7f8
+	  return GRUB_ERR_NET_PACKET_TOO_BIG;
28f7f8
       grub_errno = GRUB_ERR_NONE;
28f7f8
       if (data->chunk_rem == 0)
28f7f8
 	{