Blame SOURCES/0175-fix-memory-corruption-in-pubkey-filter-over-network.patch

6b3c76
From 27d2434ea9aed09b6cefdcc8600e191fa6d1c2fb Mon Sep 17 00:00:00 2001
a85e8e
From: Andrei Borzenkov <arvidjaar@gmail.com>
a85e8e
Date: Fri, 5 Dec 2014 21:17:08 +0300
6b3c76
Subject: [PATCH 175/261] fix memory corruption in pubkey filter over network
a85e8e
a85e8e
grub_pubkey_open closed original file after it was read; it set
a85e8e
io->device to NULL to prevent grub_file_close from trying to close device.
a85e8e
But network device itself is stacked (net -> bufio); and bufio preserved
a85e8e
original netfs file which hold reference to device. grub_file_close(io)
a85e8e
called grub_bufio_close which called grub_file_close for original file.
a85e8e
grub_file_close(netfs-file) now also called grub_device_close which
a85e8e
freed file->device->net. So file structure returned by grub_pubkey_open
a85e8e
now had device->net pointed to freed memory. When later file was closed,
a85e8e
it was attempted to be freed again.
a85e8e
a85e8e
Change grub_pubkey_open to behave like other filters - preserve original
a85e8e
parent file and pass grub_file_close down to parent. In this way only the
a85e8e
original file will close device. We really need to move this logic into
a85e8e
core instead.
a85e8e
a85e8e
Also plug memory leaks in error paths on the way.
a85e8e
a85e8e
Reported-By: Robert Kliewer <robert.kliewer@gmail.com>
a85e8e
Closes: bug #43601
a85e8e
---
a85e8e
 grub-core/commands/verify.c | 72 +++++++++++++++++++++++++++++++++++++--------
a85e8e
 1 file changed, 60 insertions(+), 12 deletions(-)
a85e8e
a85e8e
diff --git a/grub-core/commands/verify.c b/grub-core/commands/verify.c
6b3c76
index 525bdd187..d5995766b 100644
a85e8e
--- a/grub-core/commands/verify.c
a85e8e
+++ b/grub-core/commands/verify.c
a85e8e
@@ -33,6 +33,13 @@
a85e8e
 
a85e8e
 GRUB_MOD_LICENSE ("GPLv3+");
a85e8e
 
a85e8e
+struct grub_verified
a85e8e
+{
a85e8e
+  grub_file_t file;
a85e8e
+  void *buf;
a85e8e
+};
a85e8e
+typedef struct grub_verified *grub_verified_t;
a85e8e
+
a85e8e
 enum
