binutils: CVE-2017-15024

Source: binutils-gdb.git
MR: 76524
Type: Security Fix
Disposition: Backport from binutils master
ChangeID: 5f22a66eabb228b655605b964ecd350aee700806
Description:

    PR22187, infinite loop in find_abstract_instance_name

    This patch prevents the simple case of infinite recursion in
    find_abstract_instance_name by ensuring that the attributes being
    processed are not the same as the previous call.

    The patch also does a little cleanup, and leaves in place some changes
    to the nested_funcs array that I made when I wrongly thought looping
    might occur in scan_unit_for_symbols.

        PR 22187
        * dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
        pname param.  Return status.  Make name const.  Don't abort,
        return an error.  Formatting.  Exit if current info_ptr matches
        orig_info_ptr.  Update callers.
        (scan_unit_for_symbols): Start at nesting_level of zero.  Make
        nested_funcs an array of structs for extensibility.  Formatting.

Affects: <= 2.29
(From OE-Core rev: 3e88bb5e933ebbf9c3445bac1814dc0ac105bf45)

Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com>
Reviewed-by: Armin Kuster <akuster@mvista.com>
Signed-off-by: Armin Kuster <akuster@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Thiruvadi Rajaraman
2017-11-08 13:41:00 +05:30
committed by Richard Purdie
parent 05281ec4a6
commit 7006ecaba3
2 changed files with 242 additions and 0 deletions

View File

@@ -101,6 +101,7 @@ SRC_URI = "\
file://CVE-2017-9955_8.patch \
file://CVE-2017-9955_9.patch \
file://CVE-2017-14729.patch \
file://CVE-2017-15024.patch \
"
S = "${WORKDIR}/git"

View File

