summaryrefslogtreecommitdiff
path: root/bfd/elf.c
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2020-12-14 19:36:47 +1030
committerAlan Modra <amodra@gmail.com>2020-12-14 23:36:19 +1030
commita86c6c19643e9ac795b17846e5b0db8b3e4c54de (patch)
treef5386f7ef68e42eb20296f3b436e0d947fbfa136 /bfd/elf.c
parent8da4f428d1663541bdd49f5aa2041d06ac6a06de (diff)
downloadbinutils-gdb-a86c6c19643e9ac795b17846e5b0db8b3e4c54de.tar.gz
Put bfd_section_from_shdr loop detection array in elf_tdata
The static variables used by bfd_section_from_shdr to detect loops in ELF sections have a problem: Comparing a BFD pointer doesn't guarantee that the current bfd is the same as the one previously used to allocate the sections_being_created array. For example, doing size bad_elf_1 bad_elf_2 with two corrupted ELF files containing section loops will leave the section_being_created array allocated for the first file and since bfd_close is called for bad_elf_1 before bfd_elf_2 is opened, it is possible that the BFD for the second file is allocated in the same memory as the first file. If bad_elf_2 has more sections than bad_elf_1 then we might write beyond the end of the array. So this patch implements the FIXME Nick put in a comment about attaching the array to the BFD. * elf-bfd.h (struct elf_obj_tdata): Add being_created. * elf.c (bfd_section_from_shdr): Delete static vars for loop detection. Use new tdata variable instead. * elfcode.h (elf_object_p): Allocate being_created.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r--bfd/elf.c54
1 files changed, 9 insertions, 45 deletions
diff --git a/bfd/elf.c b/bfd/elf.c
index 419c5f4420c..7f2237655d3 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2045,49 +2045,20 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
const struct elf_backend_data *bed;
const char *name;
bfd_boolean ret = TRUE;
- static bfd_boolean * sections_being_created = NULL;
- static bfd * sections_being_created_abfd = NULL;
- static unsigned int nesting = 0;
if (shindex >= elf_numsections (abfd))
return FALSE;
- if (++ nesting > 3)
+ /* PR17512: A corrupt ELF binary might contain a loop of sections via
+ sh_link or sh_info. Detect this here, by refusing to load a
+ section that we are already in the process of loading. */
+ if (elf_tdata (abfd)->being_created[shindex])
{
- /* PR17512: A corrupt ELF binary might contain a recursive group of
- sections, with each the string indices pointing to the next in the
- loop. Detect this here, by refusing to load a section that we are
- already in the process of loading. We only trigger this test if
- we have nested at least three sections deep as normal ELF binaries
- can expect to recurse at least once.
-
- FIXME: It would be better if this array was attached to the bfd,
- rather than being held in a static pointer. */
-
- if (sections_being_created_abfd != abfd)
- {
- free (sections_being_created);
- sections_being_created = NULL;
- }
- if (sections_being_created == NULL)
- {
- size_t amt = elf_numsections (abfd) * sizeof (bfd_boolean);
-
- /* PR 26005: Do not use bfd_zalloc here as the memory might
- be released before the bfd has been fully scanned. */
- sections_being_created = (bfd_boolean *) bfd_zmalloc (amt);
- if (sections_being_created == NULL)
- return FALSE;
- sections_being_created_abfd = abfd;
- }
- if (sections_being_created [shindex])
- {
- _bfd_error_handler
- (_("%pB: warning: loop in section dependencies detected"), abfd);
- return FALSE;
- }
- sections_being_created [shindex] = TRUE;
+ _bfd_error_handler
+ (_("%pB: warning: loop in section dependencies detected"), abfd);
+ return FALSE;
}
+ elf_tdata (abfd)->being_created[shindex] = TRUE;
hdr = elf_elfsections (abfd)[shindex];
ehdr = elf_elfheader (abfd);
@@ -2611,14 +2582,7 @@ bfd_section_from_shdr (bfd *abfd, unsigned int shindex)
fail:
ret = FALSE;
success:
- if (sections_being_created && sections_being_created_abfd == abfd)
- sections_being_created [shindex] = FALSE;
- if (-- nesting == 0)
- {
- free (sections_being_created);
- sections_being_created = NULL;
- sections_being_created_abfd = NULL;
- }
+ elf_tdata (abfd)->being_created[shindex] = FALSE;
return ret;
}