forked from pool/grub2
Accepting request 981228 from home:michael-chang:branches:Base:System
- Security fixes and hardenings for boothole 3 / boothole 2022 (bsc#1198581) * 0001-video-Remove-trailing-whitespaces.patch * 0002-loader-efi-chainloader-Simplify-the-loader-state.patch * 0003-commands-boot-Add-API-to-pass-context-to-loader.patch - Fix CVE-2022-28736 (bsc#1198496) * 0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch - Fix CVE-2022-28735 (bsc#1198495) * 0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch * 0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch * 0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch * 0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch - Fix CVE-2021-3695 (bsc#1191184) * 0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch - Fix CVE-2021-3696 (bsc#1191185) * 0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch * 0011-video-readers-png-Sanity-check-some-huffman-codes.patch * 0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch * 0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch * 0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch - Fix CVE-2021-3697 (bsc#1191186) * 0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch * 0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch - Fix CVE-2022-28733 (bsc#1198460) * 0017-net-ip-Do-IP-fragment-maths-safely.patch * 0018-net-netbuff-Block-overly-large-netbuff-allocs.patch * 0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch * 0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch * 0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch * 0022-net-tftp-Avoid-a-trivial-UAF.patch * 0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch OBS-URL: https://build.opensuse.org/request/show/981228 OBS-URL: https://build.opensuse.org/package/show/Base:System/grub2?expand=0&rev=416
This commit is contained in:
parent
2d223e0f89
commit
e016790fe1
686
0001-video-Remove-trailing-whitespaces.patch
Normal file
686
0001-video-Remove-trailing-whitespaces.patch
Normal file
@ -0,0 +1,686 @@
|
||||
From efa2ddca2c7167e98f12e9ad8963e9201fa87e75 Mon Sep 17 00:00:00 2001
|
||||
From: Elyes Haouas <ehaouas@noos.fr>
|
||||
Date: Fri, 4 Mar 2022 07:42:13 +0100
|
||||
Subject: [PATCH 01/32] video: Remove trailing whitespaces
|
||||
|
||||
Signed-off-by: Elyes Haouas <ehaouas@noos.fr>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/bochs.c | 2 +-
|
||||
grub-core/video/capture.c | 2 +-
|
||||
grub-core/video/cirrus.c | 4 ++--
|
||||
grub-core/video/coreboot/cbfb.c | 2 +-
|
||||
grub-core/video/efi_gop.c | 22 +++++++++----------
|
||||
grub-core/video/fb/fbblit.c | 8 +++----
|
||||
grub-core/video/fb/video_fb.c | 10 ++++-----
|
||||
grub-core/video/i386/pc/vbe.c | 34 ++++++++++++++---------------
|
||||
grub-core/video/i386/pc/vga.c | 6 ++---
|
||||
grub-core/video/ieee1275.c | 4 ++--
|
||||
grub-core/video/radeon_fuloong2e.c | 6 ++---
|
||||
grub-core/video/radeon_yeeloong3a.c | 6 ++---
|
||||
grub-core/video/readers/png.c | 2 +-
|
||||
grub-core/video/readers/tga.c | 2 +-
|
||||
grub-core/video/sis315_init.c | 2 +-
|
||||
grub-core/video/sis315pro.c | 8 +++----
|
||||
grub-core/video/sm712.c | 10 ++++-----
|
||||
grub-core/video/video.c | 8 +++----
|
||||
18 files changed, 69 insertions(+), 69 deletions(-)
|
||||
|
||||
diff --git a/grub-core/video/bochs.c b/grub-core/video/bochs.c
|
||||
index 30ea1bd828..edc651697a 100644
|
||||
--- a/grub-core/video/bochs.c
|
||||
+++ b/grub-core/video/bochs.c
|
||||
@@ -212,7 +212,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
|
||||
|
||||
if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK;
|
||||
if (!framebuffer.base)
|
||||
diff --git a/grub-core/video/capture.c b/grub-core/video/capture.c
|
||||
index 4d3195e017..c653d89f91 100644
|
||||
--- a/grub-core/video/capture.c
|
||||
+++ b/grub-core/video/capture.c
|
||||
@@ -92,7 +92,7 @@ grub_video_capture_start (const struct grub_video_mode_info *mode_info,
|
||||
framebuffer.ptr = grub_calloc (framebuffer.mode_info.height, framebuffer.mode_info.pitch);
|
||||
if (!framebuffer.ptr)
|
||||
return grub_errno;
|
||||
-
|
||||
+
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr);
|
||||
diff --git a/grub-core/video/cirrus.c b/grub-core/video/cirrus.c
|
||||
index e2149e8ced..f5542ccdc6 100644
|
||||
--- a/grub-core/video/cirrus.c
|
||||
+++ b/grub-core/video/cirrus.c
|
||||
@@ -354,11 +354,11 @@ grub_video_cirrus_setup (unsigned int width, unsigned int height,
|
||||
grub_uint8_t sr_ext = 0, hidden_dac = 0;
|
||||
|
||||
grub_vga_set_geometry (&config, grub_vga_cr_write);
|
||||
-
|
||||
+
|
||||
grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1,
|
||||
GRUB_VGA_GR_MODE);
|
||||
grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6);
|
||||
-
|
||||
+
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
|
||||
|
||||
grub_vga_cr_write ((config.pitch >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT)
|
||||
diff --git a/grub-core/video/coreboot/cbfb.c b/grub-core/video/coreboot/cbfb.c
|
||||
index 9af81fa5b0..986003c516 100644
|
||||
--- a/grub-core/video/coreboot/cbfb.c
|
||||
+++ b/grub-core/video/coreboot/cbfb.c
|
||||
@@ -106,7 +106,7 @@ grub_video_cbfb_setup (unsigned int width, unsigned int height,
|
||||
|
||||
grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||
grub_video_fbstd_colors);
|
||||
-
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c
|
||||
index 5a37385398..cdf0e100fa 100644
|
||||
--- a/grub-core/video/efi_gop.c
|
||||
+++ b/grub-core/video/efi_gop.c
|
||||
@@ -273,7 +273,7 @@ grub_video_gop_iterate (int (*hook) (const struct grub_video_mode_info *info, vo
|
||||
grub_efi_status_t status;
|
||||
struct grub_efi_gop_mode_info *info = NULL;
|
||||
struct grub_video_mode_info mode_info;
|
||||
-
|
||||
+
|
||||
status = efi_call_4 (gop->query_mode, gop, mode, &size, &info);
|
||||
|
||||
if (status)
|
||||
@@ -402,7 +402,7 @@ again:
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
if (!found)
|
||||
{
|
||||
unsigned mode;
|
||||
@@ -411,7 +411,7 @@ again:
|
||||
{
|
||||
grub_efi_uintn_t size;
|
||||
grub_efi_status_t status;
|
||||
-
|
||||
+
|
||||
status = efi_call_4 (gop->query_mode, gop, mode, &size, &info);
|
||||
if (status)
|
||||
{
|
||||
@@ -489,11 +489,11 @@ again:
|
||||
framebuffer.ptr = (void *) (grub_addr_t) gop->mode->fb_base;
|
||||
framebuffer.offscreen
|
||||
= grub_malloc (framebuffer.mode_info.height
|
||||
- * framebuffer.mode_info.width
|
||||
+ * framebuffer.mode_info.width
|
||||
* sizeof (struct grub_efi_gop_blt_pixel));
|
||||
|
||||
buffer = framebuffer.offscreen;
|
||||
-
|
||||
+
|
||||
if (!buffer)
|
||||
{
|
||||
grub_dprintf ("video", "GOP: couldn't allocate shadow\n");
|
||||
@@ -502,11 +502,11 @@ again:
|
||||
&framebuffer.mode_info);
|
||||
buffer = framebuffer.ptr;
|
||||
}
|
||||
-
|
||||
+
|
||||
grub_dprintf ("video", "GOP: initialising FB @ %p %dx%dx%d\n",
|
||||
framebuffer.ptr, framebuffer.mode_info.width,
|
||||
framebuffer.mode_info.height, framebuffer.mode_info.bpp);
|
||||
-
|
||||
+
|
||||
err = grub_video_fb_create_render_target_from_pointer
|
||||
(&framebuffer.render_target, &framebuffer.mode_info, buffer);
|
||||
|
||||
@@ -515,15 +515,15 @@ again:
|
||||
grub_dprintf ("video", "GOP: Couldn't create FB target\n");
|
||||
return err;
|
||||
}
|
||||
-
|
||||
+
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
|
||||
-
|
||||
+
|
||||
if (err)
|
||||
{
|
||||
grub_dprintf ("video", "GOP: Couldn't set FB target\n");
|
||||
return err;
|
||||
}
|
||||
-
|
||||
+
|
||||
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||
grub_video_fbstd_colors);
|
||||
|
||||
@@ -531,7 +531,7 @@ again:
|
||||
grub_dprintf ("video", "GOP: Couldn't set palette\n");
|
||||
else
|
||||
grub_dprintf ("video", "GOP: Success\n");
|
||||
-
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
diff --git a/grub-core/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c
|
||||
index d55924837d..1010ef3930 100644
|
||||
--- a/grub-core/video/fb/fbblit.c
|
||||
+++ b/grub-core/video/fb/fbblit.c
|
||||
@@ -466,7 +466,7 @@ grub_video_fbblit_replace_24bit_indexa (struct grub_video_fbblit_info *dst,
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
register grub_uint32_t col;
|
||||
- if (*srcptr == 0xf0)
|
||||
+ if (*srcptr == 0xf0)
|
||||
col = palette[16];
|
||||
else
|
||||
col = palette[*srcptr & 0xf];
|
||||
@@ -478,7 +478,7 @@ grub_video_fbblit_replace_24bit_indexa (struct grub_video_fbblit_info *dst,
|
||||
*dstptr++ = col >> 0;
|
||||
*dstptr++ = col >> 8;
|
||||
*dstptr++ = col >> 16;
|
||||
-#endif
|
||||
+#endif
|
||||
srcptr++;
|
||||
}
|
||||
|
||||
@@ -651,7 +651,7 @@ grub_video_fbblit_blend_24bit_indexa (struct grub_video_fbblit_info *dst,
|
||||
for (i = 0; i < width; i++)
|
||||
{
|
||||
register grub_uint32_t col;
|
||||
- if (*srcptr != 0xf0)
|
||||
+ if (*srcptr != 0xf0)
|
||||
{
|
||||
col = palette[*srcptr & 0xf];
|
||||
#ifdef GRUB_CPU_WORDS_BIGENDIAN
|
||||
@@ -662,7 +662,7 @@ grub_video_fbblit_blend_24bit_indexa (struct grub_video_fbblit_info *dst,
|
||||
*dstptr++ = col >> 0;
|
||||
*dstptr++ = col >> 8;
|
||||
*dstptr++ = col >> 16;
|
||||
-#endif
|
||||
+#endif
|
||||
}
|
||||
else
|
||||
dstptr += 3;
|
||||
diff --git a/grub-core/video/fb/video_fb.c b/grub-core/video/fb/video_fb.c
|
||||
index ae6b89f9ae..fa4ebde260 100644
|
||||
--- a/grub-core/video/fb/video_fb.c
|
||||
+++ b/grub-core/video/fb/video_fb.c
|
||||
@@ -754,7 +754,7 @@ grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source,
|
||||
*alpha = 0;
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
/* If we have an out-of-bounds color, return transparent black. */
|
||||
if (color > 255)
|
||||
{
|
||||
@@ -1141,7 +1141,7 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
|
||||
/* If everything is aligned on 32-bit use 32-bit copy. */
|
||||
if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y)
|
||||
% sizeof (grub_uint32_t) == 0
|
||||
- && (grub_addr_t) grub_video_fb_get_video_ptr (&target, dst_x, dst_y)
|
||||
+ && (grub_addr_t) grub_video_fb_get_video_ptr (&target, dst_x, dst_y)
|
||||
% sizeof (grub_uint32_t) == 0
|
||||
&& linelen % sizeof (grub_uint32_t) == 0
|
||||
&& linedelta % sizeof (grub_uint32_t) == 0)
|
||||
@@ -1155,7 +1155,7 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
|
||||
else if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y)
|
||||
% sizeof (grub_uint16_t) == 0
|
||||
&& (grub_addr_t) grub_video_fb_get_video_ptr (&target,
|
||||
- dst_x, dst_y)
|
||||
+ dst_x, dst_y)
|
||||
% sizeof (grub_uint16_t) == 0
|
||||
&& linelen % sizeof (grub_uint16_t) == 0
|
||||
&& linedelta % sizeof (grub_uint16_t) == 0)
|
||||
@@ -1170,7 +1170,7 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
|
||||
{
|
||||
grub_uint8_t *src, *dst;
|
||||
DO_SCROLL
|
||||
- }
|
||||
+ }
|
||||
}
|
||||
|
||||
/* 4. Fill empty space with specified color. In this implementation
|
||||
@@ -1615,7 +1615,7 @@ grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
|
||||
framebuffer.render_target = framebuffer.back_target;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
-
|
||||
+
|
||||
mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c
|
||||
index 8c8cbf07eb..8b72810f85 100644
|
||||
--- a/grub-core/video/i386/pc/vbe.c
|
||||
+++ b/grub-core/video/i386/pc/vbe.c
|
||||
@@ -219,7 +219,7 @@ grub_vbe_disable_mtrr (int mtrr)
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f09 to set palette data, return status. */
|
||||
-static grub_vbe_status_t
|
||||
+static grub_vbe_status_t
|
||||
grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
|
||||
grub_uint32_t start_index,
|
||||
struct grub_vbe_palette_data *palette_data)
|
||||
@@ -237,7 +237,7 @@ grub_vbe_bios_set_palette_data (grub_uint32_t color_count,
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_get_controller_info (struct grub_vbe_info_block *ci)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -251,7 +251,7 @@ grub_vbe_bios_get_controller_info (struct grub_vbe_info_block *ci)
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f01 to get VBE Mode Information, return status. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_get_mode_info (grub_uint32_t mode,
|
||||
struct grub_vbe_mode_info_block *mode_info)
|
||||
{
|
||||
@@ -285,7 +285,7 @@ grub_vbe_bios_set_mode (grub_uint32_t mode,
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f03 to return current VBE Mode, return status. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_get_mode (grub_uint32_t *mode)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -298,7 +298,7 @@ grub_vbe_bios_get_mode (grub_uint32_t *mode)
|
||||
return regs.eax & 0xffff;
|
||||
}
|
||||
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_getset_dac_palette_width (int set, int *dac_mask_size)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -346,7 +346,7 @@ grub_vbe_bios_get_memory_window (grub_uint32_t window,
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f06 to set scanline length (in bytes), return status. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_set_scanline_length (grub_uint32_t length)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -354,14 +354,14 @@ grub_vbe_bios_set_scanline_length (grub_uint32_t length)
|
||||
regs.ecx = length;
|
||||
regs.eax = 0x4f06;
|
||||
/* BL = 2, Set Scan Line in Bytes. */
|
||||
- regs.ebx = 0x0002;
|
||||
+ regs.ebx = 0x0002;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x10, ®s);
|
||||
return regs.eax & 0xffff;
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f06 to return scanline length (in bytes), return status. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -377,7 +377,7 @@ grub_vbe_bios_get_scanline_length (grub_uint32_t *length)
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f07 to set display start, return status. */
|
||||
-static grub_vbe_status_t
|
||||
+static grub_vbe_status_t
|
||||
grub_vbe_bios_set_display_start (grub_uint32_t x, grub_uint32_t y)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -390,7 +390,7 @@ grub_vbe_bios_set_display_start (grub_uint32_t x, grub_uint32_t y)
|
||||
regs.edx = y;
|
||||
regs.eax = 0x4f07;
|
||||
/* BL = 80h, Set Display Start during Vertical Retrace. */
|
||||
- regs.ebx = 0x0080;
|
||||
+ regs.ebx = 0x0080;
|
||||
regs.flags = GRUB_CPU_INT_FLAGS_DEFAULT;
|
||||
grub_bios_interrupt (0x10, ®s);
|
||||
|
||||
@@ -401,7 +401,7 @@ grub_vbe_bios_set_display_start (grub_uint32_t x, grub_uint32_t y)
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f07 to get display start, return status. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_get_display_start (grub_uint32_t *x,
|
||||
grub_uint32_t *y)
|
||||
{
|
||||
@@ -419,7 +419,7 @@ grub_vbe_bios_get_display_start (grub_uint32_t *x,
|
||||
}
|
||||
|
||||
/* Call VESA BIOS 0x4f0a. */
|
||||
-grub_vbe_status_t
|
||||
+grub_vbe_status_t
|
||||
grub_vbe_bios_get_pm_interface (grub_uint16_t *segment, grub_uint16_t *offset,
|
||||
grub_uint16_t *length)
|
||||
{
|
||||
@@ -896,7 +896,7 @@ vbe2videoinfo (grub_uint32_t mode,
|
||||
case GRUB_VBE_MEMORY_MODEL_YUV:
|
||||
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_YUV;
|
||||
break;
|
||||
-
|
||||
+
|
||||
case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR:
|
||||
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
|
||||
break;
|
||||
@@ -923,10 +923,10 @@ vbe2videoinfo (grub_uint32_t mode,
|
||||
break;
|
||||
case 8:
|
||||
mode_info->bytes_per_pixel = 1;
|
||||
- break;
|
||||
+ break;
|
||||
case 4:
|
||||
mode_info->bytes_per_pixel = 0;
|
||||
- break;
|
||||
+ break;
|
||||
}
|
||||
|
||||
if (controller_info.version >= 0x300)
|
||||
@@ -976,7 +976,7 @@ grub_video_vbe_iterate (int (*hook) (const struct grub_video_mode_info *info, vo
|
||||
|
||||
static grub_err_t
|
||||
grub_video_vbe_setup (unsigned int width, unsigned int height,
|
||||
- grub_video_mode_type_t mode_type,
|
||||
+ grub_video_mode_type_t mode_type,
|
||||
grub_video_mode_type_t mode_mask)
|
||||
{
|
||||
grub_uint16_t *p;
|
||||
@@ -1208,7 +1208,7 @@ grub_video_vbe_print_adapter_specific_info (void)
|
||||
controller_info.version & 0xFF,
|
||||
controller_info.oem_software_rev >> 8,
|
||||
controller_info.oem_software_rev & 0xFF);
|
||||
-
|
||||
+
|
||||
/* The total_memory field is in 64 KiB units. */
|
||||
grub_printf_ (N_(" total memory: %d KiB\n"),
|
||||
(controller_info.total_memory << 6));
|
||||
diff --git a/grub-core/video/i386/pc/vga.c b/grub-core/video/i386/pc/vga.c
|
||||
index b2f776c997..50d0b5e028 100644
|
||||
--- a/grub-core/video/i386/pc/vga.c
|
||||
+++ b/grub-core/video/i386/pc/vga.c
|
||||
@@ -48,7 +48,7 @@ static struct
|
||||
int back_page;
|
||||
} framebuffer;
|
||||
|
||||
-static unsigned char
|
||||
+static unsigned char
|
||||
grub_vga_set_mode (unsigned char mode)
|
||||
{
|
||||
struct grub_bios_int_registers regs;
|
||||
@@ -182,10 +182,10 @@ grub_video_vga_setup (unsigned int width, unsigned int height,
|
||||
|
||||
is_target = 1;
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
|
||||
-
|
||||
+
|
||||
if (err)
|
||||
return err;
|
||||
-
|
||||
+
|
||||
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||
grub_video_fbstd_colors);
|
||||
|
||||
diff --git a/grub-core/video/ieee1275.c b/grub-core/video/ieee1275.c
|
||||
index b8e4b3feb3..0a89fa334d 100644
|
||||
--- a/grub-core/video/ieee1275.c
|
||||
+++ b/grub-core/video/ieee1275.c
|
||||
@@ -234,7 +234,7 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height,
|
||||
/* TODO. */
|
||||
return grub_error (GRUB_ERR_IO, "can't set mode %dx%d", width, height);
|
||||
}
|
||||
-
|
||||
+
|
||||
err = grub_video_ieee1275_fill_mode_info (dev, &framebuffer.mode_info);
|
||||
if (err)
|
||||
{
|
||||
@@ -261,7 +261,7 @@ grub_video_ieee1275_setup (unsigned int width, unsigned int height,
|
||||
|
||||
grub_video_ieee1275_set_palette (0, framebuffer.mode_info.number_of_colors,
|
||||
grub_video_fbstd_colors);
|
||||
-
|
||||
+
|
||||
return err;
|
||||
}
|
||||
|
||||
diff --git a/grub-core/video/radeon_fuloong2e.c b/grub-core/video/radeon_fuloong2e.c
|
||||
index b4da34b5ee..40917acb76 100644
|
||||
--- a/grub-core/video/radeon_fuloong2e.c
|
||||
+++ b/grub-core/video/radeon_fuloong2e.c
|
||||
@@ -75,7 +75,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
|
||||
if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
|
||||
|| pciid != 0x515a1002)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
*found = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
@@ -139,7 +139,7 @@ grub_video_radeon_fuloong2e_setup (unsigned int width, unsigned int height,
|
||||
framebuffer.mapped = 1;
|
||||
|
||||
/* Prevent garbage from appearing on the screen. */
|
||||
- grub_memset (framebuffer.ptr, 0x55,
|
||||
+ grub_memset (framebuffer.ptr, 0x55,
|
||||
framebuffer.mode_info.height * framebuffer.mode_info.pitch);
|
||||
|
||||
#ifndef TEST
|
||||
@@ -152,7 +152,7 @@ grub_video_radeon_fuloong2e_setup (unsigned int width, unsigned int height,
|
||||
return err;
|
||||
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
|
||||
-
|
||||
+
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/grub-core/video/radeon_yeeloong3a.c b/grub-core/video/radeon_yeeloong3a.c
|
||||
index 52614feb69..48631c1815 100644
|
||||
--- a/grub-core/video/radeon_yeeloong3a.c
|
||||
+++ b/grub-core/video/radeon_yeeloong3a.c
|
||||
@@ -74,7 +74,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
|
||||
if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
|
||||
|| pciid != 0x96151002)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
*found = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
@@ -137,7 +137,7 @@ grub_video_radeon_yeeloong3a_setup (unsigned int width, unsigned int height,
|
||||
#endif
|
||||
|
||||
/* Prevent garbage from appearing on the screen. */
|
||||
- grub_memset (framebuffer.ptr, 0,
|
||||
+ grub_memset (framebuffer.ptr, 0,
|
||||
framebuffer.mode_info.height * framebuffer.mode_info.pitch);
|
||||
|
||||
#ifndef TEST
|
||||
@@ -150,7 +150,7 @@ grub_video_radeon_yeeloong3a_setup (unsigned int width, unsigned int height,
|
||||
return err;
|
||||
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
|
||||
-
|
||||
+
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
|
||||
index 0157ff7420..54dfedf435 100644
|
||||
--- a/grub-core/video/readers/png.c
|
||||
+++ b/grub-core/video/readers/png.c
|
||||
@@ -916,7 +916,7 @@ grub_png_convert_image (struct grub_png_data *data)
|
||||
}
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
if (data->is_gray)
|
||||
{
|
||||
switch (data->bpp)
|
||||
diff --git a/grub-core/video/readers/tga.c b/grub-core/video/readers/tga.c
|
||||
index 7cb9d1d2a0..a9ec3a1b6e 100644
|
||||
--- a/grub-core/video/readers/tga.c
|
||||
+++ b/grub-core/video/readers/tga.c
|
||||
@@ -127,7 +127,7 @@ tga_load_palette (struct tga_data *data)
|
||||
|
||||
if (len > sizeof (data->palette))
|
||||
len = sizeof (data->palette);
|
||||
-
|
||||
+
|
||||
if (grub_file_read (data->file, &data->palette, len)
|
||||
!= (grub_ssize_t) len)
|
||||
return grub_errno;
|
||||
diff --git a/grub-core/video/sis315_init.c b/grub-core/video/sis315_init.c
|
||||
index ae5c1419c1..09c3c7bbea 100644
|
||||
--- a/grub-core/video/sis315_init.c
|
||||
+++ b/grub-core/video/sis315_init.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-static const struct { grub_uint8_t reg; grub_uint8_t val; } sr_dump [] =
|
||||
+static const struct { grub_uint8_t reg; grub_uint8_t val; } sr_dump [] =
|
||||
{
|
||||
{ 0x28, 0x81 },
|
||||
{ 0x2a, 0x00 },
|
||||
diff --git a/grub-core/video/sis315pro.c b/grub-core/video/sis315pro.c
|
||||
index 22a0c85a64..4d2f9999a9 100644
|
||||
--- a/grub-core/video/sis315pro.c
|
||||
+++ b/grub-core/video/sis315pro.c
|
||||
@@ -103,7 +103,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
|
||||
if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
|
||||
|| pciid != GRUB_SIS315PRO_PCIID)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
*found = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
@@ -218,7 +218,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height,
|
||||
|
||||
#ifndef TEST
|
||||
/* Prevent garbage from appearing on the screen. */
|
||||
- grub_memset (framebuffer.ptr, 0,
|
||||
+ grub_memset (framebuffer.ptr, 0,
|
||||
framebuffer.mode_info.height * framebuffer.mode_info.pitch);
|
||||
grub_arch_sync_dma_caches (framebuffer.ptr,
|
||||
framebuffer.mode_info.height
|
||||
@@ -231,7 +231,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height,
|
||||
| GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0
|
||||
| GRUB_VGA_IO_MISC_28MHZ
|
||||
| GRUB_VGA_IO_MISC_ENABLE_VRAM_ACCESS
|
||||
- | GRUB_VGA_IO_MISC_COLOR,
|
||||
+ | GRUB_VGA_IO_MISC_COLOR,
|
||||
GRUB_VGA_IO_MISC_WRITE + GRUB_MACHINE_PCI_IO_BASE);
|
||||
|
||||
grub_vga_sr_write (0x86, 5);
|
||||
@@ -335,7 +335,7 @@ grub_video_sis315pro_setup (unsigned int width, unsigned int height,
|
||||
{
|
||||
if (read_sis_cmd (0x5) != 0xa1)
|
||||
write_sis_cmd (0x86, 0x5);
|
||||
-
|
||||
+
|
||||
write_sis_cmd (read_sis_cmd (0x20) | 0xa1, 0x20);
|
||||
write_sis_cmd (read_sis_cmd (0x1e) | 0xda, 0x1e);
|
||||
|
||||
diff --git a/grub-core/video/sm712.c b/grub-core/video/sm712.c
|
||||
index 10c46eb654..65f59f84b1 100644
|
||||
--- a/grub-core/video/sm712.c
|
||||
+++ b/grub-core/video/sm712.c
|
||||
@@ -167,7 +167,7 @@ enum
|
||||
GRUB_SM712_CR_SHADOW_VGA_VBLANK_START = 0x46,
|
||||
GRUB_SM712_CR_SHADOW_VGA_VBLANK_END = 0x47,
|
||||
GRUB_SM712_CR_SHADOW_VGA_VRETRACE_START = 0x48,
|
||||
- GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END = 0x49,
|
||||
+ GRUB_SM712_CR_SHADOW_VGA_VRETRACE_END = 0x49,
|
||||
GRUB_SM712_CR_SHADOW_VGA_OVERFLOW = 0x4a,
|
||||
GRUB_SM712_CR_SHADOW_VGA_CELL_HEIGHT = 0x4b,
|
||||
GRUB_SM712_CR_SHADOW_VGA_HDISPLAY_END = 0x4c,
|
||||
@@ -375,7 +375,7 @@ find_card (grub_pci_device_t dev, grub_pci_id_t pciid, void *data)
|
||||
if (((class >> 16) & 0xffff) != GRUB_PCI_CLASS_SUBCLASS_VGA
|
||||
|| pciid != GRUB_SM712_PCIID)
|
||||
return 0;
|
||||
-
|
||||
+
|
||||
*found = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
@@ -471,7 +471,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height,
|
||||
|
||||
#if !defined (TEST) && !defined(GENINIT)
|
||||
/* Prevent garbage from appearing on the screen. */
|
||||
- grub_memset ((void *) framebuffer.cached_ptr, 0,
|
||||
+ grub_memset ((void *) framebuffer.cached_ptr, 0,
|
||||
framebuffer.mode_info.height * framebuffer.mode_info.pitch);
|
||||
#endif
|
||||
|
||||
@@ -482,7 +482,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height,
|
||||
grub_sm712_sr_write (0x2, 0x6b);
|
||||
grub_sm712_write_reg (0, GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_sm712_sr_write (GRUB_VGA_SR_RESET_ASYNC, GRUB_VGA_SR_RESET);
|
||||
- grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY
|
||||
+ grub_sm712_write_reg (GRUB_VGA_IO_MISC_NEGATIVE_VERT_POLARITY
|
||||
| GRUB_VGA_IO_MISC_NEGATIVE_HORIZ_POLARITY
|
||||
| GRUB_VGA_IO_MISC_UPPER_64K
|
||||
| GRUB_VGA_IO_MISC_EXTERNAL_CLOCK_0
|
||||
@@ -694,7 +694,7 @@ grub_video_sm712_setup (unsigned int width, unsigned int height,
|
||||
for (i = 0; i < ARRAY_SIZE (dda_lookups); i++)
|
||||
grub_sm712_write_dda_lookup (i, dda_lookups[i].compare, dda_lookups[i].dda,
|
||||
dda_lookups[i].vcentering);
|
||||
-
|
||||
+
|
||||
/* Undocumented */
|
||||
grub_sm712_cr_write (0, 0x9c);
|
||||
grub_sm712_cr_write (0, 0x9d);
|
||||
diff --git a/grub-core/video/video.c b/grub-core/video/video.c
|
||||
index 983424107c..8937da745d 100644
|
||||
--- a/grub-core/video/video.c
|
||||
+++ b/grub-core/video/video.c
|
||||
@@ -491,13 +491,13 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth)
|
||||
current_mode);
|
||||
|
||||
param++;
|
||||
-
|
||||
+
|
||||
*width = grub_strtoul (value, 0, 0);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("invalid video mode specification `%s'"),
|
||||
current_mode);
|
||||
-
|
||||
+
|
||||
/* Find height value. */
|
||||
value = param;
|
||||
param = grub_strchr(param, 'x');
|
||||
@@ -513,13 +513,13 @@ parse_modespec (const char *current_mode, int *width, int *height, int *depth)
|
||||
{
|
||||
/* We have optional color depth value. */
|
||||
param++;
|
||||
-
|
||||
+
|
||||
*height = grub_strtoul (value, 0, 0);
|
||||
if (grub_errno != GRUB_ERR_NONE)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
N_("invalid video mode specification `%s'"),
|
||||
current_mode);
|
||||
-
|
||||
+
|
||||
/* Convert color depth value. */
|
||||
value = param;
|
||||
*depth = grub_strtoul (value, 0, 0);
|
||||
--
|
||||
2.34.1
|
||||
|
125
0002-loader-efi-chainloader-Simplify-the-loader-state.patch
Normal file
125
0002-loader-efi-chainloader-Simplify-the-loader-state.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From c111176648717645284865e15d7c6713cf29e982 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Tue, 5 Apr 2022 10:02:04 +0100
|
||||
Subject: [PATCH 02/32] loader/efi/chainloader: Simplify the loader state
|
||||
|
||||
The chainloader command retains the source buffer and device path passed
|
||||
to LoadImage(), requiring the unload hook passed to grub_loader_set() to
|
||||
free them. It isn't required to retain this state though - they aren't
|
||||
required by StartImage() or anything else in the boot hook, so clean them
|
||||
up before grub_cmd_chainloader() finishes.
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/loader/efi/chainloader.c | 37 ++++++++++++++++--------------
|
||||
1 file changed, 20 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index 625f1d26da..1ec09a166c 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -53,12 +53,8 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
-static grub_efi_physical_address_t address;
|
||||
-static grub_efi_uintn_t pages;
|
||||
static grub_ssize_t fsize;
|
||||
-static grub_efi_device_path_t *file_path;
|
||||
static grub_efi_handle_t image_handle;
|
||||
-static grub_efi_char16_t *cmdline;
|
||||
static grub_ssize_t cmdline_len;
|
||||
static grub_efi_handle_t dev_handle;
|
||||
|
||||
@@ -70,16 +66,16 @@ static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_e
|
||||
static grub_err_t
|
||||
grub_chainloader_unload (void)
|
||||
{
|
||||
+ grub_efi_loaded_image_t *loaded_image;
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
+ loaded_image = grub_efi_get_loaded_image (image_handle);
|
||||
+ if (loaded_image != NULL)
|
||||
+ grub_free (loaded_image->load_options);
|
||||
+
|
||||
b = grub_efi_system_table->boot_services;
|
||||
efi_call_1 (b->unload_image, image_handle);
|
||||
- efi_call_2 (b->free_pages, address, pages);
|
||||
|
||||
- grub_free (file_path);
|
||||
- grub_free (cmdline);
|
||||
- cmdline = 0;
|
||||
- file_path = 0;
|
||||
dev_handle = 0;
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
@@ -158,7 +154,7 @@ make_file_path (grub_efi_device_path_t *dp, const char *filename)
|
||||
char *dir_start;
|
||||
char *dir_end;
|
||||
grub_size_t size;
|
||||
- grub_efi_device_path_t *d;
|
||||
+ grub_efi_device_path_t *d, *file_path;
|
||||
|
||||
dir_start = grub_strchr (filename, ')');
|
||||
if (! dir_start)
|
||||
@@ -641,10 +637,13 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_device_t dev = 0;
|
||||
- grub_efi_device_path_t *dp = 0;
|
||||
+ grub_efi_device_path_t *dp = NULL, *file_path = NULL;
|
||||
grub_efi_loaded_image_t *loaded_image;
|
||||
char *filename;
|
||||
void *boot_image = 0;
|
||||
+ grub_efi_physical_address_t address = 0;
|
||||
+ grub_efi_uintn_t pages = 0;
|
||||
+ grub_efi_char16_t *cmdline = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
@@ -652,10 +651,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
- /* Initialize some global variables. */
|
||||
- address = 0;
|
||||
- image_handle = 0;
|
||||
- file_path = 0;
|
||||
dev_handle = 0;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
@@ -857,6 +852,10 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_file_close (file);
|
||||
grub_device_close (dev);
|
||||
|
||||
+ /* We're finished with the source image buffer and file path now. */
|
||||
+ efi_call_2 (b->free_pages, address, pages);
|
||||
+ grub_free (file_path);
|
||||
+
|
||||
grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
|
||||
return 0;
|
||||
|
||||
@@ -868,13 +867,17 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
if (file)
|
||||
grub_file_close (file);
|
||||
|
||||
+ grub_free (cmdline);
|
||||
grub_free (file_path);
|
||||
|
||||
if (address)
|
||||
efi_call_2 (b->free_pages, address, pages);
|
||||
|
||||
- if (cmdline)
|
||||
- grub_free (cmdline);
|
||||
+ if (image_handle != NULL)
|
||||
+ {
|
||||
+ efi_call_1 (b->unload_image, image_handle);
|
||||
+ image_handle = NULL;
|
||||
+ }
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
161
0003-commands-boot-Add-API-to-pass-context-to-loader.patch
Normal file
161
0003-commands-boot-Add-API-to-pass-context-to-loader.patch
Normal file
@ -0,0 +1,161 @@
|
||||
From 8bb57923d39f00b6f850cf6138ff5973cfd0d25f Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Tue, 5 Apr 2022 10:58:28 +0100
|
||||
Subject: [PATCH 03/32] commands/boot: Add API to pass context to loader
|
||||
|
||||
Loaders rely on global variables for saving context which is consumed
|
||||
in the boot hook and freed in the unload hook. In the case where a loader
|
||||
command is executed twice, calling grub_loader_set() a second time executes
|
||||
the unload hook, but in some cases this runs when the loader's global
|
||||
context has already been updated, resulting in the updated context being
|
||||
freed and potential use-after-free bugs when the boot hook is subsequently
|
||||
called.
|
||||
|
||||
This adds a new API, grub_loader_set_ex(), which allows a loader to specify
|
||||
context that is passed to its boot and unload hooks. This is an alternative
|
||||
to requiring that loaders call grub_loader_unset() before mutating their
|
||||
global context.
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/commands/boot.c | 66 ++++++++++++++++++++++++++++++++++-----
|
||||
include/grub/loader.h | 5 +++
|
||||
2 files changed, 63 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/commands/boot.c b/grub-core/commands/boot.c
|
||||
index bbca81e947..61514788e2 100644
|
||||
--- a/grub-core/commands/boot.c
|
||||
+++ b/grub-core/commands/boot.c
|
||||
@@ -27,10 +27,20 @@
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
-static grub_err_t (*grub_loader_boot_func) (void);
|
||||
-static grub_err_t (*grub_loader_unload_func) (void);
|
||||
+static grub_err_t (*grub_loader_boot_func) (void *context);
|
||||
+static grub_err_t (*grub_loader_unload_func) (void *context);
|
||||
+static void *grub_loader_context;
|
||||
static int grub_loader_flags;
|
||||
|
||||
+struct grub_simple_loader_hooks
|
||||
+{
|
||||
+ grub_err_t (*boot) (void);
|
||||
+ grub_err_t (*unload) (void);
|
||||
+};
|
||||
+
|
||||
+/* Don't heap allocate this to avoid making grub_loader_set() fallible. */
|
||||
+static struct grub_simple_loader_hooks simple_loader_hooks;
|
||||
+
|
||||
struct grub_preboot
|
||||
{
|
||||
grub_err_t (*preboot_func) (int);
|
||||
@@ -44,6 +54,29 @@ static int grub_loader_loaded;
|
||||
static struct grub_preboot *preboots_head = 0,
|
||||
*preboots_tail = 0;
|
||||
|
||||
+static grub_err_t
|
||||
+grub_simple_boot_hook (void *context)
|
||||
+{
|
||||
+ struct grub_simple_loader_hooks *hooks;
|
||||
+
|
||||
+ hooks = (struct grub_simple_loader_hooks *) context;
|
||||
+ return hooks->boot ();
|
||||
+}
|
||||
+
|
||||
+static grub_err_t
|
||||
+grub_simple_unload_hook (void *context)
|
||||
+{
|
||||
+ struct grub_simple_loader_hooks *hooks;
|
||||
+ grub_err_t ret;
|
||||
+
|
||||
+ hooks = (struct grub_simple_loader_hooks *) context;
|
||||
+
|
||||
+ ret = hooks->unload ();
|
||||
+ grub_memset (hooks, 0, sizeof (*hooks));
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
int
|
||||
grub_loader_is_loaded (void)
|
||||
{
|
||||
@@ -110,28 +143,45 @@ grub_loader_unregister_preboot_hook (struct grub_preboot *hnd)
|
||||
}
|
||||
|
||||
void
|
||||
-grub_loader_set (grub_err_t (*boot) (void),
|
||||
- grub_err_t (*unload) (void),
|
||||
- int flags)
|
||||
+grub_loader_set_ex (grub_err_t (*boot) (void *context),
|
||||
+ grub_err_t (*unload) (void *context),
|
||||
+ void *context,
|
||||
+ int flags)
|
||||
{
|
||||
if (grub_loader_loaded && grub_loader_unload_func)
|
||||
- grub_loader_unload_func ();
|
||||
+ grub_loader_unload_func (grub_loader_context);
|
||||
|
||||
grub_loader_boot_func = boot;
|
||||
grub_loader_unload_func = unload;
|
||||
+ grub_loader_context = context;
|
||||
grub_loader_flags = flags;
|
||||
|
||||
grub_loader_loaded = 1;
|
||||
}
|
||||
|
||||
+void
|
||||
+grub_loader_set (grub_err_t (*boot) (void),
|
||||
+ grub_err_t (*unload) (void),
|
||||
+ int flags)
|
||||
+{
|
||||
+ grub_loader_set_ex (grub_simple_boot_hook,
|
||||
+ grub_simple_unload_hook,
|
||||
+ &simple_loader_hooks,
|
||||
+ flags);
|
||||
+
|
||||
+ simple_loader_hooks.boot = boot;
|
||||
+ simple_loader_hooks.unload = unload;
|
||||
+}
|
||||
+
|
||||
void
|
||||
grub_loader_unset(void)
|
||||
{
|
||||
if (grub_loader_loaded && grub_loader_unload_func)
|
||||
- grub_loader_unload_func ();
|
||||
+ grub_loader_unload_func (grub_loader_context);
|
||||
|
||||
grub_loader_boot_func = 0;
|
||||
grub_loader_unload_func = 0;
|
||||
+ grub_loader_context = 0;
|
||||
|
||||
grub_loader_loaded = 0;
|
||||
}
|
||||
@@ -158,7 +208,7 @@ grub_loader_boot (void)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
- err = (grub_loader_boot_func) ();
|
||||
+ err = (grub_loader_boot_func) (grub_loader_context);
|
||||
|
||||
for (cur = preboots_tail; cur; cur = cur->prev)
|
||||
if (! err)
|
||||
diff --git a/include/grub/loader.h b/include/grub/loader.h
|
||||
index b208642821..97f2310545 100644
|
||||
--- a/include/grub/loader.h
|
||||
+++ b/include/grub/loader.h
|
||||
@@ -40,6 +40,11 @@ void EXPORT_FUNC (grub_loader_set) (grub_err_t (*boot) (void),
|
||||
grub_err_t (*unload) (void),
|
||||
int flags);
|
||||
|
||||
+void EXPORT_FUNC (grub_loader_set_ex) (grub_err_t (*boot) (void *context),
|
||||
+ grub_err_t (*unload) (void *context),
|
||||
+ void *context,
|
||||
+ int flags);
|
||||
+
|
||||
/* Unset current loader, if any. */
|
||||
void EXPORT_FUNC (grub_loader_unset) (void);
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
83
0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
Normal file
83
0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
Normal file
@ -0,0 +1,83 @@
|
||||
From e0cc6a601865a72cfe316f2cbbaaefcdd2ad8c69 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Coulson <chris.coulson@canonical.com>
|
||||
Date: Tue, 5 Apr 2022 11:48:58 +0100
|
||||
Subject: [PATCH 04/32] loader/efi/chainloader: Use grub_loader_set_ex()
|
||||
|
||||
This ports the EFI chainloader to use grub_loader_set_ex() in order to fix
|
||||
a use-after-free bug that occurs when grub_cmd_chainloader() is executed
|
||||
more than once before a boot attempt is performed.
|
||||
|
||||
Fixes: CVE-2022-28736
|
||||
|
||||
Signed-off-by: Chris Coulson <chris.coulson@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/loader/efi/chainloader.c | 15 +++++++--------
|
||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index 1ec09a166c..b3e1e89302 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -54,7 +54,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
static grub_ssize_t fsize;
|
||||
-static grub_efi_handle_t image_handle;
|
||||
static grub_ssize_t cmdline_len;
|
||||
static grub_efi_handle_t dev_handle;
|
||||
|
||||
@@ -64,8 +63,9 @@ static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_e
|
||||
#endif
|
||||
|
||||
static grub_err_t
|
||||
-grub_chainloader_unload (void)
|
||||
+grub_chainloader_unload (void *context)
|
||||
{
|
||||
+ grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
|
||||
grub_efi_loaded_image_t *loaded_image;
|
||||
grub_efi_boot_services_t *b;
|
||||
|
||||
@@ -83,8 +83,9 @@ grub_chainloader_unload (void)
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_chainloader_boot (void)
|
||||
+grub_chainloader_boot (void *context)
|
||||
{
|
||||
+ grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_uintn_t exit_data_size;
|
||||
@@ -644,6 +645,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_efi_physical_address_t address = 0;
|
||||
grub_efi_uintn_t pages = 0;
|
||||
grub_efi_char16_t *cmdline = NULL;
|
||||
+ grub_efi_handle_t image_handle = NULL;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
@@ -856,7 +858,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
efi_call_2 (b->free_pages, address, pages);
|
||||
grub_free (file_path);
|
||||
|
||||
- grub_loader_set (grub_chainloader_boot, grub_chainloader_unload, 0);
|
||||
+ grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload, image_handle, 0);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@@ -874,10 +876,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
efi_call_2 (b->free_pages, address, pages);
|
||||
|
||||
if (image_handle != NULL)
|
||||
- {
|
||||
- efi_call_1 (b->unload_image, image_handle);
|
||||
- image_handle = NULL;
|
||||
- }
|
||||
+ efi_call_1 (b->unload_image, image_handle);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
103
0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
Normal file
103
0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From ee99e452b9c1aafd3eb80592830ae2c6f69eb395 Mon Sep 17 00:00:00 2001
|
||||
From: Julian Andres Klode <julian.klode@canonical.com>
|
||||
Date: Thu, 2 Dec 2021 15:03:53 +0100
|
||||
Subject: [PATCH 05/32] kern/efi/sb: Reject non-kernel files in the shim_lock
|
||||
verifier
|
||||
|
||||
We must not allow other verifiers to pass things like the GRUB modules.
|
||||
Instead of maintaining a blocklist, maintain an allowlist of things
|
||||
that we do not care about.
|
||||
|
||||
This allowlist really should be made reusable, and shared by the
|
||||
lockdown verifier, but this is the minimal patch addressing
|
||||
security concerns where the TPM verifier was able to mark modules
|
||||
as verified (or the OpenPGP verifier for that matter), when it
|
||||
should not do so on shim-powered secure boot systems.
|
||||
|
||||
Fixes: CVE-2022-28735
|
||||
|
||||
Signed-off-by: Julian Andres Klode <julian.klode@canonical.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/efi/sb.c | 39 ++++++++++++++++++++++++++++++++++++---
|
||||
include/grub/verify.h | 1 +
|
||||
2 files changed, 37 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c
|
||||
index c52ec6226a..89c4bb3fd1 100644
|
||||
--- a/grub-core/kern/efi/sb.c
|
||||
+++ b/grub-core/kern/efi/sb.c
|
||||
@@ -119,10 +119,11 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
|
||||
void **context __attribute__ ((unused)),
|
||||
enum grub_verify_flags *flags)
|
||||
{
|
||||
- *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
|
||||
+ *flags = GRUB_VERIFY_FLAGS_NONE;
|
||||
|
||||
switch (type & GRUB_FILE_TYPE_MASK)
|
||||
{
|
||||
+ /* Files we check. */
|
||||
case GRUB_FILE_TYPE_LINUX_KERNEL:
|
||||
case GRUB_FILE_TYPE_MULTIBOOT_KERNEL:
|
||||
case GRUB_FILE_TYPE_BSD_KERNEL:
|
||||
@@ -130,11 +131,43 @@ shim_lock_verifier_init (grub_file_t io __attribute__ ((unused)),
|
||||
case GRUB_FILE_TYPE_PLAN9_KERNEL:
|
||||
case GRUB_FILE_TYPE_EFI_CHAINLOADED_IMAGE:
|
||||
*flags = GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
|
||||
+ return GRUB_ERR_NONE;
|
||||
|
||||
- /* Fall through. */
|
||||
+ /* Files that do not affect secureboot state. */
|
||||
+ case GRUB_FILE_TYPE_NONE:
|
||||
+ case GRUB_FILE_TYPE_LOOPBACK:
|
||||
+ case GRUB_FILE_TYPE_LINUX_INITRD:
|
||||
+ case GRUB_FILE_TYPE_OPENBSD_RAMDISK:
|
||||
+ case GRUB_FILE_TYPE_XNU_RAMDISK:
|
||||
+ case GRUB_FILE_TYPE_SIGNATURE:
|
||||
+ case GRUB_FILE_TYPE_PUBLIC_KEY:
|
||||
+ case GRUB_FILE_TYPE_PUBLIC_KEY_TRUST:
|
||||
+ case GRUB_FILE_TYPE_PRINT_BLOCKLIST:
|
||||
+ case GRUB_FILE_TYPE_TESTLOAD:
|
||||
+ case GRUB_FILE_TYPE_GET_SIZE:
|
||||
+ case GRUB_FILE_TYPE_FONT:
|
||||
+ case GRUB_FILE_TYPE_ZFS_ENCRYPTION_KEY:
|
||||
+ case GRUB_FILE_TYPE_CAT:
|
||||
+ case GRUB_FILE_TYPE_HEXCAT:
|
||||
+ case GRUB_FILE_TYPE_CMP:
|
||||
+ case GRUB_FILE_TYPE_HASHLIST:
|
||||
+ case GRUB_FILE_TYPE_TO_HASH:
|
||||
+ case GRUB_FILE_TYPE_KEYBOARD_LAYOUT:
|
||||
+ case GRUB_FILE_TYPE_PIXMAP:
|
||||
+ case GRUB_FILE_TYPE_GRUB_MODULE_LIST:
|
||||
+ case GRUB_FILE_TYPE_CONFIG:
|
||||
+ case GRUB_FILE_TYPE_THEME:
|
||||
+ case GRUB_FILE_TYPE_GETTEXT_CATALOG:
|
||||
+ case GRUB_FILE_TYPE_FS_SEARCH:
|
||||
+ case GRUB_FILE_TYPE_LOADENV:
|
||||
+ case GRUB_FILE_TYPE_SAVEENV:
|
||||
+ case GRUB_FILE_TYPE_VERIFY_SIGNATURE:
|
||||
+ *flags = GRUB_VERIFY_FLAGS_SKIP_VERIFICATION;
|
||||
+ return GRUB_ERR_NONE;
|
||||
|
||||
+ /* Other files. */
|
||||
default:
|
||||
- return GRUB_ERR_NONE;
|
||||
+ return grub_error (GRUB_ERR_ACCESS_DENIED, N_("prohibited by secure boot policy"));
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/include/grub/verify.h b/include/grub/verify.h
|
||||
index 6fde244fc6..67448165f4 100644
|
||||
--- a/include/grub/verify.h
|
||||
+++ b/include/grub/verify.h
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
enum grub_verify_flags
|
||||
{
|
||||
+ GRUB_VERIFY_FLAGS_NONE = 0,
|
||||
GRUB_VERIFY_FLAGS_SKIP_VERIFICATION = 1,
|
||||
GRUB_VERIFY_FLAGS_SINGLE_CHUNK = 2,
|
||||
/* Defer verification to another authority. */
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,41 @@
|
||||
From 77a70351615e0b6e66d663e063e9b4ba8ae129a0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Fri, 25 Jun 2021 02:19:05 +1000
|
||||
Subject: [PATCH 06/32] kern/file: Do not leak device_name on error in
|
||||
grub_file_open()
|
||||
|
||||
If we have an error in grub_file_open() before we free device_name, we
|
||||
will leak it.
|
||||
|
||||
Free device_name in the error path and null out the pointer in the good
|
||||
path once we free it there.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/kern/file.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/grub-core/kern/file.c b/grub-core/kern/file.c
|
||||
index 58454458c4..ffdcaba05f 100644
|
||||
--- a/grub-core/kern/file.c
|
||||
+++ b/grub-core/kern/file.c
|
||||
@@ -79,6 +79,7 @@ grub_file_open (const char *name, enum grub_file_type type)
|
||||
|
||||
device = grub_device_open (device_name);
|
||||
grub_free (device_name);
|
||||
+ device_name = NULL;
|
||||
if (! device)
|
||||
goto fail;
|
||||
|
||||
@@ -131,6 +132,7 @@ grub_file_open (const char *name, enum grub_file_type type)
|
||||
return file;
|
||||
|
||||
fail:
|
||||
+ grub_free (device_name);
|
||||
if (device)
|
||||
grub_device_close (device);
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
201
0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
Normal file
201
0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
Normal file
@ -0,0 +1,201 @@
|
||||
From 9db9558e1c75d47beca7ba378a99471c57729be5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 6 Jul 2021 14:02:55 +1000
|
||||
Subject: [PATCH 07/32] video/readers/png: Abort sooner if a read operation
|
||||
fails
|
||||
|
||||
Fuzzing revealed some inputs that were taking a long time, potentially
|
||||
forever, because they did not bail quickly upon encountering an I/O error.
|
||||
|
||||
Try to catch I/O errors sooner and bail out.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/png.c | 55 ++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 47 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
|
||||
index 54dfedf435..d715c4629f 100644
|
||||
--- a/grub-core/video/readers/png.c
|
||||
+++ b/grub-core/video/readers/png.c
|
||||
@@ -142,6 +142,7 @@ static grub_uint8_t
|
||||
grub_png_get_byte (struct grub_png_data *data)
|
||||
{
|
||||
grub_uint8_t r;
|
||||
+ grub_ssize_t bytes_read = 0;
|
||||
|
||||
if ((data->inside_idat) && (data->idat_remain == 0))
|
||||
{
|
||||
@@ -175,7 +176,14 @@ grub_png_get_byte (struct grub_png_data *data)
|
||||
}
|
||||
|
||||
r = 0;
|
||||
- grub_file_read (data->file, &r, 1);
|
||||
+ bytes_read = grub_file_read (data->file, &r, 1);
|
||||
+
|
||||
+ if (bytes_read != 1)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "png: unexpected end of data");
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
if (data->inside_idat)
|
||||
data->idat_remain--;
|
||||
@@ -231,15 +239,16 @@ grub_png_decode_image_palette (struct grub_png_data *data,
|
||||
if (len == 0)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
- for (i = 0; 3 * i < len && i < 256; i++)
|
||||
+ grub_errno = GRUB_ERR_NONE;
|
||||
+ for (i = 0; 3 * i < len && i < 256 && grub_errno == GRUB_ERR_NONE; i++)
|
||||
for (j = 0; j < 3; j++)
|
||||
data->palette[i][j] = grub_png_get_byte (data);
|
||||
- for (i *= 3; i < len; i++)
|
||||
+ for (i *= 3; i < len && grub_errno == GRUB_ERR_NONE; i++)
|
||||
grub_png_get_byte (data);
|
||||
|
||||
grub_png_get_dword (data);
|
||||
|
||||
- return GRUB_ERR_NONE;
|
||||
+ return grub_errno;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
@@ -256,9 +265,13 @@ grub_png_decode_image_header (struct grub_png_data *data)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: invalid image size");
|
||||
|
||||
color_bits = grub_png_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
data->is_16bit = (color_bits == 16);
|
||||
|
||||
color_type = grub_png_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
/* According to PNG spec, no other types are valid. */
|
||||
if ((color_type & ~(PNG_COLOR_MASK_ALPHA | PNG_COLOR_MASK_COLOR))
|
||||
@@ -340,14 +353,20 @@ grub_png_decode_image_header (struct grub_png_data *data)
|
||||
if (grub_png_get_byte (data) != PNG_COMPRESSION_BASE)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"png: compression method not supported");
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
if (grub_png_get_byte (data) != PNG_FILTER_TYPE_BASE)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"png: filter method not supported");
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
if (grub_png_get_byte (data) != PNG_INTERLACE_NONE)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"png: interlace method not supported");
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
/* Skip crc checksum. */
|
||||
grub_png_get_dword (data);
|
||||
@@ -449,7 +468,7 @@ grub_png_get_huff_code (struct grub_png_data *data, struct huff_table *ht)
|
||||
int code, i;
|
||||
|
||||
code = 0;
|
||||
- for (i = 0; i < ht->max_length; i++)
|
||||
+ for (i = 0; i < ht->max_length && grub_errno == GRUB_ERR_NONE; i++)
|
||||
{
|
||||
code = (code << 1) + grub_png_get_bits (data, 1);
|
||||
if (code < ht->maxval[i])
|
||||
@@ -504,8 +523,14 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
|
||||
grub_uint8_t lens[DEFLATE_HCLEN_MAX];
|
||||
|
||||
nl = DEFLATE_HLIT_BASE + grub_png_get_bits (data, 5);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
nd = DEFLATE_HDIST_BASE + grub_png_get_bits (data, 5);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
nb = DEFLATE_HCLEN_BASE + grub_png_get_bits (data, 4);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
if ((nl > DEFLATE_HLIT_MAX) || (nd > DEFLATE_HDIST_MAX) ||
|
||||
(nb > DEFLATE_HCLEN_MAX))
|
||||
@@ -533,7 +558,7 @@ grub_png_init_dynamic_block (struct grub_png_data *data)
|
||||
data->dist_offset);
|
||||
|
||||
prev = 0;
|
||||
- for (i = 0; i < nl + nd; i++)
|
||||
+ for (i = 0; i < nl + nd && grub_errno == GRUB_ERR_NONE; i++)
|
||||
{
|
||||
int n, code;
|
||||
struct huff_table *ht;
|
||||
@@ -721,17 +746,21 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
|
||||
len = cplens[n];
|
||||
if (cplext[n])
|
||||
len += grub_png_get_bits (data, cplext[n]);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
n = grub_png_get_huff_code (data, &data->dist_table);
|
||||
dist = cpdist[n];
|
||||
if (cpdext[n])
|
||||
dist += grub_png_get_bits (data, cpdext[n]);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
pos = data->wp - dist;
|
||||
if (pos < 0)
|
||||
pos += WSIZE;
|
||||
|
||||
- while (len > 0)
|
||||
+ while (len > 0 && grub_errno == GRUB_ERR_NONE)
|
||||
{
|
||||
data->slide[data->wp] = data->slide[pos];
|
||||
grub_png_output_byte (data, data->slide[data->wp]);
|
||||
@@ -759,7 +788,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
|
||||
int final;
|
||||
|
||||
cmf = grub_png_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
flg = grub_png_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
if ((cmf & 0xF) != Z_DEFLATED)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
@@ -774,7 +807,11 @@ grub_png_decode_image_data (struct grub_png_data *data)
|
||||
int block_type;
|
||||
|
||||
final = grub_png_get_bits (data, 1);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
block_type = grub_png_get_bits (data, 2);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
switch (block_type)
|
||||
{
|
||||
@@ -790,7 +827,7 @@ grub_png_decode_image_data (struct grub_png_data *data)
|
||||
grub_png_get_byte (data);
|
||||
grub_png_get_byte (data);
|
||||
|
||||
- for (i = 0; i < len; i++)
|
||||
+ for (i = 0; i < len && grub_errno == GRUB_ERR_NONE; i++)
|
||||
grub_png_output_byte (data, grub_png_get_byte (data));
|
||||
|
||||
break;
|
||||
@@ -1045,6 +1082,8 @@ grub_png_decode_png (struct grub_png_data *data)
|
||||
|
||||
len = grub_png_get_dword (data);
|
||||
type = grub_png_get_dword (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ break;
|
||||
data->next_offset = data->file->offset + len + 4;
|
||||
|
||||
switch (type)
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,31 @@
|
||||
From 2ca24e4cc44effd08fe6dfa05ad8417a9b186f42 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 6 Jul 2021 14:13:40 +1000
|
||||
Subject: [PATCH 08/32] video/readers/png: Refuse to handle multiple image
|
||||
headers
|
||||
|
||||
This causes the bitmap to be leaked. Do not permit multiple image headers.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/png.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
|
||||
index d715c4629f..35ae553c8e 100644
|
||||
--- a/grub-core/video/readers/png.c
|
||||
+++ b/grub-core/video/readers/png.c
|
||||
@@ -258,6 +258,9 @@ grub_png_decode_image_header (struct grub_png_data *data)
|
||||
int color_bits;
|
||||
enum grub_video_blit_format blt;
|
||||
|
||||
+ if (data->image_width || data->image_height)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "png: two image headers found");
|
||||
+
|
||||
data->image_width = grub_png_get_dword (data);
|
||||
data->image_height = grub_png_get_dword (data);
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
171
0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
Normal file
171
0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From 7be3f3b1b7be0602056721526878c91d3333f8fd Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 6 Jul 2021 18:51:35 +1000
|
||||
Subject: [PATCH 09/32] 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>
|
||||
---
|
||||
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 35ae553c8e..a3161e25b6 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
|
||||
|
@ -0,0 +1,42 @@
|
||||
From 8ebb6943eae81d3c31963bbae42d5d1f168c8dd5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 6 Jul 2021 23:25:07 +1000
|
||||
Subject: [PATCH 10/32] video/readers/png: Avoid heap OOB R/W inserting huff
|
||||
table items
|
||||
|
||||
In fuzzing we observed crashes where a code would attempt to be inserted
|
||||
into a huffman table before the start, leading to a set of heap OOB reads
|
||||
and writes as table entries with negative indices were shifted around and
|
||||
the new code written in.
|
||||
|
||||
Catch the case where we would underflow the array and bail.
|
||||
|
||||
Fixes: CVE-2021-3696
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/png.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
|
||||
index a3161e25b6..d7ed5aa6cf 100644
|
||||
--- a/grub-core/video/readers/png.c
|
||||
+++ b/grub-core/video/readers/png.c
|
||||
@@ -438,6 +438,13 @@ grub_png_insert_huff_item (struct huff_table *ht, int code, int len)
|
||||
for (i = len; i < ht->max_length; i++)
|
||||
n += ht->maxval[i];
|
||||
|
||||
+ if (n > ht->num_values)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "png: out of range inserting huffman table item");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < n; i++)
|
||||
ht->values[ht->num_values - i] = ht->values[ht->num_values - i - 1];
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
42
0011-video-readers-png-Sanity-check-some-huffman-codes.patch
Normal file
42
0011-video-readers-png-Sanity-check-some-huffman-codes.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From bbbb410d5d7d29d935e7108c77a0368e4e007a43 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 6 Jul 2021 19:19:11 +1000
|
||||
Subject: [PATCH 11/32] video/readers/png: Sanity check some huffman codes
|
||||
|
||||
ASAN picked up two OOB global reads: we weren't checking if some code
|
||||
values fit within the cplens or cpdext arrays. Check and throw an error
|
||||
if not.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/png.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/grub-core/video/readers/png.c b/grub-core/video/readers/png.c
|
||||
index d7ed5aa6cf..7f2ba7849b 100644
|
||||
--- a/grub-core/video/readers/png.c
|
||||
+++ b/grub-core/video/readers/png.c
|
||||
@@ -753,6 +753,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
|
||||
int len, dist, pos;
|
||||
|
||||
n -= 257;
|
||||
+ if (((unsigned int) n) >= ARRAY_SIZE (cplens))
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "png: invalid huff code");
|
||||
len = cplens[n];
|
||||
if (cplext[n])
|
||||
len += grub_png_get_bits (data, cplext[n]);
|
||||
@@ -760,6 +763,9 @@ grub_png_read_dynamic_block (struct grub_png_data *data)
|
||||
return grub_errno;
|
||||
|
||||
n = grub_png_get_huff_code (data, &data->dist_table);
|
||||
+ if (((unsigned int) n) >= ARRAY_SIZE (cpdist))
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "png: invalid huff code");
|
||||
dist = cpdist[n];
|
||||
if (cpdext[n])
|
||||
dist += grub_png_get_bits (data, cpdext[n]);
|
||||
--
|
||||
2.34.1
|
||||
|
258
0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
Normal file
258
0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
Normal file
@ -0,0 +1,258 @@
|
||||
From 27134e18072a9dffb2bda6b74cd312be5360baa0 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Mon, 28 Jun 2021 14:16:14 +1000
|
||||
Subject: [PATCH 12/32] video/readers/jpeg: Abort sooner if a read operation
|
||||
fails
|
||||
|
||||
Fuzzing revealed some inputs that were taking a long time, potentially
|
||||
forever, because they did not bail quickly upon encountering an I/O error.
|
||||
|
||||
Try to catch I/O errors sooner and bail out.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/jpeg.c | 86 +++++++++++++++++++++++++++-------
|
||||
1 file changed, 70 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
|
||||
index e31602f766..10225abd53 100644
|
||||
--- a/grub-core/video/readers/jpeg.c
|
||||
+++ b/grub-core/video/readers/jpeg.c
|
||||
@@ -109,9 +109,17 @@ static grub_uint8_t
|
||||
grub_jpeg_get_byte (struct grub_jpeg_data *data)
|
||||
{
|
||||
grub_uint8_t r;
|
||||
+ grub_ssize_t bytes_read;
|
||||
|
||||
r = 0;
|
||||
- grub_file_read (data->file, &r, 1);
|
||||
+ bytes_read = grub_file_read (data->file, &r, 1);
|
||||
+
|
||||
+ if (bytes_read != 1)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: unexpected end of data");
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -120,9 +128,17 @@ static grub_uint16_t
|
||||
grub_jpeg_get_word (struct grub_jpeg_data *data)
|
||||
{
|
||||
grub_uint16_t r;
|
||||
+ grub_ssize_t bytes_read;
|
||||
|
||||
r = 0;
|
||||
- grub_file_read (data->file, &r, sizeof (grub_uint16_t));
|
||||
+ bytes_read = grub_file_read (data->file, &r, sizeof (grub_uint16_t));
|
||||
+
|
||||
+ if (bytes_read != sizeof (grub_uint16_t))
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: unexpected end of data");
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
return grub_be_to_cpu16 (r);
|
||||
}
|
||||
@@ -135,6 +151,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
|
||||
if (data->bit_mask == 0)
|
||||
{
|
||||
data->bit_save = grub_jpeg_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE) {
|
||||
+ grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: file read error");
|
||||
+ return 0;
|
||||
+ }
|
||||
if (data->bit_save == JPEG_ESC_CHAR)
|
||||
{
|
||||
if (grub_jpeg_get_byte (data) != 0)
|
||||
@@ -143,6 +164,11 @@ grub_jpeg_get_bit (struct grub_jpeg_data *data)
|
||||
"jpeg: invalid 0xFF in data stream");
|
||||
return 0;
|
||||
}
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: file read error");
|
||||
+ return 0;
|
||||
+ }
|
||||
}
|
||||
data->bit_mask = 0x80;
|
||||
}
|
||||
@@ -161,7 +187,7 @@ grub_jpeg_get_number (struct grub_jpeg_data *data, int num)
|
||||
return 0;
|
||||
|
||||
msb = value = grub_jpeg_get_bit (data);
|
||||
- for (i = 1; i < num; i++)
|
||||
+ for (i = 1; i < num && grub_errno == GRUB_ERR_NONE; i++)
|
||||
value = (value << 1) + (grub_jpeg_get_bit (data) != 0);
|
||||
if (!msb)
|
||||
value += 1 - (1 << num);
|
||||
@@ -202,6 +228,8 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
|
||||
while (data->file->offset + sizeof (count) + 1 <= next_marker)
|
||||
{
|
||||
id = grub_jpeg_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
ac = (id >> 4) & 1;
|
||||
id &= 0xF;
|
||||
if (id > 1)
|
||||
@@ -252,6 +280,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
|
||||
|
||||
next_marker = data->file->offset;
|
||||
next_marker += grub_jpeg_get_word (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
|
||||
if (next_marker > data->file->size)
|
||||
{
|
||||
@@ -263,6 +293,8 @@ grub_jpeg_decode_quan_table (struct grub_jpeg_data *data)
|
||||
<= next_marker)
|
||||
{
|
||||
id = grub_jpeg_get_byte (data);
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
if (id >= 0x10) /* Upper 4-bit is precision. */
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"jpeg: only 8-bit precision is supported");
|
||||
@@ -294,6 +326,9 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
|
||||
next_marker = data->file->offset;
|
||||
next_marker += grub_jpeg_get_word (data);
|
||||
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
+
|
||||
if (grub_jpeg_get_byte (data) != 8)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"jpeg: only 8-bit precision is supported");
|
||||
@@ -319,6 +354,8 @@ grub_jpeg_decode_sof (struct grub_jpeg_data *data)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
|
||||
|
||||
ss = grub_jpeg_get_byte (data); /* Sampling factor. */
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
if (!id)
|
||||
{
|
||||
grub_uint8_t vs, hs;
|
||||
@@ -498,7 +535,7 @@ grub_jpeg_idct_transform (jpeg_data_unit_t du)
|
||||
}
|
||||
}
|
||||
|
||||
-static void
|
||||
+static grub_err_t
|
||||
grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
|
||||
{
|
||||
int h1, h2, qt;
|
||||
@@ -513,6 +550,9 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
|
||||
data->dc_value[id] +=
|
||||
grub_jpeg_get_number (data, grub_jpeg_get_huff_code (data, h1));
|
||||
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
+
|
||||
du[0] = data->dc_value[id] * (int) data->quan_table[qt][0];
|
||||
pos = 1;
|
||||
while (pos < ARRAY_SIZE (data->quan_table[qt]))
|
||||
@@ -527,11 +567,13 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
|
||||
num >>= 4;
|
||||
pos += num;
|
||||
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
+
|
||||
if (pos >= ARRAY_SIZE (jpeg_zigzag_order))
|
||||
{
|
||||
- grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
- "jpeg: invalid position in zigzag order!?");
|
||||
- return;
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: invalid position in zigzag order!?");
|
||||
}
|
||||
|
||||
du[jpeg_zigzag_order[pos]] = val * (int) data->quan_table[qt][pos];
|
||||
@@ -539,6 +581,7 @@ grub_jpeg_decode_du (struct grub_jpeg_data *data, int id, jpeg_data_unit_t du)
|
||||
}
|
||||
|
||||
grub_jpeg_idct_transform (du);
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -597,7 +640,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
|
||||
data_offset += grub_jpeg_get_word (data);
|
||||
|
||||
cc = grub_jpeg_get_byte (data);
|
||||
-
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
if (cc != 3 && cc != 1)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"jpeg: component count must be 1 or 3");
|
||||
@@ -610,7 +654,8 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
|
||||
id = grub_jpeg_get_byte (data) - 1;
|
||||
if ((id < 0) || (id >= 3))
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid index");
|
||||
-
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
ht = grub_jpeg_get_byte (data);
|
||||
data->comp_index[id][1] = (ht >> 4);
|
||||
data->comp_index[id][2] = (ht & 0xF) + 2;
|
||||
@@ -618,11 +663,14 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
|
||||
if ((data->comp_index[id][1] < 0) || (data->comp_index[id][1] > 3) ||
|
||||
(data->comp_index[id][2] < 0) || (data->comp_index[id][2] > 3))
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: invalid hufftable index");
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
}
|
||||
|
||||
grub_jpeg_get_byte (data); /* Skip 3 unused bytes. */
|
||||
grub_jpeg_get_word (data);
|
||||
-
|
||||
+ if (grub_errno != GRUB_ERR_NONE)
|
||||
+ return grub_errno;
|
||||
if (data->file->offset != data_offset)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
|
||||
|
||||
@@ -640,6 +688,7 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
|
||||
{
|
||||
unsigned c1, vb, hb, nr1, nc1;
|
||||
int rst = data->dri;
|
||||
+ grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
vb = 8 << data->log_vs;
|
||||
hb = 8 << data->log_hs;
|
||||
@@ -660,17 +709,22 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
|
||||
|
||||
for (r2 = 0; r2 < (1U << data->log_vs); r2++)
|
||||
for (c2 = 0; c2 < (1U << data->log_hs); c2++)
|
||||
- grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
|
||||
+ {
|
||||
+ err = grub_jpeg_decode_du (data, 0, data->ydu[r2 * 2 + c2]);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
if (data->color_components >= 3)
|
||||
{
|
||||
- grub_jpeg_decode_du (data, 1, data->cbdu);
|
||||
- grub_jpeg_decode_du (data, 2, data->crdu);
|
||||
+ err = grub_jpeg_decode_du (data, 1, data->cbdu);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
+ err = grub_jpeg_decode_du (data, 2, data->crdu);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return err;
|
||||
}
|
||||
|
||||
- if (grub_errno)
|
||||
- return grub_errno;
|
||||
-
|
||||
nr2 = (data->r1 == nr1 - 1) ? (data->image_height - data->r1 * vb) : vb;
|
||||
nc2 = (c1 == nc1 - 1) ? (data->image_width - c1 * hb) : hb;
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,32 @@
|
||||
From 8f8282090a1d1469bffd0db6a07275882628caeb Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Mon, 28 Jun 2021 14:16:58 +1000
|
||||
Subject: [PATCH 13/32] video/readers/jpeg: Do not reallocate a given huff
|
||||
table
|
||||
|
||||
Fix a memory leak where an invalid file could cause us to reallocate
|
||||
memory for a huffman table we had already allocated memory for.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/jpeg.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
|
||||
index 10225abd53..caa211f06d 100644
|
||||
--- a/grub-core/video/readers/jpeg.c
|
||||
+++ b/grub-core/video/readers/jpeg.c
|
||||
@@ -245,6 +245,9 @@ grub_jpeg_decode_huff_table (struct grub_jpeg_data *data)
|
||||
n += count[i];
|
||||
|
||||
id += ac * 2;
|
||||
+ if (data->huff_value[id] != NULL)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: attempt to reallocate huffman table");
|
||||
data->huff_value[id] = grub_malloc (n);
|
||||
if (grub_errno)
|
||||
return grub_errno;
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,46 @@
|
||||
From 9b6026ba4eb26eadc7ddb8df1c49f648efe257c5 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Mon, 28 Jun 2021 14:25:17 +1000
|
||||
Subject: [PATCH 14/32] video/readers/jpeg: Refuse to handle multiple start of
|
||||
streams
|
||||
|
||||
An invalid file could contain multiple start of stream blocks, which
|
||||
would cause us to reallocate and leak our bitmap. Refuse to handle
|
||||
multiple start of streams.
|
||||
|
||||
Additionally, fix a grub_error() call formatting.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/jpeg.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
|
||||
index caa211f06d..1df1171d78 100644
|
||||
--- a/grub-core/video/readers/jpeg.c
|
||||
+++ b/grub-core/video/readers/jpeg.c
|
||||
@@ -677,6 +677,9 @@ grub_jpeg_decode_sos (struct grub_jpeg_data *data)
|
||||
if (data->file->offset != data_offset)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: extra byte in sos");
|
||||
|
||||
+ if (*data->bitmap)
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE, "jpeg: too many start of scan blocks");
|
||||
+
|
||||
if (grub_video_bitmap_create (data->bitmap, data->image_width,
|
||||
data->image_height,
|
||||
GRUB_VIDEO_BLIT_FORMAT_RGB_888))
|
||||
@@ -699,8 +702,8 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
|
||||
nc1 = (data->image_width + hb - 1) >> (3 + data->log_hs);
|
||||
|
||||
if (data->bitmap_ptr == NULL)
|
||||
- return grub_error(GRUB_ERR_BAD_FILE_TYPE,
|
||||
- "jpeg: attempted to decode data before start of stream");
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: attempted to decode data before start of stream");
|
||||
|
||||
for (; data->r1 < nr1 && (!data->dri || rst);
|
||||
data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,77 @@
|
||||
From 9a6e9ad21eb2f414dce6eaedd41e146a28142101 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Wed, 7 Jul 2021 15:38:19 +1000
|
||||
Subject: [PATCH 15/32] video/readers/jpeg: Block int underflow -> wild pointer
|
||||
write
|
||||
|
||||
Certain 1 px wide images caused a wild pointer write in
|
||||
grub_jpeg_ycrcb_to_rgb(). This was caused because in grub_jpeg_decode_data(),
|
||||
we have the following loop:
|
||||
|
||||
for (; data->r1 < nr1 && (!data->dri || rst);
|
||||
data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
|
||||
|
||||
We did not check if vb * width >= hb * nc1.
|
||||
|
||||
On a 64-bit platform, if that turns out to be negative, it will underflow,
|
||||
be interpreted as unsigned 64-bit, then be added to the 64-bit pointer, so
|
||||
we see data->bitmap_ptr jump, e.g.:
|
||||
|
||||
0x6180_0000_0480 to
|
||||
0x6181_0000_0498
|
||||
^
|
||||
~--- carry has occurred and this pointer is now far away from
|
||||
any object.
|
||||
|
||||
On a 32-bit platform, it will decrement the pointer, creating a pointer
|
||||
that won't crash but will overwrite random data.
|
||||
|
||||
Catch the underflow and error out.
|
||||
|
||||
Fixes: CVE-2021-3697
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/video/readers/jpeg.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/video/readers/jpeg.c b/grub-core/video/readers/jpeg.c
|
||||
index 1df1171d78..97a533b24f 100644
|
||||
--- a/grub-core/video/readers/jpeg.c
|
||||
+++ b/grub-core/video/readers/jpeg.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include <grub/mm.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/bufio.h>
|
||||
+#include <grub/safemath.h>
|
||||
|
||||
GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
@@ -693,6 +694,7 @@ static grub_err_t
|
||||
grub_jpeg_decode_data (struct grub_jpeg_data *data)
|
||||
{
|
||||
unsigned c1, vb, hb, nr1, nc1;
|
||||
+ unsigned stride_a, stride_b, stride;
|
||||
int rst = data->dri;
|
||||
grub_err_t err = GRUB_ERR_NONE;
|
||||
|
||||
@@ -705,8 +707,14 @@ grub_jpeg_decode_data (struct grub_jpeg_data *data)
|
||||
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
"jpeg: attempted to decode data before start of stream");
|
||||
|
||||
+ if (grub_mul(vb, data->image_width, &stride_a) ||
|
||||
+ grub_mul(hb, nc1, &stride_b) ||
|
||||
+ grub_sub(stride_a, stride_b, &stride))
|
||||
+ return grub_error (GRUB_ERR_BAD_FILE_TYPE,
|
||||
+ "jpeg: cannot decode image with these dimensions");
|
||||
+
|
||||
for (; data->r1 < nr1 && (!data->dri || rst);
|
||||
- data->r1++, data->bitmap_ptr += (vb * data->image_width - hb * nc1) * 3)
|
||||
+ data->r1++, data->bitmap_ptr += stride * 3)
|
||||
for (c1 = 0; c1 < nc1 && (!data->dri || rst);
|
||||
c1++, rst--, data->bitmap_ptr += hb * 3)
|
||||
{
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,36 @@
|
||||
From cfe96e5c432b58726047f4d94f106f58855db1e2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 13 Jul 2021 13:24:38 +1000
|
||||
Subject: [PATCH 16/32] normal/charset: Fix array out-of-bounds formatting
|
||||
unicode for display
|
||||
|
||||
In some cases attempting to display arbitrary binary strings leads
|
||||
to ASAN splats reading the widthspec array out of bounds.
|
||||
|
||||
Check the index. If it would be out of bounds, return a width of 1.
|
||||
I don't know if that's strictly correct, but we're not really expecting
|
||||
great display of arbitrary binary data, and it's certainly not worse than
|
||||
an OOB read.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/normal/charset.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c
|
||||
index 4dfcc31078..7a5a7c153c 100644
|
||||
--- a/grub-core/normal/charset.c
|
||||
+++ b/grub-core/normal/charset.c
|
||||
@@ -395,6 +395,8 @@ grub_unicode_estimate_width (const struct grub_unicode_glyph *c)
|
||||
{
|
||||
if (grub_unicode_get_comb_type (c->base))
|
||||
return 0;
|
||||
+ if (((unsigned long) (c->base >> 3)) >= ARRAY_SIZE (widthspec))
|
||||
+ return 1;
|
||||
if (widthspec[c->base >> 3] & (1 << (c->base & 7)))
|
||||
return 2;
|
||||
else
|
||||
--
|
||||
2.34.1
|
||||
|
54
0017-net-ip-Do-IP-fragment-maths-safely.patch
Normal file
54
0017-net-ip-Do-IP-fragment-maths-safely.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 5c79af15504c599b58a2f3e591850876dfdb5fa2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Mon, 20 Dec 2021 19:41:21 +1100
|
||||
Subject: [PATCH 17/32] net/ip: Do IP fragment maths safely
|
||||
|
||||
We can receive packets with invalid IP fragmentation information. This
|
||||
can lead to rsm->total_len underflowing and becoming very large.
|
||||
|
||||
Then, in grub_netbuff_alloc(), we add to this very large number, which can
|
||||
cause it to overflow and wrap back around to a small positive number.
|
||||
The allocation then succeeds, but the resulting buffer is too small and
|
||||
subsequent operations can write past the end of the buffer.
|
||||
|
||||
Catch the underflow here.
|
||||
|
||||
Fixes: CVE-2022-28733
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/ip.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/net/ip.c b/grub-core/net/ip.c
|
||||
index 01410798b3..937be87678 100644
|
||||
--- a/grub-core/net/ip.c
|
||||
+++ b/grub-core/net/ip.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <grub/net/netbuff.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/priority_queue.h>
|
||||
+#include <grub/safemath.h>
|
||||
#include <grub/time.h>
|
||||
|
||||
struct iphdr {
|
||||
@@ -551,7 +552,14 @@ grub_net_recv_ip4_packets (struct grub_net_buff *nb,
|
||||
{
|
||||
rsm->total_len = (8 * (grub_be_to_cpu16 (iph->frags) & OFFSET_MASK)
|
||||
+ (nb->tail - nb->data));
|
||||
- rsm->total_len -= ((iph->verhdrlen & 0xf) * sizeof (grub_uint32_t));
|
||||
+
|
||||
+ if (grub_sub (rsm->total_len, (iph->verhdrlen & 0xf) * sizeof (grub_uint32_t),
|
||||
+ &rsm->total_len))
|
||||
+ {
|
||||
+ grub_dprintf ("net", "IP reassembly size underflow\n");
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ }
|
||||
+
|
||||
rsm->asm_netbuff = grub_netbuff_alloc (rsm->total_len);
|
||||
if (!rsm->asm_netbuff)
|
||||
{
|
||||
--
|
||||
2.34.1
|
||||
|
55
0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
Normal file
55
0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
Normal file
@ -0,0 +1,55 @@
|
||||
From bf949ed28a526b7ab137b8804e2ef6239c3061f2 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 8 Mar 2022 23:47:46 +1100
|
||||
Subject: [PATCH 18/32] net/netbuff: Block overly large netbuff allocs
|
||||
|
||||
A netbuff shouldn't be too huge. It's bounded by MTU and TCP segment
|
||||
reassembly. If we are asked to create one that is unreasonably big, refuse.
|
||||
|
||||
This is a hardening measure: if we hit this code, there's a bug somewhere
|
||||
else that we should catch and fix.
|
||||
|
||||
This commit:
|
||||
- stops the bug propagating any further.
|
||||
- provides a spot to instrument in e.g. fuzzing to try to catch these bugs.
|
||||
|
||||
I have put instrumentation (e.g. __builtin_trap() to force a crash) here and
|
||||
have not been able to find any more crashes.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/netbuff.c | 13 +++++++++++++
|
||||
1 file changed, 13 insertions(+)
|
||||
|
||||
diff --git a/grub-core/net/netbuff.c b/grub-core/net/netbuff.c
|
||||
index dbeeefe478..d5e9e9a0d7 100644
|
||||
--- a/grub-core/net/netbuff.c
|
||||
+++ b/grub-core/net/netbuff.c
|
||||
@@ -79,10 +79,23 @@ grub_netbuff_alloc (grub_size_t len)
|
||||
|
||||
COMPILE_TIME_ASSERT (NETBUFF_ALIGN % sizeof (grub_properly_aligned_t) == 0);
|
||||
|
||||
+ /*
|
||||
+ * The largest size of a TCP packet is 64 KiB, and everything else
|
||||
+ * should be a lot smaller - most MTUs are 1500 or less. Cap data
|
||||
+ * size at 64 KiB + a buffer.
|
||||
+ */
|
||||
+ if (len > 0xffffUL + 0x1000UL)
|
||||
+ {
|
||||
+ grub_error (GRUB_ERR_BUG,
|
||||
+ "attempted to allocate a packet that is too big");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
if (len < NETBUFFMINLEN)
|
||||
len = NETBUFFMINLEN;
|
||||
|
||||
len = ALIGN_UP (len, NETBUFF_ALIGN);
|
||||
+
|
||||
#ifdef GRUB_MACHINE_EMU
|
||||
data = grub_malloc (len + sizeof (*nb));
|
||||
#else
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,59 @@
|
||||
From cc43d9a3d77069850f993fbc4ae47c941bf284b9 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Thu, 16 Sep 2021 01:29:54 +1000
|
||||
Subject: [PATCH 19/32] net/dns: Fix double-free addresses on corrupt DNS
|
||||
response
|
||||
|
||||
grub_net_dns_lookup() takes as inputs a pointer to an array of addresses
|
||||
("addresses") for the given name, and pointer to a number of addresses
|
||||
("naddresses"). grub_net_dns_lookup() is responsible for allocating
|
||||
"addresses", and the caller is responsible for freeing it if
|
||||
"naddresses" > 0.
|
||||
|
||||
The DNS recv_hook will sometimes set and free the addresses array,
|
||||
for example if the packet is too short:
|
||||
|
||||
if (ptr + 10 >= nb->tail)
|
||||
{
|
||||
if (!*data->naddresses)
|
||||
grub_free (*data->addresses);
|
||||
grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
Later on the nslookup command code unconditionally frees the "addresses"
|
||||
array. Normally this is fine: the array is either populated with valid
|
||||
data or is NULL. But in these sorts of error cases it is neither NULL
|
||||
nor valid and we get a double-free.
|
||||
|
||||
Only free "addresses" if "naddresses" > 0.
|
||||
|
||||
It looks like the other use of grub_net_dns_lookup() is not affected.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/dns.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
|
||||
index 906ec7d678..135faac035 100644
|
||||
--- a/grub-core/net/dns.c
|
||||
+++ b/grub-core/net/dns.c
|
||||
@@ -667,9 +667,11 @@ grub_cmd_nslookup (struct grub_command *cmd __attribute__ ((unused)),
|
||||
grub_net_addr_to_str (&addresses[i], buf);
|
||||
grub_printf ("%s\n", buf);
|
||||
}
|
||||
- grub_free (addresses);
|
||||
if (naddresses)
|
||||
- return GRUB_ERR_NONE;
|
||||
+ {
|
||||
+ grub_free (addresses);
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ }
|
||||
return grub_error (GRUB_ERR_NET_NO_DOMAIN, N_("no DNS record found"));
|
||||
}
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,73 @@
|
||||
From e33af61c202972c81aaccdd395d61855e1584f66 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Mon, 20 Dec 2021 21:55:43 +1100
|
||||
Subject: [PATCH 20/32] net/dns: Don't read past the end of the string we're
|
||||
checking against
|
||||
|
||||
I don't really understand what's going on here but fuzzing found
|
||||
a bug where we read past the end of check_with. That's a C string,
|
||||
so use grub_strlen() to make sure we don't overread it.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/dns.c | 19 ++++++++++++++++---
|
||||
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/dns.c b/grub-core/net/dns.c
|
||||
index 135faac035..17961a9f18 100644
|
||||
--- a/grub-core/net/dns.c
|
||||
+++ b/grub-core/net/dns.c
|
||||
@@ -146,11 +146,18 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
|
||||
int *length, char *set)
|
||||
{
|
||||
const char *readable_ptr = check_with;
|
||||
+ int readable_len;
|
||||
const grub_uint8_t *ptr;
|
||||
char *optr = set;
|
||||
int bytes_processed = 0;
|
||||
if (length)
|
||||
*length = 0;
|
||||
+
|
||||
+ if (readable_ptr != NULL)
|
||||
+ readable_len = grub_strlen (readable_ptr);
|
||||
+ else
|
||||
+ readable_len = 0;
|
||||
+
|
||||
for (ptr = name_at; ptr < tail && bytes_processed < tail - head + 2; )
|
||||
{
|
||||
/* End marker. */
|
||||
@@ -172,13 +179,16 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
|
||||
ptr = head + (((ptr[0] & 0x3f) << 8) | ptr[1]);
|
||||
continue;
|
||||
}
|
||||
- if (readable_ptr && grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0)
|
||||
+ if (readable_ptr != NULL && (*ptr > readable_len || grub_memcmp (ptr + 1, readable_ptr, *ptr) != 0))
|
||||
return 0;
|
||||
if (grub_memchr (ptr + 1, 0, *ptr)
|
||||
|| grub_memchr (ptr + 1, '.', *ptr))
|
||||
return 0;
|
||||
if (readable_ptr)
|
||||
- readable_ptr += *ptr;
|
||||
+ {
|
||||
+ readable_ptr += *ptr;
|
||||
+ readable_len -= *ptr;
|
||||
+ }
|
||||
if (readable_ptr && *readable_ptr != '.' && *readable_ptr != 0)
|
||||
return 0;
|
||||
bytes_processed += *ptr + 1;
|
||||
@@ -192,7 +202,10 @@ check_name_real (const grub_uint8_t *name_at, const grub_uint8_t *head,
|
||||
if (optr)
|
||||
*optr++ = '.';
|
||||
if (readable_ptr && *readable_ptr)
|
||||
- readable_ptr++;
|
||||
+ {
|
||||
+ readable_ptr++;
|
||||
+ readable_len--;
|
||||
+ }
|
||||
ptr += *ptr + 1;
|
||||
}
|
||||
return 0;
|
||||
--
|
||||
2.34.1
|
||||
|
115
0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
Normal file
115
0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
Normal file
@ -0,0 +1,115 @@
|
||||
From 4adbb12d15af04f8f279a6290cd0195e57cc9e69 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Mon, 20 Sep 2021 01:12:24 +1000
|
||||
Subject: [PATCH 21/32] net/tftp: Prevent a UAF and double-free from a failed
|
||||
seek
|
||||
|
||||
A malicious tftp server can cause UAFs and a double free.
|
||||
|
||||
An attempt to read from a network file is handled by grub_net_fs_read(). If
|
||||
the read is at an offset other than the current offset, grub_net_seek_real()
|
||||
is invoked.
|
||||
|
||||
In grub_net_seek_real(), if a backwards seek cannot be satisfied from the
|
||||
currently received packets, and the underlying transport does not provide
|
||||
a seek method, then grub_net_seek_real() will close and reopen the network
|
||||
protocol layer.
|
||||
|
||||
For tftp, the ->close() call goes to tftp_close() and frees the tftp_data_t
|
||||
file->data. The file->data pointer is not nulled out after the free.
|
||||
|
||||
If the ->open() call fails, the file->data will not be reallocated and will
|
||||
continue point to a freed memory block. This could happen from a server
|
||||
refusing to send the requisite ack to the new tftp request, for example.
|
||||
|
||||
The seek and the read will then fail, but the grub_file continues to exist:
|
||||
the failed seek does not necessarily cause the entire file to be thrown
|
||||
away (e.g. where the file is checked to see if it is gzipped/lzio/xz/etc.,
|
||||
a read failure is interpreted as a decompressor passing on the file, not as
|
||||
an invalidation of the entire grub_file_t structure).
|
||||
|
||||
This means subsequent attempts to read or seek the file will use the old
|
||||
file->data after free. Eventually, the file will be close()d again and
|
||||
file->data will be freed again.
|
||||
|
||||
Mark a net_fs file that doesn't reopen as broken. Do not permit read() or
|
||||
close() on a broken file (seek is not exposed directly to the file API -
|
||||
it is only called as part of read, so this blocks seeks as well).
|
||||
|
||||
As an additional defence, null out the ->data pointer if tftp_open() fails.
|
||||
That would have lead to a simple null pointer dereference rather than
|
||||
a mess of UAFs.
|
||||
|
||||
This may affect other protocols, I haven't checked.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/net.c | 11 +++++++++--
|
||||
grub-core/net/tftp.c | 1 +
|
||||
include/grub/net.h | 1 +
|
||||
3 files changed, 11 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/net.c b/grub-core/net/net.c
|
||||
index d11672fbee..b8238b7df1 100644
|
||||
--- a/grub-core/net/net.c
|
||||
+++ b/grub-core/net/net.c
|
||||
@@ -1546,7 +1546,8 @@ grub_net_fs_close (grub_file_t file)
|
||||
grub_netbuff_free (file->device->net->packs.first->nb);
|
||||
grub_net_remove_packet (file->device->net->packs.first);
|
||||
}
|
||||
- file->device->net->protocol->close (file);
|
||||
+ if (!file->device->net->broken)
|
||||
+ file->device->net->protocol->close (file);
|
||||
grub_free (file->device->net->name);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -1768,7 +1769,10 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
||||
file->device->net->stall = 0;
|
||||
err = file->device->net->protocol->open (file, file->device->net->name);
|
||||
if (err)
|
||||
- return err;
|
||||
+ {
|
||||
+ file->device->net->broken = 1;
|
||||
+ return err;
|
||||
+ }
|
||||
grub_net_fs_read_real (file, NULL, offset);
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -1777,6 +1781,9 @@ grub_net_seek_real (struct grub_file *file, grub_off_t offset)
|
||||
static grub_ssize_t
|
||||
grub_net_fs_read (grub_file_t file, char *buf, grub_size_t len)
|
||||
{
|
||||
+ if (file->device->net->broken)
|
||||
+ return -1;
|
||||
+
|
||||
if (file->offset != file->device->net->offset)
|
||||
{
|
||||
grub_err_t err;
|
||||
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
||||
index f3e7879388..d1afa25352 100644
|
||||
--- a/grub-core/net/tftp.c
|
||||
+++ b/grub-core/net/tftp.c
|
||||
@@ -404,6 +404,7 @@ tftp_open (struct grub_file *file, const char *filename)
|
||||
{
|
||||
grub_net_udp_close (data->sock);
|
||||
grub_free (data);
|
||||
+ file->data = NULL;
|
||||
return grub_errno;
|
||||
}
|
||||
|
||||
diff --git a/include/grub/net.h b/include/grub/net.h
|
||||
index cbcae79b1f..8d71ca6cc5 100644
|
||||
--- a/include/grub/net.h
|
||||
+++ b/include/grub/net.h
|
||||
@@ -277,6 +277,7 @@ typedef struct grub_net
|
||||
grub_fs_t fs;
|
||||
int eof;
|
||||
int stall;
|
||||
+ int broken;
|
||||
} *grub_net_t;
|
||||
|
||||
extern grub_net_t (*EXPORT_VAR (grub_net_open)) (const char *name);
|
||||
--
|
||||
2.34.1
|
||||
|
37
0022-net-tftp-Avoid-a-trivial-UAF.patch
Normal file
37
0022-net-tftp-Avoid-a-trivial-UAF.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 1824df76e0e712917edce83b5be57d485b81a5a7 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 18 Jan 2022 14:29:20 +1100
|
||||
Subject: [PATCH 22/32] net/tftp: Avoid a trivial UAF
|
||||
|
||||
Under tftp errors, we print a tftp error message from the tftp header.
|
||||
However, the tftph pointer is a pointer inside nb, the netbuff. Previously,
|
||||
we were freeing the nb and then dereferencing it. Don't do that, use it
|
||||
and then free it later.
|
||||
|
||||
This isn't really _bad_ per se, especially as we're single-threaded, but
|
||||
it trips up fuzzers.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/tftp.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/grub-core/net/tftp.c b/grub-core/net/tftp.c
|
||||
index d1afa25352..4222d93b6d 100644
|
||||
--- a/grub-core/net/tftp.c
|
||||
+++ b/grub-core/net/tftp.c
|
||||
@@ -251,9 +251,9 @@ tftp_receive (grub_net_udp_socket_t sock __attribute__ ((unused)),
|
||||
return GRUB_ERR_NONE;
|
||||
case TFTP_ERROR:
|
||||
data->have_oack = 1;
|
||||
- grub_netbuff_free (nb);
|
||||
grub_error (GRUB_ERR_IO, "%s", tftph->u.err.errmsg);
|
||||
grub_error_save (&data->save_err);
|
||||
+ grub_netbuff_free (nb);
|
||||
return GRUB_ERR_NONE;
|
||||
default:
|
||||
grub_netbuff_free (nb);
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,44 @@
|
||||
From 7ec48289eeae517e14e2c957a90fd95a49741894 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 1 Mar 2022 23:14:15 +1100
|
||||
Subject: [PATCH 23/32] net/http: Do not tear down socket if it's already been
|
||||
torn down
|
||||
|
||||
It's possible for data->sock to get torn down in tcp error handling.
|
||||
If we unconditionally tear it down again we will end up doing writes
|
||||
to an offset of the NULL pointer when we go to tear it down again.
|
||||
|
||||
Detect if it has been torn down and don't do it again.
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/http.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
|
||||
index bf838660d9..a77bc4e4b8 100644
|
||||
--- a/grub-core/net/http.c
|
||||
+++ b/grub-core/net/http.c
|
||||
@@ -425,7 +425,7 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
||||
return err;
|
||||
}
|
||||
|
||||
- for (i = 0; !data->headers_recv && i < 100; i++)
|
||||
+ for (i = 0; data->sock && !data->headers_recv && i < 100; i++)
|
||||
{
|
||||
grub_net_tcp_retransmit ();
|
||||
grub_net_poll_cards (300, &data->headers_recv);
|
||||
@@ -433,7 +433,8 @@ http_establish (struct grub_file *file, grub_off_t offset, int initial)
|
||||
|
||||
if (!data->headers_recv)
|
||||
{
|
||||
- grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||
+ if (data->sock)
|
||||
+ grub_net_tcp_close (data->sock, GRUB_NET_TCP_ABORT);
|
||||
if (data->err)
|
||||
{
|
||||
char *str = data->errmsg;
|
||||
--
|
||||
2.34.1
|
||||
|
48
0024-net-http-Fix-OOB-write-for-split-http-headers.patch
Normal file
48
0024-net-http-Fix-OOB-write-for-split-http-headers.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From d7374ab1a110a7ddcfa5a0eda9574ebef2220ee1 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 8 Mar 2022 18:17:03 +1100
|
||||
Subject: [PATCH 24/32] net/http: Fix OOB write for split http headers
|
||||
|
||||
GRUB has special code for handling an http header that is split
|
||||
across two packets.
|
||||
|
||||
The code tracks the end of line by looking for a "\n" byte. The
|
||||
code for split headers has always advanced the pointer just past the
|
||||
end of the line, whereas the code that handles unsplit headers does
|
||||
not advance the pointer. This extra advance causes the length to be
|
||||
one greater, which breaks an assumption in parse_line(), leading to
|
||||
it writing a NUL byte one byte past the end of the buffer where we
|
||||
reconstruct the line from the two packets.
|
||||
|
||||
It's conceivable that an attacker controlled set of packets could
|
||||
cause this to zero out the first byte of the "next" pointer of the
|
||||
grub_mm_region structure following the current_line buffer.
|
||||
|
||||
Do not advance the pointer in the split header case.
|
||||
|
||||
Fixes: CVE-2022-28734
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/http.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
|
||||
index a77bc4e4b8..d9d2ade98e 100644
|
||||
--- a/grub-core/net/http.c
|
||||
+++ b/grub-core/net/http.c
|
||||
@@ -193,9 +193,7 @@ http_receive (grub_net_tcp_socket_t sock __attribute__ ((unused)),
|
||||
int have_line = 1;
|
||||
char *t;
|
||||
ptr = grub_memchr (nb->data, '\n', nb->tail - nb->data);
|
||||
- if (ptr)
|
||||
- ptr++;
|
||||
- else
|
||||
+ if (ptr == NULL)
|
||||
{
|
||||
have_line = 0;
|
||||
ptr = (char *) nb->tail;
|
||||
--
|
||||
2.34.1
|
||||
|
50
0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
Normal file
50
0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 5a6ca6483123f2290696e7268f875ff72dd841b6 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Axtens <dja@axtens.net>
|
||||
Date: Tue, 8 Mar 2022 19:04:40 +1100
|
||||
Subject: [PATCH 25/32] net/http: Error out on headers with LF without CR
|
||||
|
||||
In a similar vein to the previous patch, parse_line() would write
|
||||
a NUL byte past the end of the buffer if there was an HTTP header
|
||||
with a LF rather than a CRLF.
|
||||
|
||||
RFC-2616 says:
|
||||
|
||||
Many HTTP/1.1 header field values consist of words separated by LWS
|
||||
or special characters. These special characters MUST be in a quoted
|
||||
string to be used within a parameter value (as defined in section 3.6).
|
||||
|
||||
We don't support quoted sections or continuation lines, etc.
|
||||
|
||||
If we see an LF that's not part of a CRLF, bail out.
|
||||
|
||||
Fixes: CVE-2022-28734
|
||||
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/net/http.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/grub-core/net/http.c b/grub-core/net/http.c
|
||||
index d9d2ade98e..0472645d12 100644
|
||||
--- a/grub-core/net/http.c
|
||||
+++ b/grub-core/net/http.c
|
||||
@@ -69,7 +69,15 @@ parse_line (grub_file_t file, http_data_t data, char *ptr, grub_size_t len)
|
||||
char *end = ptr + len;
|
||||
while (end > ptr && *(end - 1) == '\r')
|
||||
end--;
|
||||
+
|
||||
+ /* LF without CR. */
|
||||
+ if (end == ptr + len)
|
||||
+ {
|
||||
+ data->errmsg = grub_strdup (_("invalid HTTP header - LF without CR"));
|
||||
+ return GRUB_ERR_NONE;
|
||||
+ }
|
||||
*end = 0;
|
||||
+
|
||||
/* Trailing CRLF. */
|
||||
if (data->in_chunk_len == 1)
|
||||
{
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,75 @@
|
||||
From c1013c295f1e32620db302470f126df0c6a0d5a5 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Wed, 6 Apr 2022 18:03:37 +0530
|
||||
Subject: [PATCH 26/32] fs/f2fs: Do not read past the end of nat journal
|
||||
entries
|
||||
|
||||
A corrupt f2fs file system could specify a nat journal entry count
|
||||
that is beyond the maximum NAT_JOURNAL_ENTRIES.
|
||||
|
||||
Check if the specified nat journal entry count before accessing the
|
||||
array, and throw an error if it is too large.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/f2fs.c | 21 ++++++++++++++-------
|
||||
1 file changed, 14 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
|
||||
index 8a9992ca9e..63702214b0 100644
|
||||
--- a/grub-core/fs/f2fs.c
|
||||
+++ b/grub-core/fs/f2fs.c
|
||||
@@ -632,23 +632,27 @@ get_nat_journal (struct grub_f2fs_data *data)
|
||||
return err;
|
||||
}
|
||||
|
||||
-static grub_uint32_t
|
||||
-get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid)
|
||||
+static grub_err_t
|
||||
+get_blkaddr_from_nat_journal (struct grub_f2fs_data *data, grub_uint32_t nid,
|
||||
+ grub_uint32_t *blkaddr)
|
||||
{
|
||||
grub_uint16_t n = grub_le_to_cpu16 (data->nat_j.n_nats);
|
||||
- grub_uint32_t blkaddr = 0;
|
||||
grub_uint16_t i;
|
||||
|
||||
+ if (n >= NAT_JOURNAL_ENTRIES)
|
||||
+ return grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "invalid number of nat journal entries");
|
||||
+
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (grub_le_to_cpu32 (data->nat_j.entries[i].nid) == nid)
|
||||
{
|
||||
- blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
|
||||
+ *blkaddr = grub_le_to_cpu32 (data->nat_j.entries[i].ne.block_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- return blkaddr;
|
||||
+ return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_uint32_t
|
||||
@@ -656,10 +660,13 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
|
||||
{
|
||||
struct grub_f2fs_nat_block *nat_block;
|
||||
grub_uint32_t seg_off, block_off, entry_off, block_addr;
|
||||
- grub_uint32_t blkaddr;
|
||||
+ grub_uint32_t blkaddr = 0;
|
||||
grub_err_t err;
|
||||
|
||||
- blkaddr = get_blkaddr_from_nat_journal (data, nid);
|
||||
+ err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
|
||||
+ if (err != GRUB_ERR_NONE)
|
||||
+ return 0;
|
||||
+
|
||||
if (blkaddr)
|
||||
return blkaddr;
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
134
0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
Normal file
134
0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
Normal file
@ -0,0 +1,134 @@
|
||||
From 5ac885d02a9e91a5d6760090f90fa2bb4e7a5dd6 Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Wed, 6 Apr 2022 18:49:09 +0530
|
||||
Subject: [PATCH 27/32] fs/f2fs: Do not read past the end of nat bitmap
|
||||
|
||||
A corrupt f2fs filesystem could have a block offset or a bitmap
|
||||
offset that would cause us to read beyond the bounds of the nat
|
||||
bitmap.
|
||||
|
||||
Introduce the nat_bitmap_size member in grub_f2fs_data which holds
|
||||
the size of nat bitmap.
|
||||
|
||||
Set the size when loading the nat bitmap in nat_bitmap_ptr(), and
|
||||
catch when an invalid offset would create a pointer past the end of
|
||||
the allocated space.
|
||||
|
||||
Check against the bitmap size in grub_f2fs_test_bit() test bit to avoid
|
||||
reading past the end of the nat bitmap.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/f2fs.c | 33 +++++++++++++++++++++++++++------
|
||||
1 file changed, 27 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
|
||||
index 63702214b0..8898b235e0 100644
|
||||
--- a/grub-core/fs/f2fs.c
|
||||
+++ b/grub-core/fs/f2fs.c
|
||||
@@ -122,6 +122,7 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
#define F2FS_INLINE_DOTS 0x10 /* File having implicit dot dentries. */
|
||||
|
||||
#define MAX_VOLUME_NAME 512
|
||||
+#define MAX_NAT_BITMAP_SIZE 3900
|
||||
|
||||
enum FILE_TYPE
|
||||
{
|
||||
@@ -183,7 +184,7 @@ struct grub_f2fs_checkpoint
|
||||
grub_uint32_t checksum_offset;
|
||||
grub_uint64_t elapsed_time;
|
||||
grub_uint8_t alloc_type[MAX_ACTIVE_LOGS];
|
||||
- grub_uint8_t sit_nat_version_bitmap[3900];
|
||||
+ grub_uint8_t sit_nat_version_bitmap[MAX_NAT_BITMAP_SIZE];
|
||||
grub_uint32_t checksum;
|
||||
} GRUB_PACKED;
|
||||
|
||||
@@ -302,6 +303,7 @@ struct grub_f2fs_data
|
||||
|
||||
struct grub_f2fs_nat_journal nat_j;
|
||||
char *nat_bitmap;
|
||||
+ grub_uint32_t nat_bitmap_size;
|
||||
|
||||
grub_disk_t disk;
|
||||
struct grub_f2fs_node *inode;
|
||||
@@ -377,15 +379,20 @@ sum_blk_addr (struct grub_f2fs_data *data, int base, int type)
|
||||
}
|
||||
|
||||
static void *
|
||||
-nat_bitmap_ptr (struct grub_f2fs_data *data)
|
||||
+nat_bitmap_ptr (struct grub_f2fs_data *data, grub_uint32_t *nat_bitmap_size)
|
||||
{
|
||||
struct grub_f2fs_checkpoint *ckpt = &data->ckpt;
|
||||
grub_uint32_t offset;
|
||||
+ *nat_bitmap_size = MAX_NAT_BITMAP_SIZE;
|
||||
|
||||
if (grub_le_to_cpu32 (data->sblock.cp_payload) > 0)
|
||||
return ckpt->sit_nat_version_bitmap;
|
||||
|
||||
offset = grub_le_to_cpu32 (ckpt->sit_ver_bitmap_bytesize);
|
||||
+ if (offset >= MAX_NAT_BITMAP_SIZE)
|
||||
+ return NULL;
|
||||
+
|
||||
+ *nat_bitmap_size = *nat_bitmap_size - offset;
|
||||
|
||||
return ckpt->sit_nat_version_bitmap + offset;
|
||||
}
|
||||
@@ -438,11 +445,15 @@ grub_f2fs_crc_valid (grub_uint32_t blk_crc, void *buf, const grub_uint32_t len)
|
||||
}
|
||||
|
||||
static int
|
||||
-grub_f2fs_test_bit (grub_uint32_t nr, const char *p)
|
||||
+grub_f2fs_test_bit (grub_uint32_t nr, const char *p, grub_uint32_t len)
|
||||
{
|
||||
int mask;
|
||||
+ grub_uint32_t shifted_nr = (nr >> 3);
|
||||
+
|
||||
+ if (shifted_nr >= len)
|
||||
+ return -1;
|
||||
|
||||
- p += (nr >> 3);
|
||||
+ p += shifted_nr;
|
||||
mask = 1 << (7 - (nr & 0x07));
|
||||
|
||||
return mask & *p;
|
||||
@@ -662,6 +673,7 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
|
||||
grub_uint32_t seg_off, block_off, entry_off, block_addr;
|
||||
grub_uint32_t blkaddr = 0;
|
||||
grub_err_t err;
|
||||
+ int result_bit;
|
||||
|
||||
err = get_blkaddr_from_nat_journal (data, nid, &blkaddr);
|
||||
if (err != GRUB_ERR_NONE)
|
||||
@@ -682,8 +694,15 @@ get_node_blkaddr (struct grub_f2fs_data *data, grub_uint32_t nid)
|
||||
((seg_off * data->blocks_per_seg) << 1) +
|
||||
(block_off & (data->blocks_per_seg - 1));
|
||||
|
||||
- if (grub_f2fs_test_bit (block_off, data->nat_bitmap))
|
||||
+ result_bit = grub_f2fs_test_bit (block_off, data->nat_bitmap,
|
||||
+ data->nat_bitmap_size);
|
||||
+ if (result_bit > 0)
|
||||
block_addr += data->blocks_per_seg;
|
||||
+ else if (result_bit == -1)
|
||||
+ {
|
||||
+ grub_free (nat_block);
|
||||
+ return 0;
|
||||
+ }
|
||||
|
||||
err = grub_f2fs_block_read (data, block_addr, nat_block);
|
||||
if (err)
|
||||
@@ -833,7 +852,9 @@ grub_f2fs_mount (grub_disk_t disk)
|
||||
if (err)
|
||||
goto fail;
|
||||
|
||||
- data->nat_bitmap = nat_bitmap_ptr (data);
|
||||
+ data->nat_bitmap = nat_bitmap_ptr (data, &data->nat_bitmap_size);
|
||||
+ if (data->nat_bitmap == NULL)
|
||||
+ goto fail;
|
||||
|
||||
err = get_nat_journal (data);
|
||||
if (err)
|
||||
--
|
||||
2.34.1
|
||||
|
40
0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
Normal file
40
0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
Normal file
@ -0,0 +1,40 @@
|
||||
From 315e2773ed5cae92548d4508301ac0fe7515e5bb Mon Sep 17 00:00:00 2001
|
||||
From: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Date: Wed, 6 Apr 2022 18:17:43 +0530
|
||||
Subject: [PATCH 28/32] fs/f2fs: Do not copy file names that are too long
|
||||
|
||||
A corrupt f2fs file system might specify a name length which is greater
|
||||
than the maximum name length supported by the GRUB f2fs driver.
|
||||
|
||||
We will allocate enough memory to store the overly long name, but there
|
||||
are only F2FS_NAME_LEN bytes in the source, so we would read past the end
|
||||
of the source.
|
||||
|
||||
While checking directory entries, do not copy a file name with an invalid
|
||||
length.
|
||||
|
||||
Signed-off-by: Sudhakar Kuppusamy <sudhakar@linux.ibm.com>
|
||||
Signed-off-by: Daniel Axtens <dja@axtens.net>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/f2fs.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/f2fs.c b/grub-core/fs/f2fs.c
|
||||
index 8898b235e0..df6beb544c 100644
|
||||
--- a/grub-core/fs/f2fs.c
|
||||
+++ b/grub-core/fs/f2fs.c
|
||||
@@ -1003,6 +1003,10 @@ grub_f2fs_check_dentries (struct grub_f2fs_dir_iter_ctx *ctx)
|
||||
|
||||
ftype = ctx->dentry[i].file_type;
|
||||
name_len = grub_le_to_cpu16 (ctx->dentry[i].name_len);
|
||||
+
|
||||
+ if (name_len >= F2FS_NAME_LEN)
|
||||
+ return 0;
|
||||
+
|
||||
filename = grub_malloc (name_len + 1);
|
||||
if (!filename)
|
||||
return 0;
|
||||
--
|
||||
2.34.1
|
||||
|
@ -0,0 +1,79 @@
|
||||
From c64e0158654a1098caf652f6ffd192cbe26583f3 Mon Sep 17 00:00:00 2001
|
||||
From: Darren Kenny <darren.kenny@oracle.com>
|
||||
Date: Tue, 29 Mar 2022 10:49:56 +0000
|
||||
Subject: [PATCH 29/32] fs/btrfs: Fix several fuzz issues with invalid dir item
|
||||
sizing
|
||||
|
||||
According to the btrfs code in Linux, the structure of a directory item
|
||||
leaf should be of the form:
|
||||
|
||||
|struct btrfs_dir_item|name|data|
|
||||
|
||||
in GRUB the name len and data len are in the grub_btrfs_dir_item
|
||||
structure's n and m fields respectively.
|
||||
|
||||
The combined size of the structure, name and data should be less than
|
||||
the allocated memory, a difference to the Linux kernel's struct
|
||||
btrfs_dir_item is that the grub_btrfs_dir_item has an extra field for
|
||||
where the name is stored, so we adjust for that too.
|
||||
|
||||
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 26 ++++++++++++++++++++++++++
|
||||
1 file changed, 26 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 42fdbaf616..626fd2daa0 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -2210,6 +2210,7 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||
grub_uint64_t tree;
|
||||
grub_uint8_t type;
|
||||
char *new_path = NULL;
|
||||
+ grub_size_t est_size = 0;
|
||||
|
||||
if (!data)
|
||||
return grub_errno;
|
||||
@@ -2276,6 +2277,18 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (direl == NULL ||
|
||||
+ grub_add (grub_le_to_cpu16 (direl->n),
|
||||
+ grub_le_to_cpu16 (direl->m), &est_size) ||
|
||||
+ grub_add (est_size, sizeof (*direl), &est_size) ||
|
||||
+ grub_sub (est_size, sizeof (direl->name), &est_size) ||
|
||||
+ est_size > allocated)
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ r = -grub_errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
for (cdirel = direl;
|
||||
(grub_uint8_t *) cdirel - (grub_uint8_t *) direl
|
||||
< (grub_ssize_t) elemsize;
|
||||
@@ -2286,6 +2299,19 @@ grub_btrfs_dir (grub_device_t device, const char *path,
|
||||
char c;
|
||||
struct grub_btrfs_inode inode;
|
||||
struct grub_dirhook_info info;
|
||||
+
|
||||
+ if (cdirel == NULL ||
|
||||
+ grub_add (grub_le_to_cpu16 (cdirel->n),
|
||||
+ grub_le_to_cpu16 (cdirel->m), &est_size) ||
|
||||
+ grub_add (est_size, sizeof (*cdirel), &est_size) ||
|
||||
+ grub_sub (est_size, sizeof (cdirel->name), &est_size) ||
|
||||
+ est_size > allocated)
|
||||
+ {
|
||||
+ grub_errno = GRUB_ERR_OUT_OF_RANGE;
|
||||
+ r = -grub_errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
err = grub_btrfs_read_inode (data, &inode, cdirel->key.object_id,
|
||||
tree);
|
||||
grub_memset (&info, 0, sizeof (info));
|
||||
--
|
||||
2.34.1
|
||||
|
137
0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
Normal file
137
0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From 2576115cc77c45d2a77d7629b8c2f26a3a58822b Mon Sep 17 00:00:00 2001
|
||||
From: Darren Kenny <darren.kenny@oracle.com>
|
||||
Date: Tue, 29 Mar 2022 15:52:46 +0000
|
||||
Subject: [PATCH 30/32] fs/btrfs: Fix more ASAN and SEGV issues found with
|
||||
fuzzing
|
||||
|
||||
The fuzzer is generating btrfs file systems that have chunks with
|
||||
invalid combinations of stripes and substripes for the given RAID
|
||||
configurations.
|
||||
|
||||
After examining the Linux kernel fs/btrfs/tree-checker.c code, it
|
||||
appears that sub-stripes should only be applied to RAID10, and in that
|
||||
case there should only ever be 2 of them.
|
||||
|
||||
Similarly, RAID single should only have 1 stripe, and RAID1/1C3/1C4
|
||||
should have 2. 3 or 4 stripes respectively, which is what redundancy
|
||||
corresponds.
|
||||
|
||||
Some of the chunks ended up with a size of 0, which grub_malloc() still
|
||||
returned memory for and in turn generated ASAN errors later when
|
||||
accessed.
|
||||
|
||||
While it would be possible to specifically limit the number of stripes,
|
||||
a more correct test was on the combination of the chunk item, and the
|
||||
number of stripes by the size of the chunk stripe structure in
|
||||
comparison to the size of the chunk itself.
|
||||
|
||||
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 55 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 55 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 626fd2daa0..62fe5e6a69 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -938,6 +938,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
return grub_error (GRUB_ERR_BAD_FS,
|
||||
"couldn't find the chunk descriptor");
|
||||
|
||||
+ if (!chsize)
|
||||
+ {
|
||||
+ grub_dprintf ("btrfs", "zero-size chunk\n");
|
||||
+ return grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "got an invalid zero-size chunk");
|
||||
+ }
|
||||
chunk = grub_malloc (chsize);
|
||||
if (!chunk)
|
||||
return grub_errno;
|
||||
@@ -996,6 +1002,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
stripe_length = grub_divmod64 (grub_le_to_cpu64 (chunk->size),
|
||||
nstripes,
|
||||
NULL);
|
||||
+
|
||||
+ /* For single, there should be exactly 1 stripe. */
|
||||
+ if (grub_le_to_cpu16 (chunk->nstripes) != 1)
|
||||
+ {
|
||||
+ grub_dprintf ("btrfs", "invalid RAID_SINGLE: nstripes != 1 (%u)\n",
|
||||
+ grub_le_to_cpu16 (chunk->nstripes));
|
||||
+ return grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "invalid RAID_SINGLE: nstripes != 1 (%u)",
|
||||
+ grub_le_to_cpu16 (chunk->nstripes));
|
||||
+ }
|
||||
if (stripe_length == 0)
|
||||
stripe_length = 512;
|
||||
stripen = grub_divmod64 (off, stripe_length, &stripe_offset);
|
||||
@@ -1015,6 +1031,19 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
stripen = 0;
|
||||
stripe_offset = off;
|
||||
csize = grub_le_to_cpu64 (chunk->size) - off;
|
||||
+
|
||||
+ /*
|
||||
+ * Redundancy, and substripes only apply to RAID10, and there
|
||||
+ * should be exactly 2 sub-stripes.
|
||||
+ */
|
||||
+ if (grub_le_to_cpu16 (chunk->nstripes) != redundancy)
|
||||
+ {
|
||||
+ grub_dprintf ("btrfs", "invalid RAID1: nstripes != %u (%u)\n",
|
||||
+ redundancy, grub_le_to_cpu16 (chunk->nstripes));
|
||||
+ return grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "invalid RAID1: nstripes != %u (%u)",
|
||||
+ redundancy, grub_le_to_cpu16 (chunk->nstripes));
|
||||
+ }
|
||||
break;
|
||||
}
|
||||
case GRUB_BTRFS_CHUNK_TYPE_RAID0:
|
||||
@@ -1051,6 +1080,20 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
stripe_offset = low + chunk_stripe_length
|
||||
* high;
|
||||
csize = chunk_stripe_length - low;
|
||||
+
|
||||
+ /*
|
||||
+ * Substripes only apply to RAID10, and there
|
||||
+ * should be exactly 2 sub-stripes.
|
||||
+ */
|
||||
+ if (grub_le_to_cpu16 (chunk->nsubstripes) != 2)
|
||||
+ {
|
||||
+ grub_dprintf ("btrfs", "invalid RAID10: nsubstripes != 2 (%u)",
|
||||
+ grub_le_to_cpu16 (chunk->nsubstripes));
|
||||
+ return grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "invalid RAID10: nsubstripes != 2 (%u)",
|
||||
+ grub_le_to_cpu16 (chunk->nsubstripes));
|
||||
+ }
|
||||
+
|
||||
break;
|
||||
}
|
||||
case GRUB_BTRFS_CHUNK_TYPE_RAID5:
|
||||
@@ -1150,6 +1193,8 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
+ grub_size_t est_chunk_alloc = 0;
|
||||
+
|
||||
grub_dprintf ("btrfs", "chunk 0x%" PRIxGRUB_UINT64_T
|
||||
"+0x%" PRIxGRUB_UINT64_T
|
||||
" (%d stripes (%d substripes) of %"
|
||||
@@ -1162,6 +1207,16 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
grub_dprintf ("btrfs", "reading laddr 0x%" PRIxGRUB_UINT64_T "\n",
|
||||
addr);
|
||||
|
||||
+ if (grub_mul (sizeof (struct grub_btrfs_chunk_stripe),
|
||||
+ grub_le_to_cpu16 (chunk->nstripes), &est_chunk_alloc) ||
|
||||
+ grub_add (est_chunk_alloc,
|
||||
+ sizeof (struct grub_btrfs_chunk_item), &est_chunk_alloc) ||
|
||||
+ est_chunk_alloc > chunk->size)
|
||||
+ {
|
||||
+ err = GRUB_ERR_BAD_FS;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (is_raid56)
|
||||
{
|
||||
err = btrfs_read_from_chunk (data, chunk, stripen,
|
||||
--
|
||||
2.34.1
|
||||
|
78
0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
Normal file
78
0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 480019e546386b8e25a26d03408897a7752b98b6 Mon Sep 17 00:00:00 2001
|
||||
From: Darren Kenny <darren.kenny@oracle.com>
|
||||
Date: Thu, 7 Apr 2022 15:18:12 +0000
|
||||
Subject: [PATCH 31/32] fs/btrfs: Fix more fuzz issues related to chunks
|
||||
|
||||
The corpus was generating issues in grub_btrfs_read_logical() when
|
||||
attempting to iterate over stripe entries in the superblock's
|
||||
bootmapping.
|
||||
|
||||
In most cases the reason for the failure was that the number of stripes
|
||||
in chunk->nstripes exceeded the possible space statically allocated in
|
||||
superblock bootmapping space. Each stripe entry in the bootmapping block
|
||||
consists of a grub_btrfs_key followed by a grub_btrfs_chunk_stripe.
|
||||
|
||||
Another issue that came up was that while calculating the chunk size,
|
||||
in an earlier piece of code in that function, depending on the data
|
||||
provided in the btrfs file system, it would end up calculating a size
|
||||
that was too small to contain even 1 grub_btrfs_chunk_item, which is
|
||||
obviously invalid too.
|
||||
|
||||
Signed-off-by: Darren Kenny <darren.kenny@oracle.com>
|
||||
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
|
||||
---
|
||||
grub-core/fs/btrfs.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/grub-core/fs/btrfs.c b/grub-core/fs/btrfs.c
|
||||
index 62fe5e6a69..7007463c6e 100644
|
||||
--- a/grub-core/fs/btrfs.c
|
||||
+++ b/grub-core/fs/btrfs.c
|
||||
@@ -944,6 +944,17 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
return grub_error (GRUB_ERR_BAD_FS,
|
||||
"got an invalid zero-size chunk");
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * The space being allocated for a chunk should at least be able to
|
||||
+ * contain one chunk item.
|
||||
+ */
|
||||
+ if (chsize < sizeof (struct grub_btrfs_chunk_item))
|
||||
+ {
|
||||
+ grub_dprintf ("btrfs", "chunk-size too small\n");
|
||||
+ return grub_error (GRUB_ERR_BAD_FS,
|
||||
+ "got an invalid chunk size");
|
||||
+ }
|
||||
chunk = grub_malloc (chsize);
|
||||
if (!chunk)
|
||||
return grub_errno;
|
||||
@@ -1191,6 +1202,13 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
if (csize > (grub_uint64_t) size)
|
||||
csize = size;
|
||||
|
||||
+ /*
|
||||
+ * The space for a chunk stripe is limited to the space provide in the super-block's
|
||||
+ * bootstrap mapping with an initial btrfs key at the start of each chunk.
|
||||
+ */
|
||||
+ grub_size_t avail_stripes = sizeof (data->sblock.bootstrap_mapping) /
|
||||
+ (sizeof (struct grub_btrfs_key) + sizeof (struct grub_btrfs_chunk_stripe));
|
||||
+
|
||||
for (j = 0; j < 2; j++)
|
||||
{
|
||||
grub_size_t est_chunk_alloc = 0;
|
||||
@@ -1217,6 +1235,12 @@ grub_btrfs_read_logical (struct grub_btrfs_data *data, grub_disk_addr_t addr,
|
||||
break;
|
||||
}
|
||||
|
||||
+ if (grub_le_to_cpu16 (chunk->nstripes) > avail_stripes)
|
||||
+ {
|
||||
+ err = GRUB_ERR_BAD_FS;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
if (is_raid56)
|
||||
{
|
||||
err = btrfs_read_from_chunk (data, chunk, stripen,
|
||||
--
|
||||
2.34.1
|
||||
|
261
0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
Normal file
261
0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
Normal file
@ -0,0 +1,261 @@
|
||||
From 836337d9b895da32bcbc451c84bc3a7865a15963 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Chang <mchang@suse.com>
|
||||
Date: Mon, 18 Apr 2022 22:16:49 +0800
|
||||
Subject: [PATCH 32/32] Use grub_loader_set_ex() for secureboot chainloader
|
||||
|
||||
This is required as many distributions, including SUSE, has been
|
||||
shipping a variation to load and start image using native functions than
|
||||
calling out efi protocols when secure boot is enabled and shim lock is
|
||||
used to verify image.
|
||||
|
||||
Signed-off-by: Michael Chang <mchang@suse.com>
|
||||
---
|
||||
grub-core/loader/efi/chainloader.c | 100 +++++++++++++++++++----------
|
||||
1 file changed, 66 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/grub-core/loader/efi/chainloader.c b/grub-core/loader/efi/chainloader.c
|
||||
index b3e1e89302..48d69c7795 100644
|
||||
--- a/grub-core/loader/efi/chainloader.c
|
||||
+++ b/grub-core/loader/efi/chainloader.c
|
||||
@@ -53,10 +53,6 @@ GRUB_MOD_LICENSE ("GPLv3+");
|
||||
|
||||
static grub_dl_t my_mod;
|
||||
|
||||
-static grub_ssize_t fsize;
|
||||
-static grub_ssize_t cmdline_len;
|
||||
-static grub_efi_handle_t dev_handle;
|
||||
-
|
||||
#ifdef SUPPORT_SECURE_BOOT
|
||||
static grub_efi_boolean_t debug_secureboot = 0;
|
||||
static grub_efi_status_t (*entry_point) (grub_efi_handle_t image_handle, grub_efi_system_table_t *system_table);
|
||||
@@ -76,8 +72,6 @@ grub_chainloader_unload (void *context)
|
||||
b = grub_efi_system_table->boot_services;
|
||||
efi_call_1 (b->unload_image, image_handle);
|
||||
|
||||
- dev_handle = 0;
|
||||
-
|
||||
grub_dl_unref (my_mod);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
@@ -254,6 +248,17 @@ struct pe_coff_loader_image_context
|
||||
struct grub_pe32_header_no_msdos_stub *pe_hdr;
|
||||
};
|
||||
|
||||
+struct grub_secureboot_chainloader_context
|
||||
+{
|
||||
+ grub_efi_physical_address_t address;
|
||||
+ grub_efi_uintn_t pages;
|
||||
+ grub_ssize_t fsize;
|
||||
+ grub_efi_device_path_t *file_path;
|
||||
+ grub_efi_char16_t *cmdline;
|
||||
+ grub_ssize_t cmdline_len;
|
||||
+ grub_efi_handle_t dev_handle;
|
||||
+};
|
||||
+
|
||||
typedef struct pe_coff_loader_image_context pe_coff_loader_image_context_t;
|
||||
|
||||
struct grub_efi_shim_lock
|
||||
@@ -477,11 +482,13 @@ grub_efi_get_media_file_path (grub_efi_device_path_t *dp)
|
||||
}
|
||||
|
||||
static grub_efi_boolean_t
|
||||
-handle_image (void *data, grub_efi_uint32_t datasize)
|
||||
+handle_image (struct grub_secureboot_chainloader_context *load_context)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_efi_loaded_image_t *li, li_bak;
|
||||
grub_efi_status_t efi_status;
|
||||
+ void *data = (void *)(unsigned long)load_context->address;
|
||||
+ grub_efi_uint32_t datasize = load_context->fsize;
|
||||
char *buffer = NULL;
|
||||
char *buffer_aligned = NULL;
|
||||
grub_efi_uint32_t i, size;
|
||||
@@ -571,10 +578,10 @@ handle_image (void *data, grub_efi_uint32_t datasize)
|
||||
grub_memcpy (&li_bak, li, sizeof (grub_efi_loaded_image_t));
|
||||
li->image_base = buffer_aligned;
|
||||
li->image_size = context.image_size;
|
||||
- li->load_options = cmdline;
|
||||
- li->load_options_size = cmdline_len;
|
||||
- li->file_path = grub_efi_get_media_file_path (file_path);
|
||||
- li->device_handle = dev_handle;
|
||||
+ li->load_options = load_context->cmdline;
|
||||
+ li->load_options_size = load_context->cmdline_len;
|
||||
+ li->file_path = grub_efi_get_media_file_path (load_context->file_path);
|
||||
+ li->device_handle = load_context->dev_handle;
|
||||
if (li->file_path)
|
||||
{
|
||||
grub_printf ("file path: ");
|
||||
@@ -605,26 +612,27 @@ error_exit:
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_secureboot_chainloader_unload (void)
|
||||
+grub_secureboot_chainloader_unload (void* context)
|
||||
{
|
||||
grub_efi_boot_services_t *b;
|
||||
+ struct grub_secureboot_chainloader_context *sb_context = (struct grub_secureboot_chainloader_context *)context;
|
||||
|
||||
b = grub_efi_system_table->boot_services;
|
||||
- efi_call_2 (b->free_pages, address, pages);
|
||||
- grub_free (file_path);
|
||||
- grub_free (cmdline);
|
||||
- cmdline = 0;
|
||||
- file_path = 0;
|
||||
- dev_handle = 0;
|
||||
+ efi_call_2 (b->free_pages, sb_context->address, sb_context->pages);
|
||||
+ grub_free (sb_context->file_path);
|
||||
+ grub_free (sb_context->cmdline);
|
||||
+ grub_free (sb_context);
|
||||
|
||||
grub_dl_unref (my_mod);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
-grub_secureboot_chainloader_boot (void)
|
||||
+grub_secureboot_chainloader_boot (void *context)
|
||||
{
|
||||
- handle_image ((void *)address, fsize);
|
||||
+ struct grub_secureboot_chainloader_context *sb_context = (struct grub_secureboot_chainloader_context *)context;
|
||||
+
|
||||
+ handle_image (sb_context);
|
||||
grub_loader_unset ();
|
||||
return grub_errno;
|
||||
}
|
||||
@@ -635,6 +643,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
int argc, char *argv[])
|
||||
{
|
||||
grub_file_t file = 0;
|
||||
+ grub_ssize_t size;
|
||||
grub_efi_status_t status;
|
||||
grub_efi_boot_services_t *b;
|
||||
grub_device_t dev = 0;
|
||||
@@ -646,6 +655,8 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_efi_uintn_t pages = 0;
|
||||
grub_efi_char16_t *cmdline = NULL;
|
||||
grub_efi_handle_t image_handle = NULL;
|
||||
+ grub_ssize_t cmdline_len = 0;
|
||||
+ grub_efi_handle_t dev_handle = 0;
|
||||
|
||||
if (argc == 0)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("filename expected"));
|
||||
@@ -653,8 +664,6 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
|
||||
grub_dl_ref (my_mod);
|
||||
|
||||
- dev_handle = 0;
|
||||
-
|
||||
b = grub_efi_system_table->boot_services;
|
||||
|
||||
if (argc > 1)
|
||||
@@ -732,14 +741,14 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
grub_printf ("file path: ");
|
||||
grub_efi_print_device_path (file_path);
|
||||
|
||||
- fsize = grub_file_size (file);
|
||||
- if (!fsize)
|
||||
+ size = grub_file_size (file);
|
||||
+ if (!size)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
filename);
|
||||
goto fail;
|
||||
}
|
||||
- pages = (((grub_efi_uintn_t) fsize + ((1 << 12) - 1)) >> 12);
|
||||
+ pages = (((grub_efi_uintn_t) size + ((1 << 12) - 1)) >> 12);
|
||||
|
||||
status = efi_call_4 (b->allocate_pages, GRUB_EFI_ALLOCATE_ANY_PAGES,
|
||||
GRUB_EFI_LOADER_CODE,
|
||||
@@ -753,7 +762,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
|
||||
boot_image = (void *) ((grub_addr_t) address);
|
||||
- if (grub_file_read (file, boot_image, fsize) != fsize)
|
||||
+ if (grub_file_read (file, boot_image, size) != size)
|
||||
{
|
||||
if (grub_errno == GRUB_ERR_NONE)
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
@@ -763,7 +772,7 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
}
|
||||
|
||||
#if defined (__i386__) || defined (__x86_64__)
|
||||
- if (fsize >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
|
||||
+ if (size >= (grub_ssize_t) sizeof (struct grub_macho_fat_header))
|
||||
{
|
||||
struct grub_macho_fat_header *head = boot_image;
|
||||
if (head->magic
|
||||
@@ -786,30 +795,42 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
> ~grub_cpu_to_le32 (archs[i].size)
|
||||
|| grub_cpu_to_le32 (archs[i].offset)
|
||||
+ grub_cpu_to_le32 (archs[i].size)
|
||||
- > (grub_size_t) fsize)
|
||||
+ > (grub_size_t) size)
|
||||
{
|
||||
grub_error (GRUB_ERR_BAD_OS, N_("premature end of file %s"),
|
||||
filename);
|
||||
goto fail;
|
||||
}
|
||||
boot_image = (char *) boot_image + grub_cpu_to_le32 (archs[i].offset);
|
||||
- fsize = grub_cpu_to_le32 (archs[i].size);
|
||||
+ size = grub_cpu_to_le32 (archs[i].size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SUPPORT_SECURE_BOOT
|
||||
/* FIXME is secure boot possible also with universal binaries? */
|
||||
- if (debug_secureboot || (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED && grub_secure_validate ((void *)address, fsize)))
|
||||
+ if (debug_secureboot || (grub_efi_get_secureboot () == GRUB_EFI_SECUREBOOT_MODE_ENABLED && grub_secure_validate ((void *)address, size)))
|
||||
{
|
||||
+ struct grub_secureboot_chainloader_context *sb_context;
|
||||
+
|
||||
+ sb_context = grub_malloc (sizeof (*sb_context));
|
||||
+ if (!sb_context)
|
||||
+ goto fail;
|
||||
+ sb_context->cmdline = cmdline;
|
||||
+ sb_context->cmdline_len = cmdline_len;
|
||||
+ sb_context->fsize = size;
|
||||
+ sb_context->dev_handle = dev_handle;
|
||||
+ sb_context->address = address;
|
||||
+ sb_context->pages = pages;
|
||||
+ sb_context->file_path = file_path;
|
||||
grub_file_close (file);
|
||||
- grub_loader_set (grub_secureboot_chainloader_boot, grub_secureboot_chainloader_unload, 0);
|
||||
+ grub_loader_set_ex (grub_secureboot_chainloader_boot, grub_secureboot_chainloader_unload, sb_context, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
status = efi_call_6 (b->load_image, 0, grub_efi_image_handle, file_path,
|
||||
- boot_image, fsize,
|
||||
+ boot_image, size,
|
||||
&image_handle);
|
||||
#ifdef SUPPORT_SECURE_BOOT
|
||||
if (status == GRUB_EFI_SECURITY_VIOLATION && grub_efi_get_secureboot () != GRUB_EFI_SECUREBOOT_MODE_ENABLED)
|
||||
@@ -817,10 +838,21 @@ grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
|
||||
/* If it failed with security violation while not in secure boot mode,
|
||||
the firmware might be broken. We try to workaround on that by forcing
|
||||
the SB method! (bsc#887793) */
|
||||
+ struct grub_secureboot_chainloader_context *sb_context;
|
||||
+
|
||||
grub_dprintf ("chain", "Possible firmware flaw! Security violation while not in secure boot mode.\n");
|
||||
+ sb_context = grub_malloc (sizeof (*sb_context));
|
||||
+ if (!sb_context)
|
||||
+ goto fail;
|
||||
+ sb_context->cmdline = cmdline;
|
||||
+ sb_context->cmdline_len = cmdline_len;
|
||||
+ sb_context->fsize = size;
|
||||
+ sb_context->dev_handle = dev_handle;
|
||||
+ sb_context->address = address;
|
||||
+ sb_context->pages = pages;
|
||||
grub_file_close (file);
|
||||
- grub_loader_set (grub_secureboot_chainloader_boot,
|
||||
- grub_secureboot_chainloader_unload, 0);
|
||||
+ grub_loader_set_ex (grub_secureboot_chainloader_boot,
|
||||
+ grub_secureboot_chainloader_unload, sb_context, 0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
--
|
||||
2.34.1
|
||||
|
@ -1,3 +1,49 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue May 31 04:44:18 UTC 2022 - Michael Chang <mchang@suse.com>
|
||||
|
||||
- Security fixes and hardenings for boothole 3 / boothole 2022 (bsc#1198581)
|
||||
* 0001-video-Remove-trailing-whitespaces.patch
|
||||
* 0002-loader-efi-chainloader-Simplify-the-loader-state.patch
|
||||
* 0003-commands-boot-Add-API-to-pass-context-to-loader.patch
|
||||
- Fix CVE-2022-28736 (bsc#1198496)
|
||||
* 0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
|
||||
- Fix CVE-2022-28735 (bsc#1198495)
|
||||
* 0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
|
||||
* 0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
|
||||
* 0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
|
||||
* 0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch
|
||||
- Fix CVE-2021-3695 (bsc#1191184)
|
||||
* 0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
|
||||
- Fix CVE-2021-3696 (bsc#1191185)
|
||||
* 0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
|
||||
* 0011-video-readers-png-Sanity-check-some-huffman-codes.patch
|
||||
* 0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
|
||||
* 0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
|
||||
* 0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
|
||||
- Fix CVE-2021-3697 (bsc#1191186)
|
||||
* 0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
|
||||
* 0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
|
||||
- Fix CVE-2022-28733 (bsc#1198460)
|
||||
* 0017-net-ip-Do-IP-fragment-maths-safely.patch
|
||||
* 0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
|
||||
* 0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
|
||||
* 0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
|
||||
* 0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
|
||||
* 0022-net-tftp-Avoid-a-trivial-UAF.patch
|
||||
* 0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
|
||||
- Fix CVE-2022-28734 (bsc#1198493)
|
||||
* 0024-net-http-Fix-OOB-write-for-split-http-headers.patch
|
||||
- Fix CVE-2022-28734 (bsc#1198493)
|
||||
* 0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
|
||||
* 0026-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
|
||||
* 0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
|
||||
* 0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
|
||||
* 0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
|
||||
* 0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
|
||||
* 0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
|
||||
* 0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
|
||||
- Bump grub's SBAT generation to 2
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Tue May 31 04:41:44 UTC 2022 - Michael Chang <mchang@suse.com>
|
||||
|
||||
|
34
grub2.spec
34
grub2.spec
@ -22,7 +22,7 @@
|
||||
%if %{defined sbat_distro}
|
||||
# SBAT metadata
|
||||
%define sbat_generation 1
|
||||
%define sbat_generation_grub 1
|
||||
%define sbat_generation_grub 2
|
||||
%else
|
||||
%{error please define sbat_distro, sbat_distro_summary and sbat_distro_url}
|
||||
%endif
|
||||
@ -375,6 +375,38 @@ Patch849: 0001-powerpc-do-CAS-in-a-more-compatible-way.patch
|
||||
Patch850: 0001-Fix-infinite-boot-loop-on-headless-system-in-qemu.patch
|
||||
Patch851: 0001-libc-config-merge-from-glibc.patch
|
||||
Patch852: 0001-ofdisk-improve-boot-time-by-lookup-boot-disk-first.patch
|
||||
Patch853: 0001-video-Remove-trailing-whitespaces.patch
|
||||
Patch854: 0002-loader-efi-chainloader-Simplify-the-loader-state.patch
|
||||
Patch855: 0003-commands-boot-Add-API-to-pass-context-to-loader.patch
|
||||
Patch856: 0004-loader-efi-chainloader-Use-grub_loader_set_ex.patch
|
||||
Patch857: 0005-kern-efi-sb-Reject-non-kernel-files-in-the-shim_lock.patch
|
||||
Patch858: 0006-kern-file-Do-not-leak-device_name-on-error-in-grub_f.patch
|
||||
Patch859: 0007-video-readers-png-Abort-sooner-if-a-read-operation-f.patch
|
||||
Patch860: 0008-video-readers-png-Refuse-to-handle-multiple-image-he.patch
|
||||
Patch861: 0009-video-readers-png-Drop-greyscale-support-to-fix-heap.patch
|
||||
Patch862: 0010-video-readers-png-Avoid-heap-OOB-R-W-inserting-huff-.patch
|
||||
Patch863: 0011-video-readers-png-Sanity-check-some-huffman-codes.patch
|
||||
Patch864: 0012-video-readers-jpeg-Abort-sooner-if-a-read-operation-.patch
|
||||
Patch865: 0013-video-readers-jpeg-Do-not-reallocate-a-given-huff-ta.patch
|
||||
Patch866: 0014-video-readers-jpeg-Refuse-to-handle-multiple-start-o.patch
|
||||
Patch867: 0015-video-readers-jpeg-Block-int-underflow-wild-pointer-.patch
|
||||
Patch868: 0016-normal-charset-Fix-array-out-of-bounds-formatting-un.patch
|
||||
Patch869: 0017-net-ip-Do-IP-fragment-maths-safely.patch
|
||||
Patch870: 0018-net-netbuff-Block-overly-large-netbuff-allocs.patch
|
||||
Patch871: 0019-net-dns-Fix-double-free-addresses-on-corrupt-DNS-res.patch
|
||||
Patch872: 0020-net-dns-Don-t-read-past-the-end-of-the-string-we-re-.patch
|
||||
Patch873: 0021-net-tftp-Prevent-a-UAF-and-double-free-from-a-failed.patch
|
||||
Patch874: 0022-net-tftp-Avoid-a-trivial-UAF.patch
|
||||
Patch875: 0023-net-http-Do-not-tear-down-socket-if-it-s-already-bee.patch
|
||||
Patch876: 0024-net-http-Fix-OOB-write-for-split-http-headers.patch
|
||||
Patch877: 0025-net-http-Error-out-on-headers-with-LF-without-CR.patch
|
||||
Patch878: 0026-fs-f2fs-Do-not-read-past-the-end-of-nat-journal-entr.patch
|
||||
Patch879: 0027-fs-f2fs-Do-not-read-past-the-end-of-nat-bitmap.patch
|
||||
Patch880: 0028-fs-f2fs-Do-not-copy-file-names-that-are-too-long.patch
|
||||
Patch881: 0029-fs-btrfs-Fix-several-fuzz-issues-with-invalid-dir-it.patch
|
||||
Patch882: 0030-fs-btrfs-Fix-more-ASAN-and-SEGV-issues-found-with-fu.patch
|
||||
Patch883: 0031-fs-btrfs-Fix-more-fuzz-issues-related-to-chunks.patch
|
||||
Patch884: 0032-Use-grub_loader_set_ex-for-secureboot-chainloader.patch
|
||||
|
||||
Requires: gettext-runtime
|
||||
%if 0%{?suse_version} >= 1140
|
||||
|
Loading…
Reference in New Issue
Block a user