1From 18490336d91da2b532277cba56473bfed1376fc4 Mon Sep 17 00:00:00 2001
2From: Daniel Axtens <dja@axtens.net>
3Date: Thu, 21 Jan 2021 00:05:58 +1100
4Subject: [PATCH] io/gzio: Add init_dynamic_block() clean up if unpacking codes
5 fails
6
7init_dynamic_block() didn't clean up gzio->tl and td in some error
8paths. This left td pointing to part of tl. Then in grub_gzio_close(),
9when tl was freed the storage for td would also be freed. The code then
10attempts to free td explicitly, performing a UAF and then a double free.
11
12Explicitly clean up tl and td in the error paths.
13
14Signed-off-by: Daniel Axtens <dja@axtens.net>
15Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
16Signed-off-by: Stefan Sørensen <stefan.sorensen@spectralink.com>
17---
18 grub-core/io/gzio.c | 12 +++++++++---
19 1 file changed, 9 insertions(+), 3 deletions(-)
20
21diff --git a/grub-core/io/gzio.c b/grub-core/io/gzio.c
22index 4a8eaea..4236f0f 100644
23--- a/grub-core/io/gzio.c
24+++ b/grub-core/io/gzio.c
25@@ -953,7 +953,7 @@ init_dynamic_block (grub_gzio_t gzio)
26 	  if ((unsigned) i + j > n)
27 	    {
28 	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
29-	      return;
30+	      goto fail;
31 	    }
32 	  while (j--)
33 	    ll[i++] = l;
34@@ -966,7 +966,7 @@ init_dynamic_block (grub_gzio_t gzio)
35 	  if ((unsigned) i + j > n)
36 	    {
37 	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
38-	      return;
39+	      goto fail;
40 	    }
41 	  while (j--)
42 	    ll[i++] = 0;
43@@ -981,7 +981,7 @@ init_dynamic_block (grub_gzio_t gzio)
44 	  if ((unsigned) i + j > n)
45 	    {
46 	      grub_error (GRUB_ERR_BAD_COMPRESSED_DATA, "too many codes found");
47-	      return;
48+	      goto fail;
49 	    }
50 	  while (j--)
51 	    ll[i++] = 0;
52@@ -1019,6 +1019,12 @@ init_dynamic_block (grub_gzio_t gzio)
53   /* indicate we're now working on a block */
54   gzio->code_state = 0;
55   gzio->block_len++;
56+  return;
57+
58+ fail:
59+  huft_free (gzio->tl);
60+  gzio->td = NULL;
61+  gzio->tl = NULL;
62 }
63
64
65--
662.14.2
67
68