a85e8e
   {
a85e8e
     OPTION_SKIP_SIG = 0
a85e8e
@@ -802,19 +809,39 @@ grub_cmd_verify_signature (grub_extcmd_context_t ctxt,
a85e8e
 
a85e8e
 static int sec = 0;
a85e8e
 
a85e8e
+static void
a85e8e
+verified_free (grub_verified_t verified)
a85e8e
+{
a85e8e
+  if (verified)
a85e8e
+    {
a85e8e
+      grub_free (verified->buf);
a85e8e
+      grub_free (verified);
a85e8e
+    }
a85e8e
+}
a85e8e
+
a85e8e
 static grub_ssize_t
a85e8e
 verified_read (struct grub_file *file, char *buf, grub_size_t len)
a85e8e
 {
a85e8e
-  grub_memcpy (buf, (char *) file->data + file->offset, len);
a85e8e
+  grub_verified_t verified = file->data;
a85e8e
+
a85e8e
+  grub_memcpy (buf, (char *) verified->buf + file->offset, len);
a85e8e
   return len;
a85e8e
 }
a85e8e
 
a85e8e
 static grub_err_t
a85e8e
 verified_close (struct grub_file *file)
a85e8e
 {
a85e8e
-  grub_free (file->data);
a85e8e
+  grub_verified_t verified = file->data;
a85e8e
+
a85e8e
+  grub_file_close (verified->file);
a85e8e
+  verified_free (verified);
a85e8e
   file->data = 0;
a85e8e
-  return GRUB_ERR_NONE;
a85e8e
+
a85e8e
+  /* device and name are freed by parent */
a85e8e
+  file->device = 0;
a85e8e
+  file->name = 0;
a85e8e
+
a85e8e
+  return grub_errno;
a85e8e
 }
a85e8e
 
a85e8e
 struct grub_fs verified_fs =
a85e8e
@@ -832,6 +859,7 @@ grub_pubkey_open (grub_file_t io, const char *filename)
a85e8e
   grub_err_t err;
a85e8e
   grub_file_filter_t curfilt[GRUB_FILE_FILTER_MAX];
a85e8e
   grub_file_t ret;
a85e8e
+  grub_verified_t verified;
a85e8e
 
a85e8e
   if (!sec)
a85e8e
     return io;
a85e8e
@@ -857,7 +885,10 @@ grub_pubkey_open (grub_file_t io, const char *filename)
a85e8e
 
a85e8e
   ret = grub_malloc (sizeof (*ret));
a85e8e
   if (!ret)
a85e8e
-    return NULL;
a85e8e
+    {
a85e8e
+      grub_file_close (sig);
a85e8e
+      return NULL;
a85e8e
+    }
a85e8e
   *ret = *io;
a85e8e
 
a85e8e
   ret->fs = &verified_fs;
a85e8e
@@ -866,29 +897,46 @@ grub_pubkey_open (grub_file_t io, const char *filename)
a85e8e
     {
a85e8e
       grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
a85e8e
 		  "big file signature isn't implemented yet");
a85e8e
+      grub_file_close (sig);
a85e8e
+      grub_free (ret);
a85e8e
+      return NULL;
a85e8e
+    }
a85e8e
+  verified = grub_malloc (sizeof (*verified));
a85e8e
+  if (!verified)
a85e8e
+    {
a85e8e
+      grub_file_close (sig);
a85e8e
+      grub_free (ret);
a85e8e
       return NULL;
a85e8e
     }
a85e8e
-  ret->data = grub_malloc (ret->size);
a85e8e
-  if (!ret->data)
a85e8e
+  verified->buf = grub_malloc (ret->size);
a85e8e
+  if (!verified->buf)
a85e8e
     {
a85e8e
+      grub_file_close (sig);
a85e8e
+      grub_free (verified);
a85e8e
       grub_free (ret);
a85e8e
       return NULL;
a85e8e
     }
a85e8e
-  if (grub_file_read (io, ret->data, ret->size) != (grub_ssize_t) ret->size)
a85e8e
+  if (grub_file_read (io, verified->buf, ret->size) != (grub_ssize_t) ret->size)
a85e8e
     {
a85e8e
       if (!grub_errno)
a85e8e
 	grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"),
a85e8e
 		    filename);
a85e8e
+      grub_file_close (sig);
a85e8e
+      verified_free (verified);
a85e8e
+      grub_free (ret);
a85e8e
       return NULL;
a85e8e
     }
a85e8e
 
a85e8e
-  err = grub_verify_signature_real (ret->data, ret->size, 0, sig, NULL);
a85e8e
+  err = grub_verify_signature_real (verified->buf, ret->size, 0, sig, NULL);
a85e8e
   grub_file_close (sig);
a85e8e
   if (err)
a85e8e
-    return NULL;
a85e8e
-  io->device = 0;
a85e8e
-  io->name = 0;
a85e8e
-  grub_file_close (io);
a85e8e
+    {
a85e8e
+      verified_free (verified);
a85e8e
+      grub_free (ret);
a85e8e
+      return NULL;
a85e8e
+    }
a85e8e
+  verified->file = io;
a85e8e
+  ret->data = verified;
a85e8e
   return ret;
a85e8e
 }
a85e8e
 
6b3c76
-- 
6b3c76
2.13.5
6b3c76