From 4e970e640940fe59afda9ce9b3a28cf72d0d6b6c Mon Sep 17 00:00:00 2001 From: Armin Kuster Date: Tue, 7 Aug 2018 21:00:50 -0700 Subject: Binutils: Security fix for CVE-2017-17121 Affects: <= 2.29.1 (From OE-Core rev: 942e7f65fd656f2cc526a3c99edcea60f341132c) Signed-off-by: Armin Kuster Signed-off-by: Richard Purdie --- meta/recipes-devtools/binutils/binutils-2.29.1.inc | 1 + .../binutils/binutils/CVE-2017-17121.patch | 366 +++++++++++++++++++++ 2 files changed, 367 insertions(+) create mode 100644 meta/recipes-devtools/binutils/binutils/CVE-2017-17121.patch diff --git a/meta/recipes-devtools/binutils/binutils-2.29.1.inc b/meta/recipes-devtools/binutils/binutils-2.29.1.inc index 2a713caf5d..27d77cc409 100644 --- a/meta/recipes-devtools/binutils/binutils-2.29.1.inc +++ b/meta/recipes-devtools/binutils/binutils-2.29.1.inc @@ -61,6 +61,7 @@ SRC_URI = "\ file://CVE-2017-16831.patch \ file://CVE-2017-16832.patch \ file://CVE-2017-17080.patch \ + file://CVE-2017-17121.patch \ " S = "${WORKDIR}/git" diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2017-17121.patch b/meta/recipes-devtools/binutils/binutils/CVE-2017-17121.patch new file mode 100644 index 0000000000..4b675f7b72 --- /dev/null +++ b/meta/recipes-devtools/binutils/binutils/CVE-2017-17121.patch @@ -0,0 +1,366 @@ +From b23dc97fe237a1d9e850d7cbeee066183a00630b Mon Sep 17 00:00:00 2001 +From: Nick Clifton +Date: Tue, 28 Nov 2017 13:20:31 +0000 +Subject: [PATCH] Fix a memory access violation when attempting to parse a + corrupt COFF binary with a relocation that points beyond the end of the + section to be relocated. + + PR 22506 + * reloc.c (reloc_offset_in_range): Rename to + bfd_reloc_offset_in_range and export. + (bfd_perform_relocation): Rename function invocation. + (bfd_install_relocation): Likewise. + (bfd_final_link_relocate): Likewise. + * bfd-in2.h: Regenerate. + * coff-arm.c (coff_arm_reloc): Use bfd_reloc_offset_in_range. + * coff-i386.c (coff_i386_reloc): Likewise. + * coff-i860.c (coff_i860_reloc): Likewise. + * coff-m68k.c (mk68kcoff_common_addend_special_fn): Likewise. + * coff-m88k.c (m88k_special_reloc): Likewise. + * coff-mips.c (mips_reflo_reloc): Likewise. + * coff-x86_64.c (coff_amd64_reloc): Likewise. + +Upstream-Status: Backport +Affects: <= 2.29.1 +CVE: CVE-2017-17121 +Signed-off-by: Armin Kuster + +--- + bfd/ChangeLog | 17 +++++++++++++++ + bfd/bfd-in2.h | 6 +++++ + bfd/coff-arm.c | 65 ++++++++++++++++++++++++++++++------------------------- + bfd/coff-i386.c | 5 +++++ + bfd/coff-i860.c | 5 +++++ + bfd/coff-m68k.c | 5 +++++ + bfd/coff-m88k.c | 9 +++++++- + bfd/coff-mips.c | 6 +++++ + bfd/coff-x86_64.c | 16 +++++--------- + bfd/reloc.c | 40 +++++++++++++++++++++++++++++----- + 10 files changed, 126 insertions(+), 48 deletions(-) + +Index: git/bfd/bfd-in2.h +=================================================================== +--- git.orig/bfd/bfd-in2.h ++++ git/bfd/bfd-in2.h +@@ -2661,6 +2661,12 @@ bfd_reloc_status_type bfd_check_overflow + unsigned int addrsize, + bfd_vma relocation); + ++bfd_boolean bfd_reloc_offset_in_range ++ (reloc_howto_type *howto, ++ bfd *abfd, ++ asection *section, ++ bfd_size_type offset); ++ + bfd_reloc_status_type bfd_perform_relocation + (bfd *abfd, + arelent *reloc_entry, +Index: git/bfd/coff-arm.c +=================================================================== +--- git.orig/bfd/coff-arm.c ++++ git/bfd/coff-arm.c +@@ -109,41 +109,46 @@ coff_arm_reloc (bfd *abfd, + x = ((x & ~howto->dst_mask) \ + | (((x & howto->src_mask) + diff) & howto->dst_mask)) + +- if (diff != 0) +- { +- reloc_howto_type *howto = reloc_entry->howto; +- unsigned char *addr = (unsigned char *) data + reloc_entry->address; ++ if (diff != 0) ++ { ++ reloc_howto_type *howto = reloc_entry->howto; ++ unsigned char *addr = (unsigned char *) data + reloc_entry->address; ++ ++ if (! bfd_reloc_offset_in_range (howto, abfd, input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; ++ ++ switch (howto->size) ++ { ++ case 0: ++ { ++ char x = bfd_get_8 (abfd, addr); ++ DOIT (x); ++ bfd_put_8 (abfd, x, addr); ++ } ++ break; + +- switch (howto->size) ++ case 1: + { +- case 0: +- { +- char x = bfd_get_8 (abfd, addr); +- DOIT (x); +- bfd_put_8 (abfd, x, addr); +- } +- break; +- +- case 1: +- { +- short x = bfd_get_16 (abfd, addr); +- DOIT (x); +- bfd_put_16 (abfd, (bfd_vma) x, addr); +- } +- break; +- +- case 2: +- { +- long x = bfd_get_32 (abfd, addr); +- DOIT (x); +- bfd_put_32 (abfd, (bfd_vma) x, addr); +- } +- break; ++ short x = bfd_get_16 (abfd, addr); ++ DOIT (x); ++ bfd_put_16 (abfd, (bfd_vma) x, addr); ++ } ++ break; + +- default: +- abort (); ++ case 2: ++ { ++ long x = bfd_get_32 (abfd, addr); ++ DOIT (x); ++ bfd_put_32 (abfd, (bfd_vma) x, addr); + } +- } ++ break; ++ ++ default: ++ abort (); ++ } ++ } + + /* Now let bfd_perform_relocation finish everything up. */ + return bfd_reloc_continue; +Index: git/bfd/coff-i386.c +=================================================================== +--- git.orig/bfd/coff-i386.c ++++ git/bfd/coff-i386.c +@@ -144,6 +144,11 @@ coff_i386_reloc (bfd *abfd, + reloc_howto_type *howto = reloc_entry->howto; + unsigned char *addr = (unsigned char *) data + reloc_entry->address; + ++ if (! bfd_reloc_offset_in_range (howto, abfd, input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; ++ + switch (howto->size) + { + case 0: +Index: git/bfd/coff-i860.c +=================================================================== +--- git.orig/bfd/coff-i860.c ++++ git/bfd/coff-i860.c +@@ -95,6 +95,11 @@ coff_i860_reloc (bfd *abfd, + reloc_howto_type *howto = reloc_entry->howto; + unsigned char *addr = (unsigned char *) data + reloc_entry->address; + ++ if (! bfd_reloc_offset_in_range (howto, abfd, input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; ++ + switch (howto->size) + { + case 0: +Index: git/bfd/coff-m68k.c +=================================================================== +--- git.orig/bfd/coff-m68k.c ++++ git/bfd/coff-m68k.c +@@ -305,6 +305,11 @@ m68kcoff_common_addend_special_fn (bfd * + reloc_howto_type *howto = reloc_entry->howto; + unsigned char *addr = (unsigned char *) data + reloc_entry->address; + ++ if (! bfd_reloc_offset_in_range (howto, abfd, input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; ++ + switch (howto->size) + { + case 0: +Index: git/bfd/coff-m88k.c +=================================================================== +--- git.orig/bfd/coff-m88k.c ++++ git/bfd/coff-m88k.c +@@ -72,10 +72,17 @@ m88k_special_reloc (bfd *abfd, + { + bfd_vma output_base = 0; + bfd_vma addr = reloc_entry->address; +- bfd_vma x = bfd_get_16 (abfd, (bfd_byte *) data + addr); ++ bfd_vma x; + asection *reloc_target_output_section; + long relocation = 0; + ++ if (! bfd_reloc_offset_in_range (howto, abfd, input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; ++ ++ x = bfd_get_16 (abfd, (bfd_byte *) data + addr); ++ + /* Work out which section the relocation is targeted at and the + initial relocation command value. */ + +Index: git/bfd/coff-mips.c +=================================================================== +--- git.orig/bfd/coff-mips.c ++++ git/bfd/coff-mips.c +@@ -504,6 +504,12 @@ mips_reflo_reloc (bfd *abfd ATTRIBUTE_UN + unsigned long vallo; + struct mips_hi *next; + ++ if (! bfd_reloc_offset_in_range (reloc_entry->howto, abfd, ++ input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; ++ + /* Do the REFHI relocation. Note that we actually don't + need to know anything about the REFLO itself, except + where to find the low 16 bits of the addend needed by the +Index: git/bfd/coff-x86_64.c +=================================================================== +--- git.orig/bfd/coff-x86_64.c ++++ git/bfd/coff-x86_64.c +@@ -143,16 +143,10 @@ coff_amd64_reloc (bfd *abfd, + reloc_howto_type *howto = reloc_entry->howto; + unsigned char *addr = (unsigned char *) data + reloc_entry->address; + +- /* FIXME: We do not have an end address for data, so we cannot +- accurately range check any addresses computed against it. +- cf: PR binutils/17512: file: 1085-1761-0.004. +- For now we do the best that we can. */ +- if (addr < (unsigned char *) data +- || addr > ((unsigned char *) data) + input_section->size) +- { +- bfd_set_error (bfd_error_bad_value); +- return bfd_reloc_notsupported; +- } ++ if (! bfd_reloc_offset_in_range (howto, abfd, input_section, ++ reloc_entry->address ++ * bfd_octets_per_byte (abfd))) ++ return bfd_reloc_outofrange; + + switch (howto->size) + { +Index: git/bfd/reloc.c +=================================================================== +--- git.orig/bfd/reloc.c ++++ git/bfd/reloc.c +@@ -538,12 +538,31 @@ bfd_check_overflow (enum complain_overfl + return flag; + } + ++/* ++FUNCTION ++ bfd_reloc_offset_in_range ++ ++SYNOPSIS ++ bfd_boolean bfd_reloc_offset_in_range ++ (reloc_howto_type *howto, ++ bfd *abfd, ++ asection *section, ++ bfd_size_type offset); ++ ++DESCRIPTION ++ Returns TRUE if the reloc described by @var{HOWTO} can be ++ applied at @var{OFFSET} octets in @var{SECTION}. ++ ++*/ ++ + /* HOWTO describes a relocation, at offset OCTET. Return whether the + relocation field is within SECTION of ABFD. */ + +-static bfd_boolean +-reloc_offset_in_range (reloc_howto_type *howto, bfd *abfd, +- asection *section, bfd_size_type octet) ++bfd_boolean ++bfd_reloc_offset_in_range (reloc_howto_type *howto, ++ bfd *abfd, ++ asection *section, ++ bfd_size_type octet) + { + bfd_size_type octet_end = bfd_get_section_limit_octets (abfd, section); + bfd_size_type reloc_size = bfd_get_reloc_size (howto); +@@ -617,6 +636,11 @@ bfd_perform_relocation (bfd *abfd, + if (howto && howto->special_function) + { + bfd_reloc_status_type cont; ++ ++ /* Note - we do not call bfd_reloc_offset_in_range here as the ++ reloc_entry->address field might actually be valid for the ++ backend concerned. It is up to the special_function itself ++ to call bfd_reloc_offset_in_range if needed. */ + cont = howto->special_function (abfd, reloc_entry, symbol, data, + input_section, output_bfd, + error_message); +@@ -637,7 +661,7 @@ bfd_perform_relocation (bfd *abfd, + + /* Is the address of the relocation really within the section? */ + octets = reloc_entry->address * bfd_octets_per_byte (abfd); +- if (!reloc_offset_in_range (howto, abfd, input_section, octets)) ++ if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets)) + return bfd_reloc_outofrange; + + /* Work out which section the relocation is targeted at and the +@@ -1003,6 +1027,10 @@ bfd_install_relocation (bfd *abfd, + { + bfd_reloc_status_type cont; + ++ /* Note - we do not call bfd_reloc_offset_in_range here as the ++ reloc_entry->address field might actually be valid for the ++ backend concerned. It is up to the special_function itself ++ to call bfd_reloc_offset_in_range if needed. */ + /* XXX - The special_function calls haven't been fixed up to deal + with creating new relocations and section contents. */ + cont = howto->special_function (abfd, reloc_entry, symbol, +@@ -1025,7 +1053,7 @@ bfd_install_relocation (bfd *abfd, + + /* Is the address of the relocation really within the section? */ + octets = reloc_entry->address * bfd_octets_per_byte (abfd); +- if (!reloc_offset_in_range (howto, abfd, input_section, octets)) ++ if (!bfd_reloc_offset_in_range (howto, abfd, input_section, octets)) + return bfd_reloc_outofrange; + + /* Work out which section the relocation is targeted at and the +@@ -1363,7 +1391,7 @@ _bfd_final_link_relocate (reloc_howto_ty + bfd_size_type octets = address * bfd_octets_per_byte (input_bfd); + + /* Sanity check the address. */ +- if (!reloc_offset_in_range (howto, input_bfd, input_section, octets)) ++ if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, octets)) + return bfd_reloc_outofrange; + + /* This function assumes that we are dealing with a basic relocation +Index: git/bfd/ChangeLog +=================================================================== +--- git.orig/bfd/ChangeLog ++++ git/bfd/ChangeLog +@@ -1,3 +1,20 @@ ++2017-11-28 Nick Clifton ++ ++ PR 22506 ++ * reloc.c (reloc_offset_in_range): Rename to ++ bfd_reloc_offset_in_range and export. ++ (bfd_perform_relocation): Rename function invocation. ++ (bfd_install_relocation): Likewise. ++ (bfd_final_link_relocate): Likewise. ++ * bfd-in2.h: Regenerate. ++ * coff-arm.c (coff_arm_reloc): Use bfd_reloc_offset_in_range. ++ * coff-i386.c (coff_i386_reloc): Likewise. ++ * coff-i860.c (coff_i860_reloc): Likewise. ++ * coff-m68k.c (mk68kcoff_common_addend_special_fn): Likewise. ++ * coff-m88k.c (m88k_special_reloc): Likewise. ++ * coff-mips.c (mips_reflo_reloc): Likewise. ++ * coff-x86_64.c (coff_amd64_reloc): Likewise. ++ + 2017-11-16 Nick Clifton + + PR 22421 -- cgit v1.2.3-54-g00ecf