From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 114781 invoked by alias); 15 Mar 2019 07:47:55 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Received: (qmail 114758 invoked by uid 89); 15 Mar 2019 07:47:54 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-14.3 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,SPF_HELO_PASS,SPF_SOFTFAIL autolearn=ham version=3.3.1 spammy=0x41, HContent-Transfer-Encoding:8bit X-HELO: mga12.intel.com Received: from mga12.intel.com (HELO mga12.intel.com) (192.55.52.136) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 15 Mar 2019 07:47:52 +0000 Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga106.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 15 Mar 2019 00:47:51 -0700 Received: from gnu-cfl-2.sh.intel.com (HELO gnu-cfl-2.localdomain) ([10.239.153.88]) by orsmga002.jf.intel.com with ESMTP; 15 Mar 2019 00:47:49 -0700 Received: from gnu-cfl-2.sh.intel.com (localhost [IPv6:::1]) by gnu-cfl-2.localdomain (Postfix) with ESMTP id 1F9E3C0054 for ; Fri, 15 Mar 2019 15:47:49 +0800 (CST) From: "H.J. Lu" To: binutils@sourceware.org Subject: [PATCH] x86-64: Check for corrupt input with bad relocation Date: Fri, 15 Mar 2019 07:47:00 -0000 Message-Id: <20190315074749.32251-1-hjl.tools@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-IsSubscribed: yes X-SW-Source: 2019-03/txt/msg00078.txt.bz2 PR ld/24338 * elf64-x86-64.c (elf_x86_64_relocate_section): Check for corrupt input with bad relocation. --- bfd/ChangeLog | 6 ++ bfd/elf64-x86-64.c | 170 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 138 insertions(+), 38 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 084dbe08fd..a072ade16b 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,11 @@ 2019-03-15 H.J. Lu + PR ld/24338 + * elf64-x86-64.c (elf_x86_64_relocate_section): Check for corrupt + input with bad relocation. + +22019-03-15 H.J. Lu + * elf64-x86-64.c (elf_x86_64_relocate_section): Re-indent. 2019-03-14 Nick Clifton diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c index 0d1c8397c8..ecd4c6d03c 100644 --- a/bfd/elf64-x86-64.c +++ b/bfd/elf64-x86-64.c @@ -3361,20 +3361,39 @@ direct: { if (contents[roff + 5] == 0xb8) { + if (roff < 3 + || (roff - 3 + 22) > input_section->size) + { +corrupt_input: + info->callbacks->einfo + (_("%F%P: corrupt input: %pB\n"), + input_bfd); + return FALSE; + } memcpy (contents + roff - 3, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80" "\0\0\0\0\x66\x0f\x1f\x44\0", 22); largepic = 1; } else - memcpy (contents + roff - 4, - "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", - 16); + { + if (roff < 4 + || (roff - 4 + 16) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 4, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", + 16); + } } else - memcpy (contents + roff - 3, - "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", - 15); + { + if (roff < 3 + || (roff - 3 + 15) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 3, + "\x64\x8b\x04\x25\0\0\0\0\x48\x8d\x80\0\0\0", + 15); + } bfd_put_32 (output_bfd, elf_x86_64_tpoff (info, relocation), contents + roff + 8 + largepic); @@ -3395,6 +3414,8 @@ direct: unsigned int val, type; + if (roff < 3) + goto corrupt_input; type = bfd_get_8 (input_bfd, contents + roff - 3); val = bfd_get_8 (input_bfd, contents + roff - 1); bfd_put_8 (output_bfd, 0x48 | ((type >> 2) & 1), @@ -3441,7 +3462,11 @@ direct: if (roff >= 3) val = bfd_get_8 (input_bfd, contents + roff - 3); else - val = 0; + { + if (roff < 2) + goto corrupt_input; + val = 0; + } type = bfd_get_8 (input_bfd, contents + roff - 2); reg = bfd_get_8 (input_bfd, contents + roff - 1); reg >>= 3; @@ -3449,11 +3474,19 @@ direct: { /* movq */ if (val == 0x4c) - bfd_put_8 (output_bfd, 0x49, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x49, + contents + roff - 3); + } else if (!ABI_64_P (output_bfd) && val == 0x44) - bfd_put_8 (output_bfd, 0x41, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); + } bfd_put_8 (output_bfd, 0xc7, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3464,11 +3497,19 @@ direct: /* addq/addl -> addq/addl - addressing with %rsp/%r12 is special */ if (val == 0x4c) - bfd_put_8 (output_bfd, 0x49, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x49, + contents + roff - 3); + } else if (!ABI_64_P (output_bfd) && val == 0x44) - bfd_put_8 (output_bfd, 0x41, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x41, + contents + roff - 3); + } bfd_put_8 (output_bfd, 0x81, contents + roff - 2); bfd_put_8 (output_bfd, 0xc0 | reg, @@ -3478,11 +3519,19 @@ direct: { /* addq/addl -> leaq/leal */ if (val == 0x4c) - bfd_put_8 (output_bfd, 0x4d, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x4d, + contents + roff - 3); + } else if (!ABI_64_P (output_bfd) && val == 0x44) - bfd_put_8 (output_bfd, 0x45, - contents + roff - 3); + { + if (roff < 3) + goto corrupt_input; + bfd_put_8 (output_bfd, 0x45, + contents + roff - 3); + } bfd_put_8 (output_bfd, 0x8d, contents + roff - 2); bfd_put_8 (output_bfd, 0x80 | reg | (reg << 3), @@ -3652,20 +3701,33 @@ direct: { if (contents[roff + 5] == 0xb8) { + if (roff < 3 + || (roff - 3 + 22) > input_section->size) + goto corrupt_input; memcpy (contents + roff - 3, "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05" "\0\0\0\0\x66\x0f\x1f\x44\0", 22); largepic = 1; } else - memcpy (contents + roff - 4, - "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", - 16); + { + if (roff < 4 + || (roff - 4 + 16) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 4, + "\x64\x48\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", + 16); + } } else - memcpy (contents + roff - 3, - "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", - 15); + { + if (roff < 3 + || (roff - 3 + 15) > input_section->size) + goto corrupt_input; + memcpy (contents + roff - 3, + "\x64\x8b\x04\x25\0\0\0\0\x48\x03\x05\0\0\0", + 15); + } relocation = (htab->elf.sgot->output_section->vma + htab->elf.sgot->output_offset + off @@ -3694,6 +3756,8 @@ direct: turn a leaq into a movq in the form we use it, it suffices to change the second byte from 0x8d to 0x8b. */ + if (roff < 2) + goto corrupt_input; bfd_put_8 (output_bfd, 0x8b, contents + roff - 2); bfd_put_32 (output_bfd, @@ -3762,28 +3826,58 @@ direct: BFD_ASSERT (r_type == R_X86_64_TPOFF32); if (ABI_64_P (output_bfd)) { + if ((rel->r_offset + 5) >= input_section->size) + goto corrupt_input; if (contents[rel->r_offset + 5] == 0xb8) - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0" - "\x64\x48\x8b\x04\x25\0\0\0", 22); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 22) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x66\x2e\x0f\x1f\x84\0\0\0\0\0" + "\x64\x48\x8b\x04\x25\0\0\0", 22); + } else if (contents[rel->r_offset + 4] == 0xff || contents[rel->r_offset + 4] == 0x67) - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", - 13); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 13) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", + 13); + + } else - memcpy (contents + rel->r_offset - 3, - "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 12) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x66\x66\x64\x48\x8b\x04\x25\0\0\0", 12); + } } else { + if ((rel->r_offset + 4) >= input_section->size) + goto corrupt_input; if (contents[rel->r_offset + 4] == 0xff) - memcpy (contents + rel->r_offset - 3, - "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", - 13); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 13) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x66\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", + 13); + } else - memcpy (contents + rel->r_offset - 3, - "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12); + { + if (rel->r_offset < 3 + || (rel->r_offset - 3 + 12) > input_section->size) + goto corrupt_input; + memcpy (contents + rel->r_offset - 3, + "\x0f\x1f\x40\x00\x64\x8b\x04\x25\0\0\0", 12); + } } /* Skip R_X86_64_PC32, R_X86_64_PLT32, R_X86_64_GOTPCRELX and R_X86_64_PLTOFF64. */ -- 2.20.1