[binutils-gdb] m32r hi/lo reloc offset sanity checks
Alan Modra via Binutils-cvs <[email protected]>
| Newsgroups | gmane.comp.gnu.binutils.cvs |
|---|---|
| Message-ID | <[email protected]> |
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=be28dff7f92890b859cf365c4f2c7dd687da6c04 commit be28dff7f92890b859cf365c4f2c7dd687da6c04 Author: Alan Modra <[email protected]> Date: Mon Apr 20 15:41:14 2026 +0930 m32r hi/lo reloc offset sanity checks This fixes another fuzzer attack. * elf32-m32r.c (m32r_elf_hi16_reloc): Properly check reloc offset. (m32r_elf_relocate_hi16): Add input_section param. Return status. Sanity check reloc offsets before accessing section contents. Simplify sign extension. (m32r_elf_lo16_reloc): Sanity check reloc offset. Simplify sign extension. Remove unnecessary casts. (m32r_elf_relocate_section): Adjust m32r_elf_relocate_hi16 calls. Diff: --- bfd/elf32-m32r.c | 48 +++++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/bfd/elf32-m32r.c b/bfd/elf32-m32r.c index c10195b154d..68ef7122368 100644 --- a/bfd/elf32-m32r.c +++ b/bfd/elf32-m32r.c @@ -353,7 +353,7 @@ m32r_elf_free_cached_info (bfd *abfd) static bfd_reloc_status_type -m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, +m32r_elf_hi16_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, void * data, @@ -378,7 +378,8 @@ m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, } /* Sanity check the address (offset in section). */ - if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, input_section, + reloc_entry->address)) return bfd_reloc_outofrange; ret = bfd_reloc_ok; @@ -413,8 +414,9 @@ m32r_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, /* Handle an M32R ELF HI16 reloc. */ -static void +static bfd_reloc_status_type m32r_elf_relocate_hi16 (bfd *input_bfd, + asection *input_section, int type, Elf_Internal_Rela *relhi, Elf_Internal_Rela *rello, @@ -423,6 +425,11 @@ m32r_elf_relocate_hi16 (bfd *input_bfd, { unsigned long insn; bfd_vma addlo; + bfd_vma end = bfd_get_section_limit_octets (input_bfd, input_section); + + if (relhi->r_offset > end || end - relhi->r_offset < 4 + || rello->r_offset > end || end - rello->r_offset < 4) + return bfd_reloc_outofrange; insn = bfd_get_32 (input_bfd, contents + relhi->r_offset); @@ -435,13 +442,13 @@ m32r_elf_relocate_hi16 (bfd *input_bfd, addend += ((insn & 0xffff) << 16) + addlo; /* Reaccount for sign extension of low part. */ - if (type == R_M32R_HI16_SLO - && (addend & 0x8000) != 0) - addend += 0x10000; + if (type == R_M32R_HI16_SLO) + addend += 0x8000; bfd_put_32 (input_bfd, (insn & 0xffff0000) | ((addend >> 16) & 0xffff), contents + relhi->r_offset); + return bfd_reloc_ok; } /* Do an R_M32R_LO16 relocation. This is a straightforward 16 bit @@ -470,6 +477,10 @@ m32r_elf_lo16_reloc (bfd *input_bfd, return bfd_reloc_ok; } + if (!bfd_reloc_offset_in_range (reloc_entry->howto, input_bfd, input_section, + reloc_entry->address)) + return bfd_reloc_outofrange; + sdata = m32r_elf_section_data (input_section); if (sdata->m32r_hi16_list != NULL) { @@ -488,16 +499,15 @@ m32r_elf_lo16_reloc (bfd *input_bfd, find the low 16 bits of the addend needed by the LO16. */ insn = bfd_get_32 (input_bfd, l->addr); vallo = ((bfd_get_32 (input_bfd, (bfd_byte *) data + reloc_entry->address) - & 0xffff) ^ 0x8000) - 0x8000; + & 0xffff) ^ 0x8000) - 0x8000; val = ((insn & 0xffff) << 16) + vallo; val += l->addend; /* Reaccount for sign extension of low part. */ - if ((val & 0x8000) != 0) - val += 0x10000; + val += 0x8000; - insn = (insn &~ (bfd_vma) 0xffff) | ((val >> 16) & 0xffff); - bfd_put_32 (input_bfd, (bfd_vma) insn, l->addr); + insn = (insn & ~0xffff) | ((val >> 16) & 0xffff); + bfd_put_32 (input_bfd, insn, l->addr); next = l->next; free (l); @@ -2451,11 +2461,9 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, continue; if (lorel < relend && ELF32_R_TYPE (lorel->r_info) == R_M32R_LO16) - { - m32r_elf_relocate_hi16 (input_bfd, r_type, rel, lorel, - contents, addend); - r = bfd_reloc_ok; - } + r = m32r_elf_relocate_hi16 (input_bfd, input_section, + r_type, rel, lorel, + contents, addend); else r = _bfd_relocate_contents (howto, input_bfd, addend, contents + offset); @@ -2778,11 +2786,9 @@ m32r_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED, continue; if (lorel < relend && ELF32_R_TYPE (lorel->r_info) == R_M32R_LO16) - { - m32r_elf_relocate_hi16 (input_bfd, r_type, rel, lorel, - contents, relocation + addend); - r = bfd_reloc_ok; - } + r = m32r_elf_relocate_hi16 (input_bfd, input_section, + r_type, rel, lorel, + contents, relocation + addend); else r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, offset,