From bf59c5d5f4f5b8b4da1f5f605cfa546f8029b43d Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 3 Nov 2017 13:57:15 +0000 Subject: [PATCH] Fix integer overflow problems when reading an ELF binary with corrupt augmentation data. PR 22386 * dwarf.c (read_cie): Use bfd_size_type for augmentation_data_len. (display_augmentation_data): New function. (display_debug_frames): Use it. Check for integer overflow when testing augmentation_data_len. Upstream-Status: Backport Affects: <= 2.29.1 CVE: CVE-2017-16828 patch2 Signed-off-by: Armin Kuster --- binutils/ChangeLog | 10 +++++++++ binutils/dwarf.c | 65 +++++++++++++++++++++++++++++++++--------------------- 2 files changed, 50 insertions(+), 25 deletions(-) Index: git/binutils/dwarf.c =================================================================== --- git.orig/binutils/dwarf.c +++ git/binutils/dwarf.c @@ -6577,13 +6577,13 @@ frame_display_row (Frame_Chunk *fc, int static unsigned char * read_cie (unsigned char *start, unsigned char *end, Frame_Chunk **p_cie, int *p_version, - unsigned long *p_aug_len, unsigned char **p_aug) + bfd_size_type *p_aug_len, unsigned char **p_aug) { int version; Frame_Chunk *fc; unsigned int length_return; unsigned char *augmentation_data = NULL; - unsigned long augmentation_data_len = 0; + bfd_size_type augmentation_data_len = 0; * p_cie = NULL; /* PR 17512: file: 001-228113-0.004. */ @@ -6653,10 +6653,11 @@ read_cie (unsigned char *start, unsigned READ_ULEB (augmentation_data_len); augmentation_data = start; /* PR 17512: file: 11042-2589-0.004. */ - if (augmentation_data_len > (size_t) (end - start)) + if (augmentation_data_len > (bfd_size_type) (end - start)) { - warn (_("Augmentation data too long: %#lx, expected at most %#lx\n"), - augmentation_data_len, (unsigned long) (end - start)); + warn (_("Augmentation data too long: 0x%s, expected at most %#lx\n"), + dwarf_vmatoa ("x", augmentation_data_len), + (unsigned long) (end - start)); return end; } start += augmentation_data_len; @@ -6701,6 +6702,31 @@ read_cie (unsigned char *start, unsigned return start; } +/* Prints out the contents on the augmentation data array. + If do_wide is not enabled, then formats the output to fit into 80 columns. */ + +static void +display_augmentation_data (const unsigned char * data, const bfd_size_type len) +{ + bfd_size_type i; + + i = printf (_(" Augmentation data: ")); + + if (do_wide || len < ((80 - i) / 3)) + for (i = 0; i < len; ++i) + printf (" %02x", data[i]); + else + { + for (i = 0; i < len; ++i) + { + if (i % (80 / 3) == 0) + putchar ('\n'); + printf (" %02x", data[i]); + } + } + putchar ('\n'); +} + static int display_debug_frames (struct dwarf_section *section, void *file ATTRIBUTE_UNUSED) @@ -6729,7 +6755,7 @@ display_debug_frames (struct dwarf_secti Frame_Chunk *cie; int need_col_headers = 1; unsigned char *augmentation_data = NULL; - unsigned long augmentation_data_len = 0; + bfd_size_type augmentation_data_len = 0; unsigned int encoded_ptr_size = saved_eh_addr_size; unsigned int offset_size; unsigned int initial_length_size; @@ -6823,16 +6849,8 @@ display_debug_frames (struct dwarf_secti printf (" Return address column: %d\n", fc->ra); if (augmentation_data_len) - { - unsigned long i; + display_augmentation_data (augmentation_data, augmentation_data_len); - printf (" Augmentation data: "); - for (i = 0; i < augmentation_data_len; ++i) - /* FIXME: If do_wide is FALSE, then we should - add carriage returns at 80 columns... */ - printf (" %02x", augmentation_data[i]); - putchar ('\n'); - } putchar ('\n'); } } @@ -6988,11 +7006,13 @@ display_debug_frames (struct dwarf_secti READ_ULEB (augmentation_data_len); augmentation_data = start; start += augmentation_data_len; - /* PR 17512: file: 722-8446-0.004. */ - if (start >= end || ((signed long) augmentation_data_len) < 0) + /* PR 17512 file: 722-8446-0.004 and PR 22386. */ + if (start >= end + || ((bfd_signed_vma) augmentation_data_len) < 0 + || augmentation_data > start) { - warn (_("Corrupt augmentation data length: %lx\n"), - augmentation_data_len); + warn (_("Corrupt augmentation data length: 0x%s\n"), + dwarf_vmatoa ("x", augmentation_data_len)); start = end; augmentation_data = NULL; augmentation_data_len = 0; @@ -7014,12 +7034,7 @@ display_debug_frames (struct dwarf_secti if (! do_debug_frames_interp && augmentation_data_len) { - unsigned long i; - - printf (" Augmentation data: "); - for (i = 0; i < augmentation_data_len; ++i) - printf (" %02x", augmentation_data[i]); - putchar ('\n'); + display_augmentation_data (augmentation_data, augmentation_data_len); putchar ('\n'); } }