diff options
author | Nick Clifton <nickc@redhat.com> | 2019-02-20 17:51:21 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2019-02-20 17:51:21 +0000 |
commit | 3ca60c57a715bbefc091949dd2381bab1b124715 (patch) | |
tree | 6bd9d7bf0bd830bd680d4bd90b80e301330cb034 /binutils | |
parent | 171375c68e809e97b5653ef424f80d46956a50e8 (diff) | |
download | gdb-3ca60c57a715bbefc091949dd2381bab1b124715.zip gdb-3ca60c57a715bbefc091949dd2381bab1b124715.tar.gz gdb-3ca60c57a715bbefc091949dd2381bab1b124715.tar.bz2 |
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.
Diffstat (limited to 'binutils')
-rw-r--r-- | binutils/ChangeLog | 3 | ||||
-rw-r--r-- | binutils/readelf.c | 54 |
2 files changed, 50 insertions, 7 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 8c08a8e..4d77120 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,5 +1,8 @@ 2019-02-20 Nick Clifton <nickc@redhat.com> + 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 20ebacc..0e3e43c 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 (_(" <corrupt - note is too small>\n")); + error (_("corrupt stapdt note - the data size is too small\n")); + return FALSE; } static const char * |