Harden PowerPC64 OPD handling against fuzzers
authorAlan Modra <amodra@gmail.com>
Wed, 31 May 2023 05:41:34 +0000 (15:11 +0930)
committerAlan Modra <amodra@gmail.com>
Thu, 1 Jun 2023 00:22:07 +0000 (09:52 +0930)
commit6313825cbf834b1852007707cfff2ccd3b0dbd6b
treed93d33d570420df75074c6c825415d0e1711bbc0
parent8261abd51344cb4c454514fba1389a9292f9652b
Harden PowerPC64 OPD handling against fuzzers

PowerPC64 ELFv1 object files should have at most one .opd section, and
OPD handling in elf64-ppc.c makes use of this fact by caching some
.opd section info in the per-object bfd.tdata.  This was done to avoid
another word in the target specific section data.  Of course, fuzzers
don't respect the ABI, and even non-malicious users can accidentally
create multiple .opd sections.  So it is better to avoid possible
buffer overflows and other confusion when OPD handling for a second
.opd section references data for the first .opd section, by keeping
the data per-section.

The patch also fixes a memory leak, and a corner case where I think we
could hit an assertion in opd_entry_value or read out of bounds in
ppc64_elf_branch_reloc doing a final link producing non-ppc64 output.
(It's a really rare corner case because not only would you need to be
linking ppc64 objects to non-ppc64 output, you'd also need a branch
reloc symbol to be defined in a .opd section of a non-ppc64 input.)

* elf64-ppc.c (is_ppc64_elf): Move earlier in file.
(ppc64_elf_branch_reloc): Check symbol bfd before accessing
ppc64 elf specific data structures.
(struct ppc64_elf_obj_tdata): Move opd union..
(struct _ppc64_elf_section_data): ..to here.
(ppc64_elf_before_check_relocs): Allow for opd sec_type
already set to sec_opd.
(ppc64_elf_check_relocs): Only set sec_type to sec_toc when
unset.  Error for unexpected toc relocs.
(opd_entry_value): Return -1 when non-ppc64 rather than
asserting.  Check and set sec_type too.  Adjust for changed
location of contents and relocs.
(ppc64_elf_relocate_section): Adjust for changed location of
cached .opd relocs.
(ppc64_elf_free_cached_info): New function.
(bfd_elf64_bfd_free_cached_info): Define.
bfd/elf64-ppc.c