All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zhixiong Chi <zhixiong.chi@windriver.com>
To: <openembedded-core@lists.openembedded.org>
Subject: Re: [PATCH] grub: CVE-2017-9763
Date: Thu, 6 Jul 2017 16:43:28 +0800	[thread overview]
Message-ID: <595DF830.9080401@windriver.com> (raw)
In-Reply-To: <1499330451-117347-1-git-send-email-zhixiong.chi@windriver.com>

Please ignore this, I will resent one updated patch.

Thanks.

On 2017年07月06日 16:40, Zhixiong Chi wrote:
> Issue: LIN9-4520
>
> The grub_ext2_read_block function in fs/ext2.c in GNU GRUB before
> 2013-11-12, allows remote attackers to cause a denial of service
> (excessive stack use and application crash) via a crafted binary
> file, related to use of a variable-size stack array.
>
> patch from http://git.savannah.gnu.org/cgit/grub.git commit
> f797ec85a02c0137a739fba7ee3f40d063bb7ade
> ac8cac1dac50daaf1c390d701cca3b55e16ee768
>
> CVE: CVE-2017-9763
>
> Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> ---
>   meta/recipes-bsp/grub/files/CVE-2017-9763.patch    | 252 +++++++++++++++++++++
>   .../grub-core-fs-ext2-use-shifts-rather-than.patch | 105 +++++++++
>   meta/recipes-bsp/grub/grub2.inc                    |   2 +
>   3 files changed, 359 insertions(+)
>   create mode 100644 meta/recipes-bsp/grub/files/CVE-2017-9763.patch
>   create mode 100644 meta/recipes-bsp/grub/files/grub-core-fs-ext2-use-shifts-rather-than.patch
>
> diff --git a/meta/recipes-bsp/grub/files/CVE-2017-9763.patch b/meta/recipes-bsp/grub/files/CVE-2017-9763.patch
> new file mode 100644
> index 0000000..4286730
> --- /dev/null
> +++ b/meta/recipes-bsp/grub/files/CVE-2017-9763.patch
> @@ -0,0 +1,252 @@
> +From ac8cac1dac50daaf1c390d701cca3b55e16ee768 Mon Sep 17 00:00:00 2001
> +From: Vladimir Serbinenko <phcoder@gmail.com>
> +Date: Tue, 12 Nov 2013 03:04:19 +0100
> +Subject: 	* grub-core/fs/ext2.c: Remove variable length arrays.
> +
> +Upstream-Status: Backport
> +
> +CVE: CVE-2017-9763
> +
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +
> +---
> + ChangeLog           |  4 +++
> + grub-core/fs/ext2.c | 79 +++++++++++++++++++++++++++++++++--------------------
> + 2 files changed, 53 insertions(+), 30 deletions(-)
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index 269a841..75034e0 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,7 @@
> ++2013-11-12  Vladimir Serbinenko  <phcoder@gmail.com>
> ++
> ++	* grub-core/fs/ext2.c: Remove variable length arrays.
> ++
> + 2013-01-05  Vladimir Serbinenko  <phcoder@gmail.com>
> +
> + 	* grub-core/fs/ext2.c (grub_ext2_read_block): Use shifts rather than
> +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
> +index 6941ef2..aba5cb1 100644
> +--- a/grub-core/fs/ext2.c
> ++++ b/grub-core/fs/ext2.c
> +@@ -247,6 +247,7 @@ struct ext2_dirent
> + {
> +   grub_uint32_t inode;
> +   grub_uint16_t direntlen;
> ++#define MAX_NAMELEN 255
> +   grub_uint8_t namelen;
> +   grub_uint8_t filetype;
> + };
> +@@ -344,11 +345,12 @@ grub_ext2_blockgroup (struct grub_ext2_data *data, int group,
> + }
> +
> + static struct grub_ext4_extent_header *
> +-grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf,
> ++grub_ext4_find_leaf (struct grub_ext2_data *data,
> +                      struct grub_ext4_extent_header *ext_block,
> +                      grub_uint32_t fileblock)
> + {
> +   struct grub_ext4_extent_idx *index;
> ++  void *buf = NULL;
> +
> +   while (1)
> +     {
> +@@ -357,8 +359,8 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf,
> +
> +       index = (struct grub_ext4_extent_idx *) (ext_block + 1);
> +
> +-      if (grub_le_to_cpu16(ext_block->magic) != EXT4_EXT_MAGIC)
> +-        return 0;
> ++      if (ext_block->magic != grub_cpu_to_le16_compile_time (EXT4_EXT_MAGIC))
> ++	goto fail;
> +
> +       if (ext_block->depth == 0)
> +         return ext_block;
> +@@ -370,17 +372,24 @@ grub_ext4_find_leaf (struct grub_ext2_data *data, grub_properly_aligned_t *buf,
> +         }
> +
> +       if (--i < 0)
> +-        return 0;
> ++	goto fail;
> +
> +       block = grub_le_to_cpu16 (index[i].leaf_hi);
> +       block = (block << 32) + grub_le_to_cpu32 (index[i].leaf);
> ++      if (!buf)
> ++	buf = grub_malloc (EXT2_BLOCK_SIZE(data));
> ++      if (!buf)
> ++	goto fail;
> +       if (grub_disk_read (data->disk,
> +                           block << LOG2_EXT2_BLOCK_SIZE (data),
> +                           0, EXT2_BLOCK_SIZE(data), buf))
> +-        return 0;
> ++	goto fail;
> +
> +-      ext_block = (struct grub_ext4_extent_header *) buf;
> ++      ext_block = buf;
> +     }
> ++ fail:
> ++  grub_free (buf);
> ++  return 0;
> + }
> +
> + static grub_disk_addr_t
> +@@ -394,14 +403,12 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +
> +   if (inode->flags & grub_cpu_to_le32_compile_time (EXT4_EXTENTS_FLAG))
> +     {
> +-      GRUB_PROPERLY_ALIGNED_ARRAY (buf, EXT2_BLOCK_SIZE(data));
> +       struct grub_ext4_extent_header *leaf;
> +       struct grub_ext4_extent *ext;
> +       int i;
> ++      grub_disk_addr_t ret;
> +
> +-      leaf = grub_ext4_find_leaf (data, buf,
> +-                                  (struct grub_ext4_extent_header *) inode->blocks.dir_blocks,
> +-                                  fileblock);
> ++      leaf = grub_ext4_find_leaf (data, (struct grub_ext4_extent_header *) inode->blocks.dir_blocks, fileblock);
> +       if (! leaf)
> +         {
> +           grub_error (GRUB_ERR_BAD_FS, "invalid extent");
> +@@ -419,7 +426,7 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +         {
> +           fileblock -= grub_le_to_cpu32 (ext[i].block);
> +           if (fileblock >= grub_le_to_cpu16 (ext[i].len))
> +-            return 0;
> ++	    ret = 0;
> +           else
> +             {
> +               grub_disk_addr_t start;
> +@@ -427,14 +434,19 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +               start = grub_le_to_cpu16 (ext[i].start_hi);
> +               start = (start << 32) + grub_le_to_cpu32 (ext[i].start);
> +
> +-              return fileblock + start;
> ++              ret = fileblock + start;
> +             }
> +         }
> +       else
> +         {
> +           grub_error (GRUB_ERR_BAD_FS, "something wrong with extent");
> +-          return -1;
> ++	  ret = -1;
> +         }
> ++
> ++      if (leaf != (struct grub_ext4_extent_header *) inode->blocks.dir_blocks)
> ++	grub_free (leaf);
> ++
> ++      return ret;
> +     }
> +   /* Direct blocks.  */
> +   if (fileblock < INDIRECT_BLOCKS)
> +@@ -442,16 +454,17 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +   /* Indirect.  */
> +   else if (fileblock < INDIRECT_BLOCKS + blksz / 4)
> +     {
> +-      grub_uint32_t indir[blksz / 4];
> ++      grub_uint32_t indir;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> + 			   grub_le_to_cpu32 (inode->blocks.indir_block))
> + 			  << log2_blksz,
> +-			  0, blksz, indir))
> ++			  (fileblock - INDIRECT_BLOCKS) * sizeof (indir),
> ++			  sizeof (indir), &indir))
> + 	return grub_errno;
> +
> +-      blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
> ++      blknr = grub_le_to_cpu32 (indir);
> +     }
> +   /* Double indirect.  */
> +   else if (fileblock < INDIRECT_BLOCKS
> +@@ -460,24 +473,26 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +       int log_perblock = log2_blksz + 9 - 2;
> +       grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS
> + 					     + blksz / 4);
> +-      grub_uint32_t indir[blksz / 4];
> ++      grub_uint32_t indir;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> + 			   grub_le_to_cpu32 (inode->blocks.double_indir_block))
> + 			  << log2_blksz,
> +-			  0, blksz, indir))
> ++			  (rblock >> log_perblock) * sizeof (indir),
> ++			  sizeof (indir), &indir))
> + 	return grub_errno;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> +-			   grub_le_to_cpu32 (indir[rblock >> log_perblock]))
> ++			   grub_le_to_cpu32 (indir))
> + 			  << log2_blksz,
> +-			  0, blksz, indir))
> ++			  (rblock & ((1 << log_perblock) - 1)) * sizeof (indir),
> ++			  sizeof (indir), &indir))
> + 	return grub_errno;
> +
> +
> +-      blknr = grub_le_to_cpu32 (indir[rblock & ((1 << log_perblock) - 1)]);
> ++      blknr = grub_le_to_cpu32 (indir);
> +     }
> +   /* triple indirect.  */
> +   else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1)
> +@@ -487,34 +502,38 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +       int log_perblock = log2_blksz + 9 - 2;
> +       grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
> + 					     * (blksz / 4 + 1));
> +-      grub_uint32_t indir[blksz / 4];
> ++      grub_uint32_t indir;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> + 			   grub_le_to_cpu32 (inode->blocks.triple_indir_block))
> + 			  << log2_blksz,
> +-			  0, blksz, indir))
> ++			  ((rblock >> log_perblock) >> log_perblock)
> ++			  * sizeof (indir), sizeof (indir), &indir))
> + 	return grub_errno;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> +-			   grub_le_to_cpu32 (indir[(rblock >> log_perblock) >> log_perblock]))
> ++			   grub_le_to_cpu32 (indir))
> + 			  << log2_blksz,
> +-			  0, blksz, indir))
> ++			  ((rblock >> log_perblock)
> ++			   & ((1 << log_perblock) - 1)) * sizeof (indir),
> ++			  sizeof (indir), &indir))
> + 	return grub_errno;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> +-			   grub_le_to_cpu32 (indir[(rblock >> log_perblock) & ((1 << log_perblock) - 1)]))
> ++			   grub_le_to_cpu32 (indir))
> + 			  << log2_blksz,
> +-			  0, blksz, indir))
> ++			  (rblock  & ((1 << log_perblock) - 1))
> ++			  * sizeof (indir), sizeof (indir), &indir))
> + 	return grub_errno;
> +
> +-      blknr = grub_le_to_cpu32 (indir[rblock  & ((1 << log_perblock) - 1)]);
> ++      blknr = grub_le_to_cpu32 (indir);
> +     }
> +   else
> +     {
> +-      grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
> ++      grub_error (GRUB_ERR_BAD_FS,
> + 		  "ext2fs doesn't support quadruple indirect blocks");
> +     }
> +
> +@@ -719,7 +738,7 @@ grub_ext2_iterate_dir (grub_fshelp_node_t dir,
> +
> +       if (dirent.inode != 0 && dirent.namelen != 0)
> + 	{
> +-	  char filename[dirent.namelen + 1];
> ++	  char filename[MAX_NAMELEN + 1];
> + 	  struct grub_fshelp_node *fdiro;
> + 	  enum grub_fshelp_filetype type = GRUB_FSHELP_UNKNOWN;
> +
> +--
> +cgit v1.0-41-gc330
> diff --git a/meta/recipes-bsp/grub/files/grub-core-fs-ext2-use-shifts-rather-than.patch b/meta/recipes-bsp/grub/files/grub-core-fs-ext2-use-shifts-rather-than.patch
> new file mode 100644
> index 0000000..d7fca89
> --- /dev/null
> +++ b/meta/recipes-bsp/grub/files/grub-core-fs-ext2-use-shifts-rather-than.patch
> @@ -0,0 +1,105 @@
> +From f797ec85a02c0137a739fba7ee3f40d063bb7ade Mon Sep 17 00:00:00 2001
> +From: Vladimir 'phcoder' Serbinenko <phcoder@gmail.com>
> +Date: Sat, 5 Jan 2013 18:37:34 +0100
> +Subject: 	* grub-core/fs/ext2.c (grub_ext2_read_block): Use shifts
> + rather than 	divisions.
> +
> +Upstream-Status: Backport
> +
> +This patch is for CVE-2017-9763 patch.
> +
> +Signed-off-by: Zhixiong Chi <zhixiong.chi@windriver.com>
> +---
> + ChangeLog           |  5 +++++
> + grub-core/fs/ext2.c | 30 ++++++++++++++++--------------
> + 2 files changed, 21 insertions(+), 14 deletions(-)
> +
> +diff --git a/ChangeLog b/ChangeLog
> +index 88fd763..af29161 100644
> +--- a/ChangeLog
> ++++ b/ChangeLog
> +@@ -1,3 +1,8 @@
> ++2013-01-05  Vladimir Serbinenko  <phcoder@gmail.com>
> ++
> ++	* grub-core/fs/ext2.c (grub_ext2_read_block): Use shifts rather than
> ++	divisions.
> ++
> + 2013-01-20  Colin Watson  <cjwatson@ubuntu.com>
> +
> +        * grub-core/loader/i386/linux.c (grub_cmd_initrd): Don't add the
> +diff --git a/grub-core/fs/ext2.c b/grub-core/fs/ext2.c
> +index bd1ab24..cf2e2f4 100644
> +--- a/grub-core/fs/ext2.c
> ++++ b/grub-core/fs/ext2.c
> +@@ -454,11 +454,12 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +       blknr = grub_le_to_cpu32 (indir[fileblock - INDIRECT_BLOCKS]);
> +     }
> +   /* Double indirect.  */
> +-  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1))
> ++  else if (fileblock < INDIRECT_BLOCKS
> ++	   + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1))
> +     {
> +-      unsigned int perblock = blksz / 4;
> +-      unsigned int rblock = fileblock - (INDIRECT_BLOCKS
> +-					 + blksz / 4);
> ++      int log_perblock = log2_blksz + 9 - 2;
> ++      grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS
> ++					     + blksz / 4);
> +       grub_uint32_t indir[blksz / 4];
> +
> +       if (grub_disk_read (data->disk,
> +@@ -470,21 +471,22 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> +-			   grub_le_to_cpu32 (indir[rblock / perblock]))
> ++			   grub_le_to_cpu32 (indir[rblock >> log_perblock]))
> + 			  << log2_blksz,
> + 			  0, blksz, indir))
> + 	return grub_errno;
> +
> +
> +-      blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
> ++      blknr = grub_le_to_cpu32 (indir[rblock & ((1 << log_perblock) - 1)]);
> +     }
> +   /* triple indirect.  */
> +-  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * (blksz / 4 + 1)
> +-	   + (blksz / 4) * (blksz / 4) * (blksz / 4 + 1))
> ++  else if (fileblock < INDIRECT_BLOCKS + blksz / 4 * ((grub_disk_addr_t) blksz / 4 + 1)
> ++	   + ((grub_disk_addr_t) blksz / 4) * ((grub_disk_addr_t) blksz / 4)
> ++	   * ((grub_disk_addr_t) blksz / 4 + 1))
> +     {
> +-      unsigned int perblock = blksz / 4;
> +-      unsigned int rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
> +-					 * (blksz / 4 + 1));
> ++      int log_perblock = log2_blksz + 9 - 2;
> ++      grub_disk_addr_t rblock = fileblock - (INDIRECT_BLOCKS + blksz / 4
> ++					     * (blksz / 4 + 1));
> +       grub_uint32_t indir[blksz / 4];
> +
> +       if (grub_disk_read (data->disk,
> +@@ -496,19 +498,19 @@ grub_ext2_read_block (grub_fshelp_node_t node, grub_disk_addr_t fileblock)
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> +-			   grub_le_to_cpu32 (indir[(rblock / perblock) / perblock]))
> ++			   grub_le_to_cpu32 (indir[(rblock >> log_perblock) >> log_perblock]))
> + 			  << log2_blksz,
> + 			  0, blksz, indir))
> + 	return grub_errno;
> +
> +       if (grub_disk_read (data->disk,
> + 			  ((grub_disk_addr_t)
> +-			   grub_le_to_cpu32 (indir[(rblock / perblock) % perblock]))
> ++			   grub_le_to_cpu32 (indir[(rblock >> log_perblock) & ((1 << log_perblock) - 1)]))
> + 			  << log2_blksz,
> + 			  0, blksz, indir))
> + 	return grub_errno;
> +
> +-      blknr = grub_le_to_cpu32 (indir[rblock % perblock]);
> ++      blknr = grub_le_to_cpu32 (indir[rblock  & ((1 << log_perblock) - 1)]);
> +     }
> +   else
> +     {
> +--
> +cgit v1.0-41-gc330
> diff --git a/meta/recipes-bsp/grub/grub2.inc b/meta/recipes-bsp/grub/grub2.inc
> index ef893b3..a51c5ac 100644
> --- a/meta/recipes-bsp/grub/grub2.inc
> +++ b/meta/recipes-bsp/grub/grub2.inc
> @@ -36,6 +36,8 @@ SRC_URI = "ftp://ftp.gnu.org/gnu/grub/grub-${PV}.tar.gz \
>              file://0001-grub-core-kern-efi-mm.c-grub_efi_finish_boot_service.patch \
>              file://0002-grub-core-kern-efi-mm.c-grub_efi_get_memory_map-Neve.patch \
>              file://0001-build-Use-AC_HEADER_MAJOR-to-find-device-macros.patch \
> +           file://grub-core-fs-ext2-use-shifts-rather-than.patch \
> +           file://CVE-2017-9763.patch \
>               "
>   
>   DEPENDS = "flex-native bison-native autogen-native"

-- 
---------------------
Thanks,
Zhixiong Chi
Tel: +86-10-8477-7036



  reply	other threads:[~2017-07-06  8:43 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-06  8:40 [PATCH] grub: CVE-2017-9763 Zhixiong Chi
2017-07-06  8:43 ` Zhixiong Chi [this message]
2017-07-06  9:01 ` ✗ patchtest: failure for " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=595DF830.9080401@windriver.com \
    --to=zhixiong.chi@windriver.com \
    --cc=openembedded-core@lists.openembedded.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.