Package: release.debian.org
Severity: normal
Tags: jessie
User: release.debian....@packages.debian.org
Usertags: pu

Dear release team,

I would like to propose the following changes to the dwarfutils
package in jessie:

  * New maintainer.
  * Add patch CVE-2015-8538.patch to fix CVE-2015-8538 (Closes: #807817).
  * Add patch CVE-2015-8750.patch to fix CVE-2015-8750 (Closes: #813182).
  * Add patch CVE-2016-2050.patch to fix CVE-2016-2050.
  * Add patch CVE-2016-2091.patch to fix CVE-2016-2091 (Closes: #813148).
  * Add patch CVE-2016-5034.patch to fix CVE-2016-5034.
  * Add patch CVE-2016-5036.patch to fix CVE-2016-5036.
  * Add patch CVE-2016-5038.patch to fix CVE-2016-5038.
  * Add patch CVE-2016-5039.patch to fix CVE-2016-5039.
  * Add patch CVE-2016-5042.patch to fix CVE-2016-5042.

The current version in stable is rather old and still has Troy Heber
listed as the package maintainer, who orphaned the package a few years
ago. I am the new maintainer.

Because of the rather large number of patches, I have decided against
replicating them in this bug report, but each one of them features a
DEP-3 conformant header with information regarding its origin and, if
applicable, the corresponding Debian bug, so I hope you won't have
much trouble navigating them.

I have attached the debdiff I would like to apply to the current
version in stable.

Thank you!

Kind regards,
Fabian
diff -u dwarfutils-20120410/debian/changelog 
dwarfutils-20120410/debian/changelog
--- dwarfutils-20120410/debian/changelog
+++ dwarfutils-20120410/debian/changelog
@@ -1,3 +1,18 @@
+dwarfutils (20120410-2+deb8u1) stable; urgency=medium
+
+  * New maintainer.
+  * Add patch CVE-2015-8538.patch to fix CVE-2015-8538 (Closes: #807817).
+  * Add patch CVE-2015-8750.patch to fix CVE-2015-8750 (Closes: #813182).
+  * Add patch CVE-2016-2050.patch to fix CVE-2016-2050.
+  * Add patch CVE-2016-2091.patch to fix CVE-2016-2091 (Closes: #813148).
+  * Add patch CVE-2016-5034.patch to fix CVE-2016-5034.
+  * Add patch CVE-2016-5036.patch to fix CVE-2016-5036.
+  * Add patch CVE-2016-5038.patch to fix CVE-2016-5038.
+  * Add patch CVE-2016-5039.patch to fix CVE-2016-5039.
+  * Add patch CVE-2016-5042.patch to fix CVE-2016-5042.
+
+ -- Fabian Wolff <fabi.wo...@arcor.de>  Tue, 16 Aug 2016 15:27:35 +0200
+
 dwarfutils (20120410-2) unstable; urgency=low
 
   * Fix FTBFS on Debian GNU/Hurd by Barry deFreese <bdefre...@debian.org>
diff -u dwarfutils-20120410/debian/control dwarfutils-20120410/debian/control
--- dwarfutils-20120410/debian/control
+++ dwarfutils-20120410/debian/control
@@ -1,8 +1,7 @@
 Source: dwarfutils
 Section: libs
 Priority: optional
-Maintainer: Troy Heber <tr...@debian.org>
-Uploaders:
+Maintainer: Fabian Wolff <fabi.wo...@arcor.de>
 Build-Depends: debhelper (>> 9), quilt (>= 0.47), libelf-dev, binutils-dev
 Standards-Version: 3.9.3.1
 
diff -u dwarfutils-20120410/debian/patches/series 
dwarfutils-20120410/debian/patches/series
--- dwarfutils-20120410/debian/patches/series
+++ dwarfutils-20120410/debian/patches/series
@@ -2,0 +3,9 @@
+CVE-2016-5034.patch
+CVE-2016-2050.patch
+CVE-2015-8538.patch
+CVE-2015-8750.patch
+CVE-2016-2091.patch
+CVE-2016-5042.patch
+CVE-2016-5039.patch
+CVE-2016-5038.patch
+CVE-2016-5036.patch
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2015-8538.patch
+++ dwarfutils-20120410/debian/patches/CVE-2015-8538.patch
@@ -0,0 +1,340 @@
+Description: Fix for CVE-2015-8538 (OOB read)
+Origin: 
http://sourceforge.net/p/libdwarf/code/ci/da724a0bc5eec8e9ec0b0cb0c238a80e34466459/
+Bug-Debian: https://bugs.debian.org/807817
+
+--- a/libdwarf/dwarf_abbrev.c
++++ b/libdwarf/dwarf_abbrev.c
+@@ -126,6 +126,10 @@
+         attr = (Dwarf_Half) utmp2;
+         DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+         attr_form = (Dwarf_Half) utmp2;
++        if (!_dwarf_valid_form_we_know(dbg,attr_form,attr)) {
++            _dwarf_error(NULL, error, DW_DLE_UNKNOWN_FORM);
++            return DW_DLV_ERROR;
++        }
+ 
+         if (attr != 0)
+             (labbr_count)++;
+--- a/libdwarf/dwarf_die_deliv.c
++++ b/libdwarf/dwarf_die_deliv.c
+@@ -657,13 +657,15 @@
+     Dwarf_Byte_Ptr info_ptr = 0;
+     Dwarf_Byte_Ptr abbrev_ptr = 0;
+     Dwarf_Word abbrev_code = 0;
+-    Dwarf_Abbrev_List abbrev_list;
++    Dwarf_Abbrev_List abbrev_list = 0;
+     Dwarf_Half attr = 0;
+     Dwarf_Half attr_form = 0;
+     Dwarf_Unsigned offset = 0;
+     Dwarf_Word leb128_length = 0;
+     Dwarf_Unsigned utmp = 0;
+     Dwarf_Debug dbg = 0;
++    Dwarf_Error error = 0;
++    int lres = 0;
+ 
+     info_ptr = die_info_ptr;
+     DECODE_LEB128_UWORD(info_ptr, utmp);
+@@ -673,8 +675,8 @@
+     }
+ 
+ 
+-    abbrev_list = _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
+-    if (abbrev_list == NULL) {
++    lres = _dwarf_get_abbrev_for_code(cu_context, abbrev_code, &abbrev_list, 
&error);
++    if (lres == DW_DLV_ERROR || lres == DW_DLV_NO_ENTRY) {
+         return (NULL);
+     }
+     dbg = cu_context->cc_dbg;
+@@ -833,6 +835,7 @@
+     Dwarf_Byte_Ptr die_info_end = 0;
+     Dwarf_Word abbrev_code = 0;
+     Dwarf_Unsigned utmp = 0;
++    int lres = 0;
+     /* Since die may be NULL, we rely on the input argument. */
+     Dwarf_Debug_InfoTypes dis = is_info? &dbg->de_info_reading: 
+         &dbg->de_types_reading; 
+@@ -962,9 +965,13 @@
+         return (DW_DLV_NO_ENTRY);
+     }
+     ret_die->di_abbrev_code = abbrev_code;
+-    ret_die->di_abbrev_list =
+-        _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code);
+-    if (ret_die->di_abbrev_list == NULL ) {
++    lres = _dwarf_get_abbrev_for_code(ret_die->di_cu_context, abbrev_code,
++                                      &ret_die->di_abbrev_list, error);
++    if (lres == DW_DLV_ERROR) {
++        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
++        return lres;
++    }
++    if (lres == DW_DLV_NO_ENTRY) {
+         dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+         _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
+         return (DW_DLV_ERROR);
+@@ -1073,12 +1080,19 @@
+         return DW_DLV_NO_ENTRY;
+     }
+     ret_die->di_abbrev_code = abbrev_code;
+-    ret_die->di_abbrev_list =
+-        _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code);
+-    if (ret_die->di_abbrev_list == NULL) {
+-        dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
+-        _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+-        return (DW_DLV_ERROR);
++
++    {
++        int lres = _dwarf_get_abbrev_for_code(die->di_cu_context, abbrev_code,
++                                              &ret_die->di_abbrev_list, 
error);
++        if (lres == DW_DLV_ERROR) {
++            dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
++            return lres;
++        }
++        if (lres == DW_DLV_NO_ENTRY) {
++            dwarf_dealloc(dbg, ret_die, DW_DLA_DIE);
++            _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
++            return (DW_DLV_ERROR);
++        }
+     }
+ 
+     *caller_ret_die = ret_die;
+@@ -1111,6 +1125,7 @@
+     Dwarf_Byte_Ptr info_ptr = 0;
+     Dwarf_Unsigned abbrev_code = 0;
+     Dwarf_Unsigned utmp = 0;
++    int lres = 0;
+     Dwarf_Debug_InfoTypes dis = 0;
+ 
+ 
+@@ -1201,9 +1216,13 @@
+         return DW_DLV_NO_ENTRY;
+     }
+     die->di_abbrev_code = abbrev_code;
+-    die->di_abbrev_list =
+-        _dwarf_get_abbrev_for_code(cu_context, abbrev_code);
+-    if (die->di_abbrev_list == NULL) {
++    lres = _dwarf_get_abbrev_for_code(cu_context, abbrev_code,
++                                      &die->di_abbrev_list, error);
++    if (lres == DW_DLV_ERROR) {
++        dwarf_dealloc(dbg, die, DW_DLA_DIE);
++        return lres;
++    }
++    if (lres == DW_DLV_NO_ENTRY) {
+         dwarf_dealloc(dbg, die, DW_DLA_DIE);
+         _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_LIST_NULL);
+         return (DW_DLV_ERROR);
+--- a/libdwarf/dwarf_error.c
++++ b/libdwarf/dwarf_error.c
+@@ -328,6 +328,7 @@
+     "DW_DLE_DEBUG_TYPEOFFSET_BAD (239)",
+     "DW_DLE_GNU_OPCODE_ERROR (240)",
+     "DW_DLE_RELOC_INVALID (241)",
++    "DW_DLE_UNKNOWN_FORM (242) Possibly corrupt DWARF data",
+ };
+ 
+ 
+--- a/libdwarf/dwarf_query.c
++++ b/libdwarf/dwarf_query.c
+@@ -189,14 +189,19 @@
+     Dwarf_Attribute *attr_ptr = 0;
+     Dwarf_Debug dbg = 0;
+     Dwarf_Byte_Ptr info_ptr = 0;
++    int lres = 0;
+ 
+     CHECK_DIE(die, DW_DLV_ERROR);
+     dbg = die->di_cu_context->cc_dbg;
+ 
+-    abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context,
+-        die->di_abbrev_list->ab_code);
+-    if (abbrev_list == NULL) {
+-        _dwarf_error(dbg, error, DW_DLE_DIE_ABBREV_BAD);
++    lres = _dwarf_get_abbrev_for_code(die->di_cu_context,
++                                      die->di_abbrev_list->ab_code,
++                                      &abbrev_list,error);
++    if (lres == DW_DLV_ERROR) {
++        return lres;
++    }
++    if (lres == DW_DLV_NO_ENTRY) {
++        _dwarf_error(dbg, error, DW_DLE_DIE_BAD);
+         return (DW_DLV_ERROR);
+     }
+     abbrev_ptr = abbrev_list->ab_abbrev_ptr;
+@@ -211,6 +216,10 @@
+         attr = (Dwarf_Half) utmp2;
+         DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
+         attr_form = (Dwarf_Half) utmp2;
++        if (!_dwarf_valid_form_we_know(dbg,attr_form,attr)) {
++            _dwarf_error(dbg, error, DW_DLE_UNKNOWN_FORM);
++            return DW_DLV_ERROR;
++        }
+ 
+         if (attr != 0) {
+             new_attr =
+@@ -298,10 +307,14 @@
+     Dwarf_Half curr_attr = 0;
+     Dwarf_Half curr_attr_form = 0;
+     Dwarf_Byte_Ptr info_ptr = 0;
++    Dwarf_Error error = 0;
++    int lres = 0;
+ 
+-    abbrev_list = _dwarf_get_abbrev_for_code(die->di_cu_context,
+-        die->di_abbrev_list->ab_code);
+-    if (abbrev_list == NULL) {
++    lres = _dwarf_get_abbrev_for_code(die->di_cu_context,
++                                      die->di_abbrev_list->ab_code,
++                                      &abbrev_list,
++                                      &error);
++    if (lres == DW_DLV_NO_ENTRY || lres == DW_DLV_ERROR) {
+         *attr_form = 0;
+         return (NULL);
+     }
+--- a/libdwarf/dwarf_util.c
++++ b/libdwarf/dwarf_util.c
+@@ -222,6 +222,23 @@
+     }
+ }
+ 
++#define TRUE 1
++#define FALSE 0
++
++int _dwarf_valid_form_we_know (Dwarf_Debug dbg, Dwarf_Unsigned at_form, 
Dwarf_Unsigned at_name)
++{
++    if (at_form == 0 && at_name == 0) {
++        return TRUE;
++    }
++    if (at_name == 0) {
++        return FALSE;
++    }
++    if (at_form <= DW_FORM_ref_sig8) {
++        return TRUE;
++    }
++    return FALSE;
++}
++
+ /*  This function returns a pointer to a Dwarf_Abbrev_List_s
+     struct for the abbrev with the given code.  It puts the
+     struct on the appropriate hash table.  It also adds all
+@@ -247,8 +264,8 @@
+     never moves once allocated, so the pointer is safe to return.
+ 
+     Returns NULL on error.  */
+-Dwarf_Abbrev_List
+-_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned code)
++int _dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned 
code,
++                               Dwarf_Abbrev_List *list_out, Dwarf_Error 
*error)
+ {
+     Dwarf_Debug dbg = cu_context->cc_dbg;
+     Dwarf_Hash_Table hash_table_base = cu_context->cc_abbrev_hash_table;
+@@ -276,7 +293,7 @@
+             DW_DLA_HASH_TABLE_ENTRY, 
+             hash_table_base->tb_table_entry_count);
+         if(! hash_table_base->tb_entries) {
+-            return NULL;
++            return DW_DLV_NO_ENTRY;
+         }
+ 
+     } else if (hash_table_base->tb_total_abbrev_count >
+@@ -290,7 +307,7 @@
+             newht.tb_table_entry_count);
+ 
+         if(! newht.tb_entries) {
+-            return NULL;
++            return DW_DLV_NO_ENTRY;
+         }
+         /*  Copy the existing entries to the new table,
+             rehashing each.  */
+@@ -318,7 +335,8 @@
+     if (hash_abbrev_entry != NULL) {
+         /*  This returns a pointer to an abbrev list entry, not 
+             the list itself. */
+-        return (hash_abbrev_entry);
++        *list_out = hash_abbrev_entry;
++        return DW_DLV_OK;
+     }
+ 
+     abbrev_ptr = cu_context->cc_last_abbrev_ptr != NULL ?
+@@ -330,22 +348,23 @@
+     /*  End of abbrev's as we are past the end entirely.
+         THis can happen */
+     if (abbrev_ptr > end_abbrev_ptr) {
+-        return (NULL);
++        return DW_DLV_NO_ENTRY;
+     }
+     /*  End of abbrev's for this cu, since abbrev code is 0. */
+     if (*abbrev_ptr == 0) {
+-        return (NULL);
++        return DW_DLV_NO_ENTRY;
+     }
+ 
+     do {
+         unsigned new_hashable_val = 0;
+         DECODE_LEB128_UWORD(abbrev_ptr, abbrev_code);
+         DECODE_LEB128_UWORD(abbrev_ptr, abbrev_tag);
++        unsigned long abcount = 0;
+ 
+         inner_list_entry = (Dwarf_Abbrev_List)
+             _dwarf_get_alloc(cu_context->cc_dbg, DW_DLA_ABBREV_LIST, 1);
+         if (inner_list_entry == NULL) {
+-            return (NULL);
++            return DW_DLV_NO_ENTRY;
+         }
+ 
+         new_hashable_val = abbrev_code;
+@@ -363,11 +382,17 @@
+         inner_list_entry->ab_has_child = *(abbrev_ptr++);
+         inner_list_entry->ab_abbrev_ptr = abbrev_ptr;
+ 
++        hash_table_base->tb_total_abbrev_count++;
++
+         /*  Cycle thru the abbrev content, ignoring the content except
+             to find the end of the content. */
+         do {
+             DECODE_LEB128_UWORD(abbrev_ptr, attr_name);
+             DECODE_LEB128_UWORD(abbrev_ptr, attr_form);
++            if (!_dwarf_valid_form_we_know(dbg,attr_form,attr_name)) {
++                _dwarf_error(dbg,error,DW_DLE_UNKNOWN_FORM);
++                return DW_DLV_ERROR;
++            }
+         } while (attr_name != 0 && attr_form != 0);
+ 
+         /*  We may have fallen off the end of content,  that is not
+@@ -377,7 +402,11 @@
+         *abbrev_ptr != 0 && abbrev_code != code);
+ 
+     cu_context->cc_last_abbrev_ptr = abbrev_ptr;
+-    return (abbrev_code == code ? inner_list_entry : NULL);
++    if(abbrev_code == code) {
++        *list_out = inner_list_entry;
++        return DW_DLV_OK;
++    }
++    return DW_DLV_NO_ENTRY;
+ }
+ 
+ 
+--- a/libdwarf/dwarf_util.h
++++ b/libdwarf/dwarf_util.h
+@@ -300,9 +300,8 @@
+ 
+ 
+ 
+-Dwarf_Abbrev_List
+-_dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context,
+-    Dwarf_Unsigned code);
++int _dwarf_get_abbrev_for_code(Dwarf_CU_Context cu_context, Dwarf_Unsigned 
code,
++                               Dwarf_Abbrev_List *list_out, Dwarf_Error 
*error);
+ 
+ 
+ /* return 1 if string ends before 'endptr' else
+--- a/libdwarf/libdwarf.h
++++ b/libdwarf/libdwarf.h
+@@ -1062,10 +1062,11 @@
+ #define DW_DLE_DEBUG_TYPEOFFSET_BAD            239
+ #define DW_DLE_GNU_OPCODE_ERROR                240
+ #define DW_DLE_RELOC_INVALID                   241
++#define DW_DLE_UNKNOWN_FORM                    242
+ 
+ 
+     /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */
+-#define DW_DLE_LAST        241
++#define DW_DLE_LAST        242
+ #define DW_DLE_LO_USER     0x10000
+ 
+     /*  Taken as meaning 'undefined value', this is not
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2015-8750.patch
+++ dwarfutils-20120410/debian/patches/CVE-2015-8750.patch
@@ -0,0 +1,17 @@
+Description: Fix for CVE-2015-8750 (NULL dereference)
+Origin: 
https://github.com/tomhughes/libdwarf/commit/11750a2838e52953013e3114ef27b3c7b1780697
+Bug-Debian: https://bugs.debian.org/813182
+
+--- a/libdwarf/dwarf_elf_access.c
++++ b/libdwarf/dwarf_elf_access.c
+@@ -932,6 +932,10 @@
+             *error = DW_DLE_MDE;
+             return DW_DLV_ERROR;
+         }
++        if (!data->d_buf) {
++            *error = DW_DLE_MDE;
++            return DW_DLV_ERROR;
++        }
+         *section_data = data->d_buf;
+     }
+     return DW_DLV_OK;
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-2050.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-2050.patch
@@ -0,0 +1,14 @@
+Description: Fix for CVE-2016-2050 (OOB write in get_abbrev_array_info)
+Origin: 
https://sourceforge.net/p/libdwarf/code/ci/a05f5e2ae6a5f34daa566975894fc2803d6ec684
+
+--- a/dwarfdump/print_abbrevs.c
++++ b/dwarfdump/print_abbrevs.c
+@@ -252,7 +252,7 @@
+             } else {
+                 /* Valid abbreviation code */
+                 if (abbrev_code > 0) {
+-                    if (abbrev_code > abbrev_array_size) {
++                    while (abbrev_code > abbrev_array_size) {
+                         /* Resize abbreviation array */
+                         abbrev_array_size *= 2;
+                         abbrev_array = (Dwarf_Signed *)
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-2091.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-2091.patch
@@ -0,0 +1,33 @@
+Description: Fix for CVE-2016-2091
+ The dwarf_read_cie_fde_prefix function in dwarf_frame2.c in libdwarf
+ allows attackers to cause a denial of service (out-of-bounds read)
+ via a crafted ELF object file.
+Origin: 
https://sourceforge.net/p/libdwarf/code/ci/9565964f26966d8391fe2cfa8e6e8e59278c5f91
+Bug-Debian: https://bugs.debian.org/813148
+
+--- a/libdwarf/dwarf_frame2.c
++++ b/libdwarf/dwarf_frame2.c
+@@ -939,7 +939,12 @@
+     Dwarf_Small *frame_ptr = frame_ptr_in;
+     Dwarf_Small *cie_ptr_addr = 0;
+     Dwarf_Unsigned cie_id = 0;
++    Dwarf_Small *section_end = section_ptr_in + section_length_in;
+ 
++    if (section_end < (frame_ptr + 4)) {
++        _dwarf_error (dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
++        return DW_DLV_ERROR;
++    }
+     /* READ_AREA_LENGTH updates frame_ptr for consumed bytes */
+     READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+         frame_ptr, local_length_size,
+@@ -951,6 +956,10 @@
+             data. We should be very close to end of section. */
+         return DW_DLV_NO_ENTRY;
+     }
++    if ((frame_ptr + local_length_size) >= section_end) {
++        _dwarf_error (dbg, error, DW_DLE_DEBUG_FRAME_LENGTH_BAD);
++        return DW_DLV_ERROR;
++    }
+ 
+     cie_ptr_addr = frame_ptr;
+     READ_UNALIGNED(dbg, cie_id, Dwarf_Unsigned,
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-5034.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-5034.patch
@@ -0,0 +1,93 @@
+Description: Fix for CVE-2016-5034 (OOB write from relocation records)
+Origin: 
https://sourceforge.net/p/libdwarf/code/ci/10ca310f64368dc083efacac87732c02ef560a92
+
+--- a/libdwarf/dwarf_elf_access.c
++++ b/libdwarf/dwarf_elf_access.c
+@@ -617,7 +617,8 @@
+ update_entry(Dwarf_Debug dbg,
+     Dwarf_Bool is_64bit, Dwarf_Endianness endianess,
+     Dwarf_Half machine, struct Dwarf_Elf_Rela *rela,
+-    Dwarf_Small *target_section, 
++    Dwarf_Small *target_section,
++    Dwarf_Unsigned target_section_size,
+     Dwarf_Small *symtab_section_data,
+     Dwarf_Unsigned symtab_section_size, 
+     Dwarf_Unsigned symtab_section_entrysize,
+@@ -654,7 +655,10 @@
+         return DW_DLV_ERROR;
+     }
+     
+-    
++    if (offset >= target_section_size) {
++        *error = DW_DLE_RELOC_INVALID;
++        return DW_DLV_ERROR;
++    }
+ 
+     if (is_64bit) {
+ #ifdef HAVE_ELF64_SYM
+@@ -685,6 +689,14 @@
+         return DW_DLV_ERROR;
+     }
+ 
++    if ( (offset + reloc_size) < offset) {
++        *error = DW_DLE_RELOC_INVALID;
++        return DW_DLV_ERROR;
++    }
++    if ( (offset + reloc_size) > target_section_size) {
++        *error = DW_DLE_RELOC_INVALID;
++        return DW_DLV_ERROR;
++    }
+ 
+     {
+         /*  Assuming we do not need to do a READ_UNALIGNED here
+@@ -709,6 +721,7 @@
+     Dwarf_Endianness endianess,
+     Dwarf_Half machine,
+     Dwarf_Small *target_section,
++    Dwarf_Unsigned target_section_size,
+     Dwarf_Small *symtab_section,
+     Dwarf_Unsigned symtab_section_size,
+     Dwarf_Unsigned symtab_section_entrysize,
+@@ -732,6 +745,7 @@
+                 machine,
+                 &(relas)[i],
+                 target_section,
++                target_section_size,
+                 symtab_section,
+                 symtab_section_size,
+                 symtab_section_entrysize,
+@@ -796,7 +810,8 @@
+         dbg,
+         obj->is_64bit,
+         obj->endianness, obj->machine, 
+-        target_section, 
++        target_section,
++        relocatablesec->dss_size,
+         symtab_section,
+         symtab_section_size,
+         symtab_section_entrysize,
+--- a/libdwarf/libdwarf.h
++++ b/libdwarf/libdwarf.h
+@@ -1061,10 +1061,11 @@
+ #define DW_DLE_DEBUG_TYPES_ONLY_DWARF4         238
+ #define DW_DLE_DEBUG_TYPEOFFSET_BAD            239
+ #define DW_DLE_GNU_OPCODE_ERROR                240
++#define DW_DLE_RELOC_INVALID                   241
+ 
+ 
+     /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */
+-#define DW_DLE_LAST        239
++#define DW_DLE_LAST        241
+ #define DW_DLE_LO_USER     0x10000
+ 
+     /*  Taken as meaning 'undefined value', this is not
+--- a/libdwarf/dwarf_error.c
++++ b/libdwarf/dwarf_error.c
+@@ -327,6 +327,7 @@
+     "DW_DLE_DEBUG_TYPES_ONLY_DWARF4 (238)",
+     "DW_DLE_DEBUG_TYPEOFFSET_BAD (239)",
+     "DW_DLE_GNU_OPCODE_ERROR (240)",
++    "DW_DLE_RELOC_INVALID (241)",
+ };
+ 
+ 
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-5036.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-5036.patch
@@ -0,0 +1,15 @@
+Description: fix of CVE-2016-5036 (OOB read bug in dump_block)
+Author: Fabian Wolff <fabi.wo...@arcor.de>
+Origin: backport, 
https://sourceforge.net/p/libdwarf/code/ci/82d8e007851805af0dcaaff41f49a2d48473334b/
+
+--- a/dwarfdump2/dieholder.h
++++ b/dwarfdump2/dieholder.h
+@@ -45,7 +45,7 @@
+         (*refcount_)--;
+         if( (*refcount_) == 0) {
+             delete refcount_; 
+-            if(die_) dwarf_dealloc(dbg_,die_,DW_DLA_DIE);
++            //if(die_) dwarf_dealloc(dbg_,die_,DW_DLA_DIE);
+         }
+     };
+     DieHolder(const DieHolder & d):dbg_(d.dbg_),die_(d.die_),
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-5038.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-5038.patch
@@ -0,0 +1,208 @@
+Description: Fix for CVE-2016-5038 (OOB read in 
dwarf_get_macro_startend_file())
+Author: Fabian Wolff <fabi.wo...@arcor.de>
+Origin: backport, 
https://sourceforge.net/p/libdwarf/code/ci/82d8e007851805af0dcaaff41f49a2d48473334b/
+
+--- a/libdwarf/dwarf_die_deliv.c
++++ b/libdwarf/dwarf_die_deliv.c
+@@ -655,7 +655,7 @@
+     Dwarf_Bool * has_die_child)
+ {
+     Dwarf_Byte_Ptr info_ptr = 0;
+-    Dwarf_Byte_Ptr abbrev_ptr = 0;
++    Dwarf_Byte_Ptr abbrev_ptr = 0, abbrev_end = 0;
+     Dwarf_Word abbrev_code = 0;
+     Dwarf_Abbrev_List abbrev_list = 0;
+     Dwarf_Half attr = 0;
+@@ -684,12 +684,14 @@
+     *has_die_child = abbrev_list->ab_has_child;
+ 
+     abbrev_ptr = abbrev_list->ab_abbrev_ptr;
++    abbrev_end = (&dbg->de_debug_abbrev)->dss_data
++        + (&dbg->de_debug_abbrev)->dss_size;
+     do {
+         Dwarf_Unsigned utmp2;
+ 
+-        DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
++        DECODE_LEB128_UWORD_CK(abbrev_ptr, utmp2,dbg,&error,abbrev_end);
+         attr = (Dwarf_Half) utmp2;
+-        DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
++        DECODE_LEB128_UWORD_CK(abbrev_ptr, utmp2,dbg,&error,abbrev_end);
+         attr_form = (Dwarf_Half) utmp2;
+         if (attr_form == DW_FORM_indirect) {
+             Dwarf_Unsigned utmp6;
+@@ -1032,7 +1034,7 @@
+         _dwarf_next_die_info_ptr(die_info_ptr, die->di_cu_context,
+             die_info_end, NULL, false,
+             &has_die_child);
+-    if (die_info_ptr == NULL) {
++    if ((die_info_ptr == NULL) || (die_info_ptr == (void *) 1)) {
+         _dwarf_error(dbg, error, DW_DLE_NEXT_DIE_PTR_NULL);
+         return (DW_DLV_ERROR);
+     }
+--- a/libdwarf/dwarf_error.c
++++ b/libdwarf/dwarf_error.c
+@@ -332,6 +332,7 @@
+     "DW_DLE_READ_LITTLEENDIAN_ERROR (243)",
+     "DW_DLE_READ_BIGENDIAN_ERROR (244)",
+     "DW_DLE_ARANGES_HEADER_ERROR (245)",
++    "DW_DLE_LEB_IMPROPER (246)",
+ };
+ 
+ 
+--- a/libdwarf/dwarf_leb.c
++++ b/libdwarf/dwarf_leb.c
+@@ -108,6 +108,85 @@
+     }
+ }
+ 
++#define BYTESLEBMAX 10
++
++/* Decode ULEB with checking */
++int
++_dwarf_decode_u_leb128_chk(Dwarf_Small * leb128, Dwarf_Word * leb128_length,
++    Dwarf_Unsigned *outval,Dwarf_Byte_Ptr endptr)
++{
++    unsigned char byte     = 0;
++    Dwarf_Word word_number = 0;
++    Dwarf_Unsigned number  = 0;
++    Dwarf_Sword shift      = 0;
++    /*  The byte_length value will be a small non-negative integer. */
++    unsigned byte_length   = 0;
++
++    if (leb128 >=endptr) {
++        return DW_DLV_ERROR;
++    }
++    /*  The following unrolls-the-loop for the first two bytes and
++        unpacks into 32 bits to make this as fast as possible.
++        word_number is assumed big enough that the shift has a defined
++        result. */
++    if ((*leb128 & 0x80) == 0) {
++        if (leb128_length) {
++            *leb128_length = 1;
++        }
++        *outval = *leb128;
++        return DW_DLV_OK;
++    } else {
++        if ((leb128+1) >=endptr) {
++            return DW_DLV_ERROR;
++        }
++        if ((*(leb128 + 1) & 0x80) == 0) {
++            if (leb128_length) {
++                *leb128_length = 2;
++            }
++            word_number = *leb128 & 0x7f;
++            word_number |= (*(leb128 + 1) & 0x7f) << 7;
++            *outval = word_number;
++            return DW_DLV_OK;
++        }
++        /* Gets messy to hand-inline more byte checking. */
++    }
++
++    /*  The rest handles long numbers Because the 'number' may be larger
++        than the default int/unsigned, we must cast the 'byte' before
++        the shift for the shift to have a defined result. */
++    number = 0;
++    shift = 0;
++    byte_length = 1;
++    byte = *leb128;
++    for (;;) {
++        number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift;
++
++        if ((byte & 0x80) == 0) {
++            if (leb128_length) {
++                *leb128_length = byte_length;
++            }
++            *outval = number;
++            return DW_DLV_OK;
++        }
++        shift += 7;
++
++        byte_length++;
++        if (byte_length > BYTESLEBMAX) {
++            /*  Erroneous input.  */
++            if( leb128_length) {
++                *leb128_length = BYTESLEBMAX;
++            }
++            break;
++        }
++        ++leb128;
++        if ((leb128) >=endptr) {
++            return DW_DLV_ERROR;
++        }
++        byte = *leb128;
++    }
++    return DW_DLV_ERROR;
++}
++
+ #define BITSINBYTE 8
+ 
+ /*  decode SLEB */
+--- a/libdwarf/dwarf_util.h
++++ b/libdwarf/dwarf_util.h
+@@ -43,7 +43,19 @@
+ */
+ 
+ 
+-
++#define DECODE_LEB128_UWORD_CK(ptr, value,dbg,errptr,endptr) \
++    do {                                                     \
++        Dwarf_Word lu_leblen = 0;                            \
++        Dwarf_Unsigned lu_local = 0;                         \
++        int lu_res = 0;                                      \
++        lu_res = _dwarf_decode_u_leb128_chk(ptr,&lu_leblen,&lu_local,endptr); 
\
++        if (lu_res == DW_DLV_ERROR) {                        \
++            _dwarf_error(dbg, errptr, DW_DLE_LEB_IMPROPER);  \
++            return DW_DLV_ERROR;                             \
++        }                                                    \
++        value = lu_local;                                    \
++        ptr += lu_leblen;                                    \
++    } while (0)
+ 
+ /*
+     Decodes unsigned leb128 encoded numbers.
+--- a/libdwarf/libdwarf.h
++++ b/libdwarf/libdwarf.h
+@@ -1066,10 +1066,11 @@
+ #define DW_DLE_READ_LITTLEENDIAN_ERROR         243
+ #define DW_DLE_READ_BIGENDIAN_ERROR            244
+ #define DW_DLE_ARANGES_HEADER_ERROR            245
++#define DW_DLE_LEB_IMPROPER                    246
+ 
+ 
+     /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */
+-#define DW_DLE_LAST        245
++#define DW_DLE_LAST        246
+ #define DW_DLE_LO_USER     0x10000
+ 
+     /*  Taken as meaning 'undefined value', this is not
+--- a/libdwarf/dwarf_query.c
++++ b/libdwarf/dwarf_query.c
+@@ -181,7 +181,7 @@
+     Dwarf_Word i = 0;
+     Dwarf_Half attr = 0;
+     Dwarf_Half attr_form = 0;
+-    Dwarf_Byte_Ptr abbrev_ptr = 0;
++    Dwarf_Byte_Ptr abbrev_ptr = 0, abbrev_end = 0;
+     Dwarf_Abbrev_List abbrev_list = 0;
+     Dwarf_Attribute new_attr = 0;
+     Dwarf_Attribute head_attr = NULL;
+@@ -205,6 +205,7 @@
+         return (DW_DLV_ERROR);
+     }
+     abbrev_ptr = abbrev_list->ab_abbrev_ptr;
++    abbrev_end = (&dbg->de_debug_abbrev)->dss_data + 
(&dbg->de_debug_abbrev)->dss_size;
+ 
+     info_ptr = die->di_debug_ptr;
+     SKIP_LEB128_WORD(info_ptr);
+@@ -212,9 +213,9 @@
+     do {
+         Dwarf_Unsigned utmp2;
+ 
+-        DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
++        DECODE_LEB128_UWORD_CK(abbrev_ptr, utmp2,dbg,error,abbrev_end);
+         attr = (Dwarf_Half) utmp2;
+-        DECODE_LEB128_UWORD(abbrev_ptr, utmp2);
++        DECODE_LEB128_UWORD_CK(abbrev_ptr, utmp2,dbg,error,abbrev_end);
+         attr_form = (Dwarf_Half) utmp2;
+         if (!_dwarf_valid_form_we_know(dbg,attr_form,attr)) {
+             _dwarf_error(dbg, error, DW_DLE_UNKNOWN_FORM);
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-5039.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-5039.patch
@@ -0,0 +1,43 @@
+Description: Fix for CVE-2016-5039 (OOB read bug in get_attr_value())
+Author: Fabian Wolff <fabi.wo...@arcor.de>
+Origin: backport, 
https://sourceforge.net/p/libdwarf/code/ci/eb1472afac95031d0c9dd8c11d527b865fe7deb8/
+
+--- a/libdwarf/dwarf_form.c
++++ b/libdwarf/dwarf_form.c
+@@ -766,10 +766,17 @@
+     Dwarf_Word leb128_length = 0;
+     Dwarf_Block *ret_block = 0;
+ 
++    Dwarf_Unsigned section_length = 0;
++
+     int res  = get_attr_dbg(&dbg,&cu_context,attr,error);
+     if(res != DW_DLV_OK) { 
+         return res;
+-    } 
++    }
++
++    section_length = (cu_context->cc_is_info
++                      ? (&dbg->de_debug_info)
++                      : (&dbg->de_debug_types))->dss_size;
++
+     switch (attr->ar_attribute_form) {
+ 
+     case DW_FORM_block1:
+@@ -801,11 +808,12 @@
+     }
+ 
+     /* Check that block lies within current cu in .debug_info. */
+-    if (attr->ar_debug_ptr + length >=
+-        dbg->de_debug_info.dss_data + cu_context->cc_debug_offset +
+-        cu_context->cc_length + cu_context->cc_length_size +
+-        cu_context->cc_extension_size) {
+-        _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
++    if ((attr->ar_debug_ptr + length >=
++         dbg->de_debug_info.dss_data + cu_context->cc_debug_offset +
++         cu_context->cc_length + cu_context->cc_length_size +
++         cu_context->cc_extension_size)
++        || (length >= section_length)) {
++            _dwarf_error(dbg, error, DW_DLE_ATTR_FORM_SIZE_BAD);
+         return (DW_DLV_ERROR);
+     }
+ 
only in patch2:
unchanged:
--- dwarfutils-20120410.orig/debian/patches/CVE-2016-5042.patch
+++ dwarfutils-20120410/debian/patches/CVE-2016-5042.patch
@@ -0,0 +1,155 @@
+Description: Fix for CVE-2016-5042
+ In dwarf_get_aranges_list() an invalid count will iterate, reading
+ from memory addresses that increase till it all fails.
+Origin: backport, 
https://sourceforge.net/p/libdwarf/code/ci/98a3da1e8237fe0d45b67ef77f3fa5ed9ff0215f
+
+--- a/libdwarf/dwarf_arange.c
++++ b/libdwarf/dwarf_arange.c
+@@ -102,13 +102,12 @@
+         /* Length of current set of aranges. */
+         Dwarf_Unsigned length = 0;
+         Dwarf_Small remainder = 0;
+-        Dwarf_Small *arange_ptr_past_end = 0;
+         Dwarf_Unsigned range_entry_size = 0;
+-
+         int local_length_size;
+ 
+         /*REFERENCED*/ /* Not used in this instance of the macro */
+         int local_extension_size = 0;
++        Dwarf_Small *end_this_arange = 0;
+ 
+         header_ptr = arange_ptr;
+ 
+@@ -116,11 +115,19 @@
+         READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
+             arange_ptr, local_length_size,
+             local_extension_size);
+-        arange_ptr_past_end = arange_ptr + length;
++
++        if ((length + local_length_size + local_extension_size) >
++            dbg->de_debug_aranges.dss_size) {
++            _dwarf_error(dbg, error, DW_DLE_ARANGES_HEADER_ERROR);
++            return DW_DLV_ERROR;
++        }
++
++        end_this_arange = arange_ptr + length;
+ 
+ 
+-        READ_UNALIGNED(dbg, version, Dwarf_Half,
+-            arange_ptr, sizeof(Dwarf_Half));
++        READ_UNALIGNED_CK(dbg, version, Dwarf_Half,
++                          arange_ptr, sizeof(Dwarf_Half),
++                          error,end_this_arange);
+         arange_ptr += sizeof(Dwarf_Half);
+         length = length - sizeof(Dwarf_Half);
+         if (version != CURRENT_VERSION_STAMP) {
+@@ -128,8 +135,9 @@
+             return (DW_DLV_ERROR);
+         }
+ 
+-        READ_UNALIGNED(dbg, info_offset, Dwarf_Off,
+-            arange_ptr, local_length_size);
++        READ_UNALIGNED_CK(dbg, info_offset, Dwarf_Off,
++                          arange_ptr, local_length_size,
++                          error, end_this_arange);
+         arange_ptr += local_length_size;
+         length = length - local_length_size;
+         /* This applies to debug_info only, not to debug_types. */
+@@ -243,14 +251,14 @@
+                 DWARF2,3,4 section 7.20 
+                 We stop short to avoid overrun of the end of the CU.  */
+               
+-        } while (arange_ptr_past_end >= (arange_ptr + range_entry_size));
++        } while (end_this_arange >= (arange_ptr + range_entry_size));
+ 
+         /*  A compiler could emit some padding bytes here. dwarf2/3
+             (dwarf4 sec 7.20) does not clearly make extra padding 
+             bytes illegal. */
+-        if (arange_ptr_past_end < arange_ptr) {
++        if (end_this_arange < arange_ptr) {
+             char buf[200];
+-            Dwarf_Unsigned pad_count = arange_ptr - arange_ptr_past_end;
++            Dwarf_Unsigned pad_count = arange_ptr - end_this_arange;
+             Dwarf_Unsigned offset = arange_ptr - arange_ptr_start;
+             snprintf(buf,sizeof(buf),"DW_DLE_ARANGE_LENGTH_BAD."
+                 " 0x%" DW_PR_XZEROS DW_PR_DUx 
+@@ -259,9 +267,9 @@
+                 pad_count, offset);
+             dwarf_insert_harmless_error(dbg,buf);
+         }
+-        /*  For most compilers, arange_ptr == arange_ptr_past_end at
++        /*  For most compilers, arange_ptr == end_this_arange at
+             this point. But not if there were padding bytes */
+-        arange_ptr = arange_ptr_past_end;
++        arange_ptr = end_this_arange;
+     } while (arange_ptr <
+         dbg->de_debug_aranges.dss_data + dbg->de_debug_aranges.dss_size);
+ 
+--- a/libdwarf/dwarf_error.c
++++ b/libdwarf/dwarf_error.c
+@@ -329,6 +329,9 @@
+     "DW_DLE_GNU_OPCODE_ERROR (240)",
+     "DW_DLE_RELOC_INVALID (241)",
+     "DW_DLE_UNKNOWN_FORM (242) Possibly corrupt DWARF data",
++    "DW_DLE_READ_LITTLEENDIAN_ERROR (243)",
++    "DW_DLE_READ_BIGENDIAN_ERROR (244)",
++    "DW_DLE_ARANGES_HEADER_ERROR (245)",
+ };
+ 
+ 
+--- a/libdwarf/dwarf_util.h
++++ b/libdwarf/dwarf_util.h
+@@ -130,6 +130,18 @@
+         dest = (desttype)_ltmp;  \
+     } while (0)
+ 
++#define READ_UNALIGNED_CK(dbg,dest,desttype, source, length,error,endptr) \
++    do {                                                                  \
++        BIGGEST_UINT _ltmp = 0;                                           \
++        Dwarf_Byte_Ptr readend = source+length;                           \
++        if (readend > endptr) {                                           \
++            _dwarf_error(dbg, error, DW_DLE_READ_LITTLEENDIAN_ERROR);     \
++            return DW_DLV_ERROR;                                          \
++        }                                                                 \
++        dbg->de_copy_word( (((char *)(&_ltmp)) + sizeof(_ltmp) - length), \
++                           source, length);                               \
++        dest = (desttype)_ltmp;                                           \
++    } while (0)
+ 
+ /*
+     This macro sign-extends a variable depending on the length.
+@@ -155,6 +167,17 @@
+         dest = (desttype)_ltmp;               \
+     } while (0)
+ 
++#define READ_UNALIGNED_CK(dbg,dest,desttype, source, length,error,endptr) \
++    do {                                                                  \
++        BIGGEST_UINT _ltmp = 0;                                           \
++        Dwarf_Byte_Ptr readend = source+length;                           \
++        if (readend > endptr) {                                           \
++            _dwarf_error(dbg, error, DW_DLE_READ_BIGENDIAN_ERROR);        \
++            return DW_DLV_ERROR;                                          \
++        }                                                                 \
++        dbg->de_copy_word( (char *)(&_ltmp), source, length);             \
++        dest = (desttype)_ltmp;                                           \
++    } while (0)
+ 
+ /*
+     This macro sign-extends a variable depending on the length.
+--- a/libdwarf/libdwarf.h
++++ b/libdwarf/libdwarf.h
+@@ -1063,10 +1063,13 @@
+ #define DW_DLE_GNU_OPCODE_ERROR                240
+ #define DW_DLE_RELOC_INVALID                   241
+ #define DW_DLE_UNKNOWN_FORM                    242
++#define DW_DLE_READ_LITTLEENDIAN_ERROR         243
++#define DW_DLE_READ_BIGENDIAN_ERROR            244
++#define DW_DLE_ARANGES_HEADER_ERROR            245
+ 
+ 
+     /* DW_DLE_LAST MUST EQUAL LAST ERROR NUMBER */
+-#define DW_DLE_LAST        242
++#define DW_DLE_LAST        245
+ #define DW_DLE_LO_USER     0x10000
+ 
+     /*  Taken as meaning 'undefined value', this is not

Attachment: signature.asc
Description: PGP signature

Reply via email to