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
signature.asc
Description: PGP signature