@@ -0,0 +1,241 @@
commit 52a93b95ec0771c97e26f0bb28630a271a667bd2
Author: Alan Modra <amodra@gmail.com>
Date: Sun Sep 24 14:37:16 2017 +0930
PR22187, infinite loop in find_abstract_instance_name
This patch prevents the simple case of infinite recursion in
find_abstract_instance_name by ensuring that the attributes being
processed are not the same as the previous call.
The patch also does a little cleanup, and leaves in place some changes
to the nested_funcs array that I made when I wrongly thought looping
might occur in scan_unit_for_symbols.
PR 22187
* dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
pname param. Return status. Make name const. Don't abort,
return an error. Formatting. Exit if current info_ptr matches
orig_info_ptr. Update callers.
(scan_unit_for_symbols): Start at nesting_level of zero. Make
nested_funcs an array of structs for extensibility. Formatting.
Upstream-Status: Backport
CVE: CVE-2017-15024
Signed-off-by: Thiruvadi Rajaraman <trajaraman@mvista.com>
Index: git/bfd/dwarf2.c
===================================================================
--- git.orig/bfd/dwarf2.c 2017-11-08 12:44:59.198052588 +0530
+++ git/bfd/dwarf2.c 2017-11-08 12:45:10.670155730 +0530
@@ -2273,9 +2273,11 @@
return FALSE;
}
-static char *
+static bfd_boolean
find_abstract_instance_name (struct comp_unit *unit,
+ bfd_byte *orig_info_ptr,
struct attribute *attr_ptr,
+ const char **pname,
bfd_boolean *is_linkage)
{
bfd *abfd = unit->abfd;
@@ -2285,7 +2287,7 @@
struct abbrev_info *abbrev;
bfd_uint64_t die_ref = attr_ptr->u.val;
struct attribute attr;
- char *name = NULL;
+ const char *name = NULL;
/* DW_FORM_ref_addr can reference an entry in a different CU. It
is an offset from the .debug_info section, not the current CU. */
@@ -2294,7 +2296,12 @@
/* We only support DW_FORM_ref_addr within the same file, so
any relocations should be resolved already. */
if (!die_ref)
- abort ();
+ {
+ _bfd_error_handler
+ (_("Dwarf Error: Abstract instance DIE ref zero."));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
info_ptr = unit->sec_info_ptr + die_ref;
info_ptr_end = unit->end_ptr;
@@ -2329,9 +2336,10 @@
(*_bfd_error_handler)
(_("Dwarf Error: Unable to read alt ref %u."), die_ref);
bfd_set_error (bfd_error_bad_value);
- return NULL;
+ return FALSE;
}
- info_ptr_end = unit->stash->alt_dwarf_info_buffer + unit->stash->alt_dwarf_info_size;
+ info_ptr_end = (unit->stash->alt_dwarf_info_buffer
+ + unit->stash->alt_dwarf_info_size);
/* FIXME: Do we need to locate the correct CU, in a similar
fashion to the code in the DW_FORM_ref_addr case above ? */
@@ -2353,6 +2361,7 @@
(*_bfd_error_handler)
(_("Dwarf Error: Could not find abbrev number %u."), abbrev_number);
bfd_set_error (bfd_error_bad_value);
+ return FALSE;
}
else
{
@@ -2362,6 +2371,15 @@
info_ptr, info_ptr_end);
if (info_ptr == NULL)
break;
+ /* It doesn't ever make sense for DW_AT_specification to
+ refer to the same DIE. Stop simple recursion. */
+ if (info_ptr == orig_info_ptr)
+ {
+ _bfd_error_handler
+ (_("Dwarf Error: Abstract instance recursion detected."));
+ bfd_set_error (bfd_error_bad_value);
+ return FALSE;
+ }
switch (attr.name)
{
case DW_AT_name:
@@ -2375,7 +2393,9 @@
}
break;
case DW_AT_specification:
- name = find_abstract_instance_name (unit, &attr, is_linkage);
+ if (!find_abstract_instance_name (unit, info_ptr, &attr,
+ pname, is_linkage))
+ return FALSE;
break;
case DW_AT_linkage_name:
case DW_AT_MIPS_linkage_name:
@@ -2393,7 +2413,8 @@
}
}
}
- return name;
+ *pname = name;
+ return TRUE;
}
static bfd_boolean
@@ -2454,20 +2475,22 @@
bfd *abfd = unit->abfd;
bfd_byte *info_ptr = unit->first_child_die_ptr;
bfd_byte *info_ptr_end = unit->stash->info_ptr_end;
- int nesting_level = 1;
- struct funcinfo **nested_funcs;
+ int nesting_level = 0;
+ struct nest_funcinfo {
+ struct funcinfo *func;
+ } *nested_funcs;
int nested_funcs_size;
/* Maintain a stack of in-scope functions and inlined functions, which we
can use to set the caller_func field. */
nested_funcs_size = 32;
- nested_funcs = (struct funcinfo **)
- bfd_malloc (nested_funcs_size * sizeof (struct funcinfo *));
+ nested_funcs = (struct nest_funcinfo *)
+ bfd_malloc (nested_funcs_size * sizeof (*nested_funcs));
if (nested_funcs == NULL)
return FALSE;
- nested_funcs[nesting_level] = 0;
+ nested_funcs[nesting_level].func = 0;
- while (nesting_level)
+ while (nesting_level >= 0)
{
unsigned int abbrev_number, bytes_read, i;
struct abbrev_info *abbrev;
@@ -2516,13 +2539,13 @@
BFD_ASSERT (!unit->cached);
if (func->tag == DW_TAG_inlined_subroutine)
- for (i = nesting_level - 1; i >= 1; i--)
- if (nested_funcs[i])
+ for (i = nesting_level; i-- != 0; )
+ if (nested_funcs[i].func)
{
- func->caller_func = nested_funcs[i];
+ func->caller_func = nested_funcs[i].func;
break;
}
- nested_funcs[nesting_level] = func;
+ nested_funcs[nesting_level].func = func;
}
else
{
@@ -2541,12 +2564,13 @@
}
/* No inline function in scope at this nesting level. */
- nested_funcs[nesting_level] = 0;
+ nested_funcs[nesting_level].func = 0;
}
for (i = 0; i < abbrev->num_attrs; ++i)
{
- info_ptr = read_attribute (&attr, &abbrev->attrs[i], unit, info_ptr, info_ptr_end);
+ info_ptr = read_attribute (&attr, &abbrev->attrs[i],
+ unit, info_ptr, info_ptr_end);
if (info_ptr == NULL)
goto fail;
@@ -2565,8 +2589,10 @@
case DW_AT_abstract_origin:
case DW_AT_specification:
- func->name = find_abstract_instance_name (unit, &attr,
- &func->is_linkage);
+ if (!find_abstract_instance_name (unit, info_ptr, &attr,
+ &func->name,
+ &func->is_linkage))
+ goto fail;
break;
case DW_AT_name:
@@ -2691,17 +2717,17 @@
if (nesting_level >= nested_funcs_size)
{
- struct funcinfo **tmp;
+ struct nest_funcinfo *tmp;
nested_funcs_size *= 2;
- tmp = (struct funcinfo **)
+ tmp = (struct nest_funcinfo *)
bfd_realloc (nested_funcs,
- nested_funcs_size * sizeof (struct funcinfo *));
+ nested_funcs_size * sizeof (*nested_funcs));
if (tmp == NULL)
goto fail;
nested_funcs = tmp;
}
- nested_funcs[nesting_level] = 0;
+ nested_funcs[nesting_level].func = 0;
}
}
Index: git/bfd/ChangeLog
===================================================================
--- git.orig/bfd/ChangeLog 2017-11-08 12:45:10.614155229 +0530
+++ git/bfd/ChangeLog 2017-11-08 12:46:55.791054918 +0530
@@ -1,3 +1,13 @@
+2017-09-24 Alan Modra <amodra@gmail.com>
+
+ PR 22187
+ * dwarf2.c (find_abstract_instance_name): Add orig_info_ptr and
+ pname param. Return status. Make name const. Don't abort,
+ return an error. Formatting. Exit if current info_ptr matches
+ orig_info_ptr. Update callers.
+ (scan_unit_for_symbols): Start at nesting_level of zero. Make
+ nested_funcs an array of structs for extensibility. Formatting.
+
2017-09-22 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/22170