summaryrefslogtreecommitdiffstats
path: root/meta/recipes-bsp/grub/files/CVE-2021-3695-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
blob: 7f7bb1acfe7b8ffccd3363d6be87bab6c710c452 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
From e623866d9286410156e8b9d2c82d6253a1b22d08 Mon Sep 17 00:00:00 2001
From: Daniel Axtens <dja@axtens.net>
Date: Tue, 6 Jul 2021 18:51:35 +1000
Subject: [PATCH] video/readers/png: Drop greyscale support to fix heap
 out-of-bounds write

A 16-bit greyscale PNG without alpha is processed in the following loop:

      for (i = 0; i < (data->image_width * data->image_height);
	   i++, d1 += 4, d2 += 2)
	{
	  d1[R3] = d2[1];
	  d1[G3] = d2[1];
	  d1[B3] = d2[1];
	}

The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration,
but there are only 3 bytes allocated for storage. This means that image
data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes
out of every 4 following the end of the image.

This has existed since greyscale support was added in 2013 in commit
3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale).

Saving starfield.png as a 16-bit greyscale image without alpha in the gimp
and attempting to load it causes grub-emu to crash - I don't think this code
has ever worked.

Delete all PNG greyscale support.

Fixes: CVE-2021-3695

Signed-off-by: Daniel Axtens <dja@axtens.net>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>

Upstream-Status: Backport
CVE: CVE-2021-3695

Reference to upstream patch:
https://git.savannah.gnu.org/cgit/grub.git/commit/?id=e623866d9286410156e8b9d2c82d6253a1b22d08

Signed-off-by: Yongxin Liu <yongxin.liu@windriver.com>
---
 grub-core/video/readers/png.c | 87 +++--------------------------------
 1 file changed, 7 insertions(+), 80 deletions(-)

diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
index 35ae553c8..a3161e25b 100644
--- a/grub-core/video/readers/png.c
+++ b/grub-core/video/readers/png.c
@@ -100,7 +100,7 @@ struct grub_png_data
 
   unsigned image_width, image_height;
   int bpp, is_16bit;
-  int raw_bytes, is_gray, is_alpha, is_palette;
+  int raw_bytes, is_alpha, is_palette;
   int row_bytes, color_bits;
   grub_uint8_t *image_data;
 
@@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
     data->bpp = 3;
   else
     {
-      data->is_gray = 1;
-      data->bpp = 1;
+      return grub_error (GRUB_ERR_BAD_FILE_TYPE,
+			 "png: color type not supported");
     }
 
   if ((color_bits != 8) && (color_bits != 16)
       && (color_bits != 4
-	  || !(data->is_gray || data->is_palette)))
+	  || !data->is_palette))
     return grub_error (GRUB_ERR_BAD_FILE_TYPE,
                        "png: bit depth must be 8 or 16");
 
@@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data)
     }
 
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
-  if (data->is_16bit || data->is_gray || data->is_palette)
+  if (data->is_16bit || data->is_palette)
 #endif
     {
       data->image_data = grub_calloc (data->image_height, data->row_bytes);
@@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data)
       int shift;
       int mask = (1 << data->color_bits) - 1;
       unsigned j;
-      if (data->is_gray)
-	{
-	  /* Generic formula is
-	     (0xff * i) / ((1U << data->color_bits) - 1)
-	     but for allowed bit depth of 1, 2 and for it's
-	     equivalent to
-	     (0xff / ((1U << data->color_bits) - 1)) * i
-	     Precompute the multipliers to avoid division.
-	  */
-
-	  const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 };
-	  for (i = 0; i < (1U << data->color_bits); i++)
-	    {
-	      grub_uint8_t col = multipliers[data->color_bits] * i;
-	      palette[i][0] = col;
-	      palette[i][1] = col;
-	      palette[i][2] = col;
-	    }
-	}
-      else
-	grub_memcpy (palette, data->palette, 3 << data->color_bits);
+
+      grub_memcpy (palette, data->palette, 3 << data->color_bits);
       d1c = d1;
       d2c = d2;
       for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3,
@@ -957,60 +938,6 @@ grub_png_convert_image (struct grub_png_data *data)
       return;
     }
 
-  if (data->is_gray)
-    {
-      switch (data->bpp)
-	{
-	case 4:
-	  /* 16-bit gray with alpha.  */
-	  for (i = 0; i < (data->image_width * data->image_height);
-	       i++, d1 += 4, d2 += 4)
-	    {
-	      d1[R4] = d2[3];
-	      d1[G4] = d2[3];
-	      d1[B4] = d2[3];
-	      d1[A4] = d2[1];
-	    }
-	  break;
-	case 2:
-	  if (data->is_16bit)
-	    /* 16-bit gray without alpha.  */
-	    {
-	      for (i = 0; i < (data->image_width * data->image_height);
-		   i++, d1 += 4, d2 += 2)
-		{
-		  d1[R3] = d2[1];
-		  d1[G3] = d2[1];
-		  d1[B3] = d2[1];
-		}
-	    }
-	  else
-	    /* 8-bit gray with alpha.  */
-	    {
-	      for (i = 0; i < (data->image_width * data->image_height);
-		   i++, d1 += 4, d2 += 2)
-		{
-		  d1[R4] = d2[1];
-		  d1[G4] = d2[1];
-		  d1[B4] = d2[1];
-		  d1[A4] = d2[0];
-		}
-	    }
-	  break;
-	  /* 8-bit gray without alpha.  */
-	case 1:
-	  for (i = 0; i < (data->image_width * data->image_height);
-	       i++, d1 += 3, d2++)
-	    {
-	      d1[R3] = d2[0];
-	      d1[G3] = d2[0];
-	      d1[B3] = d2[0];
-	    }
-	  break;
-	}
-      return;
-    }
-
     {
   /* Only copy the upper 8 bit.  */
 #ifndef GRUB_CPU_WORDS_BIGENDIAN
-- 
2.34.1