Patrick Williams | 92b42cb | 2022-09-03 06:53:57 -0500 | [diff] [blame] | 1 | From e623866d9286410156e8b9d2c82d6253a1b22d08 Mon Sep 17 00:00:00 2001 |
| 2 | From: Daniel Axtens <dja@axtens.net> |
| 3 | Date: Tue, 6 Jul 2021 18:51:35 +1000 |
| 4 | Subject: [PATCH] video/readers/png: Drop greyscale support to fix heap |
| 5 | out-of-bounds write |
| 6 | |
| 7 | A 16-bit greyscale PNG without alpha is processed in the following loop: |
| 8 | |
| 9 | for (i = 0; i < (data->image_width * data->image_height); |
| 10 | i++, d1 += 4, d2 += 2) |
| 11 | { |
| 12 | d1[R3] = d2[1]; |
| 13 | d1[G3] = d2[1]; |
| 14 | d1[B3] = d2[1]; |
| 15 | } |
| 16 | |
| 17 | The increment of d1 is wrong. d1 is incremented by 4 bytes per iteration, |
| 18 | but there are only 3 bytes allocated for storage. This means that image |
| 19 | data will overwrite somewhat-attacker-controlled parts of memory - 3 bytes |
| 20 | out of every 4 following the end of the image. |
| 21 | |
| 22 | This has existed since greyscale support was added in 2013 in commit |
| 23 | 3ccf16dff98f (grub-core/video/readers/png.c: Support grayscale). |
| 24 | |
| 25 | Saving starfield.png as a 16-bit greyscale image without alpha in the gimp |
| 26 | and attempting to load it causes grub-emu to crash - I don't think this code |
| 27 | has ever worked. |
| 28 | |
| 29 | Delete all PNG greyscale support. |
| 30 | |
| 31 | Fixes: CVE-2021-3695 |
| 32 | |
| 33 | Signed-off-by: Daniel Axtens <dja@axtens.net> |
| 34 | Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com> |
| 35 | |
| 36 | Upstream-Status: Backport |
| 37 | CVE: CVE-2021-3695 |
| 38 | |
| 39 | Reference to upstream patch: |
| 40 | https://git.savannah.gnu.org/cgit/grub.git/commit/?id=e623866d9286410156e8b9d2c82d6253a1b22d08 |
| 41 | |
| 42 | Signed-off-by: Yongxin Liu <yongxin.liu@windriver.com> |
| 43 | --- |
| 44 | grub-core/video/readers/png.c | 87 +++-------------------------------- |
| 45 | 1 file changed, 7 insertions(+), 80 deletions(-) |
| 46 | |
| 47 | diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c |
| 48 | index 35ae553c8..a3161e25b 100644 |
| 49 | --- a/grub-core/video/readers/png.c |
| 50 | +++ b/grub-core/video/readers/png.c |
| 51 | @@ -100,7 +100,7 @@ struct grub_png_data |
| 52 | |
| 53 | unsigned image_width, image_height; |
| 54 | int bpp, is_16bit; |
| 55 | - int raw_bytes, is_gray, is_alpha, is_palette; |
| 56 | + int raw_bytes, is_alpha, is_palette; |
| 57 | int row_bytes, color_bits; |
| 58 | grub_uint8_t *image_data; |
| 59 | |
| 60 | @@ -296,13 +296,13 @@ grub_png_decode_image_header (struct grub_png_data *data) |
| 61 | data->bpp = 3; |
| 62 | else |
| 63 | { |
| 64 | - data->is_gray = 1; |
| 65 | - data->bpp = 1; |
| 66 | + return grub_error (GRUB_ERR_BAD_FILE_TYPE, |
| 67 | + "png: color type not supported"); |
| 68 | } |
| 69 | |
| 70 | if ((color_bits != 8) && (color_bits != 16) |
| 71 | && (color_bits != 4 |
| 72 | - || !(data->is_gray || data->is_palette))) |
| 73 | + || !data->is_palette)) |
| 74 | return grub_error (GRUB_ERR_BAD_FILE_TYPE, |
| 75 | "png: bit depth must be 8 or 16"); |
| 76 | |
| 77 | @@ -331,7 +331,7 @@ grub_png_decode_image_header (struct grub_png_data *data) |
| 78 | } |
| 79 | |
| 80 | #ifndef GRUB_CPU_WORDS_BIGENDIAN |
| 81 | - if (data->is_16bit || data->is_gray || data->is_palette) |
| 82 | + if (data->is_16bit || data->is_palette) |
| 83 | #endif |
| 84 | { |
| 85 | data->image_data = grub_calloc (data->image_height, data->row_bytes); |
| 86 | @@ -899,27 +899,8 @@ grub_png_convert_image (struct grub_png_data *data) |
| 87 | int shift; |
| 88 | int mask = (1 << data->color_bits) - 1; |
| 89 | unsigned j; |
| 90 | - if (data->is_gray) |
| 91 | - { |
| 92 | - /* Generic formula is |
| 93 | - (0xff * i) / ((1U << data->color_bits) - 1) |
| 94 | - but for allowed bit depth of 1, 2 and for it's |
| 95 | - equivalent to |
| 96 | - (0xff / ((1U << data->color_bits) - 1)) * i |
| 97 | - Precompute the multipliers to avoid division. |
| 98 | - */ |
| 99 | - |
| 100 | - const grub_uint8_t multipliers[5] = { 0xff, 0xff, 0x55, 0x24, 0x11 }; |
| 101 | - for (i = 0; i < (1U << data->color_bits); i++) |
| 102 | - { |
| 103 | - grub_uint8_t col = multipliers[data->color_bits] * i; |
| 104 | - palette[i][0] = col; |
| 105 | - palette[i][1] = col; |
| 106 | - palette[i][2] = col; |
| 107 | - } |
| 108 | - } |
| 109 | - else |
| 110 | - grub_memcpy (palette, data->palette, 3 << data->color_bits); |
| 111 | + |
| 112 | + grub_memcpy (palette, data->palette, 3 << data->color_bits); |
| 113 | d1c = d1; |
| 114 | d2c = d2; |
| 115 | for (j = 0; j < data->image_height; j++, d1c += data->image_width * 3, |
| 116 | @@ -957,60 +938,6 @@ grub_png_convert_image (struct grub_png_data *data) |
| 117 | return; |
| 118 | } |
| 119 | |
| 120 | - if (data->is_gray) |
| 121 | - { |
| 122 | - switch (data->bpp) |
| 123 | - { |
| 124 | - case 4: |
| 125 | - /* 16-bit gray with alpha. */ |
| 126 | - for (i = 0; i < (data->image_width * data->image_height); |
| 127 | - i++, d1 += 4, d2 += 4) |
| 128 | - { |
| 129 | - d1[R4] = d2[3]; |
| 130 | - d1[G4] = d2[3]; |
| 131 | - d1[B4] = d2[3]; |
| 132 | - d1[A4] = d2[1]; |
| 133 | - } |
| 134 | - break; |
| 135 | - case 2: |
| 136 | - if (data->is_16bit) |
| 137 | - /* 16-bit gray without alpha. */ |
| 138 | - { |
| 139 | - for (i = 0; i < (data->image_width * data->image_height); |
| 140 | - i++, d1 += 4, d2 += 2) |
| 141 | - { |
| 142 | - d1[R3] = d2[1]; |
| 143 | - d1[G3] = d2[1]; |
| 144 | - d1[B3] = d2[1]; |
| 145 | - } |
| 146 | - } |
| 147 | - else |
| 148 | - /* 8-bit gray with alpha. */ |
| 149 | - { |
| 150 | - for (i = 0; i < (data->image_width * data->image_height); |
| 151 | - i++, d1 += 4, d2 += 2) |
| 152 | - { |
| 153 | - d1[R4] = d2[1]; |
| 154 | - d1[G4] = d2[1]; |
| 155 | - d1[B4] = d2[1]; |
| 156 | - d1[A4] = d2[0]; |
| 157 | - } |
| 158 | - } |
| 159 | - break; |
| 160 | - /* 8-bit gray without alpha. */ |
| 161 | - case 1: |
| 162 | - for (i = 0; i < (data->image_width * data->image_height); |
| 163 | - i++, d1 += 3, d2++) |
| 164 | - { |
| 165 | - d1[R3] = d2[0]; |
| 166 | - d1[G3] = d2[0]; |
| 167 | - d1[B3] = d2[0]; |
| 168 | - } |
| 169 | - break; |
| 170 | - } |
| 171 | - return; |
| 172 | - } |
| 173 | - |
| 174 | { |
| 175 | /* Only copy the upper 8 bit. */ |
| 176 | #ifndef GRUB_CPU_WORDS_BIGENDIAN |
| 177 | -- |
| 178 | 2.34.1 |
| 179 | |