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

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