From: Nick Clifton Date: Wed, 20 Feb 2019 17:51:21 +0000 (+0000) Subject: Fix potential illegal memory access by readelf when parsing a binary containing corru... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=3ca60c57a715bbefc091949dd2381bab1b124715;p=binutils-gdb.git Fix potential illegal memory access by readelf when parsing a binary containing corrupt system tap notes. PR 24246 * readelf.c (print_stapsdt_note): Harden against corrupt notes. --- diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 8c08a8eb7f7..4d7712075f1 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,8 @@ 2019-02-20 Nick Clifton + PR 24246 + * readelf.c (print_stapsdt_note): Harden against corrupt notes. + PR 24244 * unwind-ia64.c (unw_decode_uleb128): Add end parameter, use it to prevent walking off the end of the buffer. diff --git a/binutils/readelf.c b/binutils/readelf.c index 20ebacc9cbd..0e3e43cc8ed 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -17868,25 +17868,60 @@ get_stapsdt_note_type (unsigned e_type) static bfd_boolean print_stapsdt_note (Elf_Internal_Note *pnote) { - int addr_size = is_32bit_elf ? 4 : 8; + size_t len, maxlen; + unsigned long addr_size = is_32bit_elf ? 4 : 8; char *data = pnote->descdata; char *data_end = pnote->descdata + pnote->descsz; bfd_vma pc, base_addr, semaphore; char *provider, *probe, *arg_fmt; + if (pnote->descsz < (addr_size * 3)) + goto stapdt_note_too_small; + pc = byte_get ((unsigned char *) data, addr_size); data += addr_size; + base_addr = byte_get ((unsigned char *) data, addr_size); data += addr_size; + semaphore = byte_get ((unsigned char *) data, addr_size); data += addr_size; - provider = data; - data += strlen (data) + 1; - probe = data; - data += strlen (data) + 1; - arg_fmt = data; - data += strlen (data) + 1; + if (data >= data_end) + goto stapdt_note_too_small; + maxlen = data_end - data; + len = strnlen (data, maxlen); + if (len < maxlen) + { + provider = data; + data += len + 1; + } + else + goto stapdt_note_too_small; + + if (data >= data_end) + goto stapdt_note_too_small; + maxlen = data_end - data; + len = strnlen (data, maxlen); + if (len < maxlen) + { + probe = data; + data += len + 1; + } + else + goto stapdt_note_too_small; + + if (data >= data_end) + goto stapdt_note_too_small; + maxlen = data_end - data; + len = strnlen (data, maxlen); + if (len < maxlen) + { + arg_fmt = data; + data += len + 1; + } + else + goto stapdt_note_too_small; printf (_(" Provider: %s\n"), provider); printf (_(" Name: %s\n"), probe); @@ -17900,6 +17935,11 @@ print_stapsdt_note (Elf_Internal_Note *pnote) printf (_(" Arguments: %s\n"), arg_fmt); return data == data_end; + + stapdt_note_too_small: + printf (_(" \n")); + error (_("corrupt stapdt note - the data size is too small\n")); + return FALSE; } static const char *