]> code.ossystems Code Review - openembedded-core.git/commitdiff
Binutils: Security fix for CVE-2018-7568
authorArmin Kuster <akuster@mvista.com>
Wed, 8 Aug 2018 20:47:28 +0000 (13:47 -0700)
committerRichard Purdie <richard.purdie@linuxfoundation.org>
Wed, 15 Aug 2018 09:22:31 +0000 (10:22 +0100)
Affects: <= 2.30

Signed-off-by: Armin Kuster <akuster@mvista.com>
meta/recipes-devtools/binutils/binutils-2.29.1.inc
meta/recipes-devtools/binutils/binutils/CVE-2018-7568_p1.patch [new file with mode: 0644]
meta/recipes-devtools/binutils/binutils/CVE-2018-7568_p2.patch [new file with mode: 0644]

index 13389a1d30ad99764fd12689c0110a61a70e187e..ceb8e855795c4349402b63cc46d4a587b35cff29 100644 (file)
@@ -73,6 +73,8 @@ SRC_URI = "\
      file://CVE-2018-6323.patch \
      file://CVE-2018-6759.patch \
      file://CVE-2018-7208.patch \
+     file://CVE-2018-7568_p1.patch \
+     file://CVE-2018-7568_p2.patch \
 "
 S  = "${WORKDIR}/git"
 
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2018-7568_p1.patch b/meta/recipes-devtools/binutils/binutils/CVE-2018-7568_p1.patch
new file mode 100644 (file)
index 0000000..b014080
--- /dev/null
@@ -0,0 +1,161 @@
+From 1da5c9a485f3dcac4c45e96ef4b7dae5948314b5 Mon Sep 17 00:00:00 2001
+From: Alan Modra <amodra@gmail.com>
+Date: Mon, 25 Sep 2017 20:20:38 +0930
+Subject: [PATCH] PR22202, buffer overflow in parse_die
+
+There was a complete lack of sanity checking in dwarf1.c
+
+       PR 22202
+       * dwarf1.c (parse_die): Sanity check pointer against section limit
+       before dereferencing.
+       (parse_line_table): Likewise.
+
+Upstream-Status: Backport
+Affects: <= 2.30
+CVE: CVE-2018-7568 patch1
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ bfd/ChangeLog |  7 +++++++
+ bfd/dwarf1.c  | 56 ++++++++++++++++++++++++++++++++++++++------------------
+ 2 files changed, 45 insertions(+), 18 deletions(-)
+
+Index: git/bfd/dwarf1.c
+===================================================================
+--- git.orig/bfd/dwarf1.c
++++ git/bfd/dwarf1.c
+@@ -189,11 +189,14 @@ parse_die (bfd *             abfd,
+   memset (aDieInfo, 0, sizeof (* aDieInfo));
+   /* First comes the length.  */
+-  aDieInfo->length = bfd_get_32 (abfd, (bfd_byte *) xptr);
++  if (xptr + 4 > aDiePtrEnd)
++    return FALSE;
++  aDieInfo->length = bfd_get_32 (abfd, xptr);
+   xptr += 4;
+   if (aDieInfo->length == 0
+-      || (this_die + aDieInfo->length) >= aDiePtrEnd)
++      || this_die + aDieInfo->length > aDiePtrEnd)
+     return FALSE;
++  aDiePtrEnd = this_die + aDieInfo->length;
+   if (aDieInfo->length < 6)
+     {
+       /* Just padding bytes.  */
+@@ -202,18 +205,20 @@ parse_die (bfd *             abfd,
+     }
+   /* Then the tag.  */
+-  aDieInfo->tag = bfd_get_16 (abfd, (bfd_byte *) xptr);
++  if (xptr + 2 > aDiePtrEnd)
++    return FALSE;
++  aDieInfo->tag = bfd_get_16 (abfd, xptr);
+   xptr += 2;
+   /* Then the attributes.  */
+-  while (xptr < (this_die + aDieInfo->length))
++  while (xptr + 2 <= aDiePtrEnd)
+     {
+       unsigned short attr;
+       /* Parse the attribute based on its form.  This section
+          must handle all dwarf1 forms, but need only handle the
+        actual attributes that we care about.  */
+-      attr = bfd_get_16 (abfd, (bfd_byte *) xptr);
++      attr = bfd_get_16 (abfd, xptr);
+       xptr += 2;
+       switch (FORM_FROM_ATTR (attr))
+@@ -223,12 +228,15 @@ parse_die (bfd *             abfd,
+         break;
+       case FORM_DATA4:
+       case FORM_REF:
+-        if (attr == AT_sibling)
+-          aDieInfo->sibling = bfd_get_32 (abfd, (bfd_byte *) xptr);
+-        else if (attr == AT_stmt_list)
++        if (xptr + 4 <= aDiePtrEnd)
+           {
+-            aDieInfo->stmt_list_offset = bfd_get_32 (abfd, (bfd_byte *) xptr);
+-            aDieInfo->has_stmt_list = 1;
++            if (attr == AT_sibling)
++              aDieInfo->sibling = bfd_get_32 (abfd, xptr);
++            else if (attr == AT_stmt_list)
++              {
++                aDieInfo->stmt_list_offset = bfd_get_32 (abfd, xptr);
++                aDieInfo->has_stmt_list = 1;
++              }
+           }
+         xptr += 4;
+         break;
+@@ -236,22 +244,29 @@ parse_die (bfd *             abfd,
+         xptr += 8;
+         break;
+       case FORM_ADDR:
+-        if (attr == AT_low_pc)
+-          aDieInfo->low_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
+-        else if (attr == AT_high_pc)
+-          aDieInfo->high_pc = bfd_get_32 (abfd, (bfd_byte *) xptr);
++        if (xptr + 4 <= aDiePtrEnd)
++          {
++            if (attr == AT_low_pc)
++              aDieInfo->low_pc = bfd_get_32 (abfd, xptr);
++            else if (attr == AT_high_pc)
++              aDieInfo->high_pc = bfd_get_32 (abfd, xptr);
++          }
+         xptr += 4;
+         break;
+       case FORM_BLOCK2:
+-        xptr += 2 + bfd_get_16 (abfd, (bfd_byte *) xptr);
++        if (xptr + 2 <= aDiePtrEnd)
++          xptr += bfd_get_16 (abfd, xptr);
++        xptr += 2;
+         break;
+       case FORM_BLOCK4:
+-        xptr += 4 + bfd_get_32 (abfd, (bfd_byte *) xptr);
++        if (xptr + 4 <= aDiePtrEnd)
++          xptr += bfd_get_32 (abfd, xptr);
++        xptr += 4;
+         break;
+       case FORM_STRING:
+         if (attr == AT_name)
+           aDieInfo->name = (char *) xptr;
+-        xptr += strlen ((char *) xptr) + 1;
++        xptr += strnlen ((char *) xptr, aDiePtrEnd - xptr) + 1;
+         break;
+       }
+     }
+@@ -290,7 +305,7 @@ parse_line_table (struct dwarf1_debug* s
+     }
+   xptr = stash->line_section + aUnit->stmt_list_offset;
+-  if (xptr < stash->line_section_end)
++  if (xptr + 8 <= stash->line_section_end)
+     {
+       unsigned long eachLine;
+       bfd_byte *tblend;
+@@ -318,6 +333,11 @@ parse_line_table (struct dwarf1_debug* s
+       for (eachLine = 0; eachLine < aUnit->line_count; eachLine++)
+       {
++        if (xptr + 10 > stash->line_section_end)
++          {
++            aUnit->line_count = eachLine;
++            break;
++          }
+         /* A line number.  */
+         aUnit->linenumber_table[eachLine].linenumber
+           = bfd_get_32 (stash->abfd, (bfd_byte *) xptr);
+Index: git/bfd/ChangeLog
+===================================================================
+--- git.orig/bfd/ChangeLog
++++ git/bfd/ChangeLog
+@@ -1,3 +1,10 @@
++2017-09-25  Alan Modra  <amodra@gmail.com>
++
++       PR 22202
++       * dwarf1.c (parse_die): Sanity check pointer against section limit
++       before dereferencing.
++       (parse_line_table): Likewise.
++
+ 2018-01-29  Alan Modra  <amodra@gmail.com>
+        PR 22741
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2018-7568_p2.patch b/meta/recipes-devtools/binutils/binutils/CVE-2018-7568_p2.patch
new file mode 100644 (file)
index 0000000..b5511d7
--- /dev/null
@@ -0,0 +1,73 @@
+From eef104664efb52965d85a28bc3fc7c77e52e48e2 Mon Sep 17 00:00:00 2001
+From: Nick Clifton <nickc@redhat.com>
+Date: Wed, 28 Feb 2018 10:13:54 +0000
+Subject: [PATCH] Fix potential integer overflow when reading corrupt dwarf1
+ debug information.
+
+       PR 22894
+       * dwarf1.c (parse_die): Check the length of form blocks before
+       advancing the data pointer.
+
+Upstream-Status: Backport
+Affects: <= 2.30
+CVE: CVE-2018-7568 patch2
+Signed-off-by: Armin Kuster <akuster@mvista.com>
+
+---
+ bfd/ChangeLog |  6 ++++++
+ bfd/dwarf1.c  | 17 +++++++++++++++--
+ 2 files changed, 21 insertions(+), 2 deletions(-)
+
+Index: git/bfd/dwarf1.c
+===================================================================
+--- git.orig/bfd/dwarf1.c
++++ git/bfd/dwarf1.c
+@@ -213,6 +213,7 @@ parse_die (bfd *             abfd,
+   /* Then the attributes.  */
+   while (xptr + 2 <= aDiePtrEnd)
+     {
++      unsigned int   block_len;
+       unsigned short attr;
+       /* Parse the attribute based on its form.  This section
+@@ -255,12 +256,24 @@ parse_die (bfd *             abfd,
+         break;
+       case FORM_BLOCK2:
+         if (xptr + 2 <= aDiePtrEnd)
+-          xptr += bfd_get_16 (abfd, xptr);
++          {
++            block_len = bfd_get_16 (abfd, xptr);
++            if (xptr + block_len > aDiePtrEnd
++                || xptr + block_len < xptr)
++              return FALSE;
++            xptr += block_len;
++          }
+         xptr += 2;
+         break;
+       case FORM_BLOCK4:
+         if (xptr + 4 <= aDiePtrEnd)
+-          xptr += bfd_get_32 (abfd, xptr);
++          {
++            block_len = bfd_get_32 (abfd, xptr);
++            if (xptr + block_len > aDiePtrEnd
++                || xptr + block_len < xptr)
++              return FALSE;
++            xptr += block_len;
++          }
+         xptr += 4;
+         break;
+       case FORM_STRING:
+Index: git/bfd/ChangeLog
+===================================================================
+--- git.orig/bfd/ChangeLog
++++ git/bfd/ChangeLog
+@@ -1,3 +1,9 @@
++2018-02-28  Nick Clifton  <nickc@redhat.com>
++
++       PR 22894
++       * dwarf1.c (parse_die): Check the length of form blocks before
++       advancing the data pointer.
++
+ 2017-09-25  Alan Modra  <amodra@gmail.com>
+        PR 22202