From 463ec189fe9eca199edf87cda2c31efbe850390d Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 3 Jun 2020 15:16:48 +0100 Subject: Prevent a potential use-after-fee memory corruption bug in the linker (for PE format files). PR 25993 * emultempl/pe.em (_after_open): Check for duplicate filename pointers before renaming the dll. * emultempl/pep.em (_after_open): Likewise. --- ld/ChangeLog | 10 ++++++++++ ld/emultempl/pe.em | 25 +++++++++++++++++++------ ld/emultempl/pep.em | 25 +++++++++++++++++++------ 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index f26bea4..0006ace 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2020-06-03 Nick Clifton + + Import from mainline: + 2020-05-18 Nick Clifton + + PR 25993 + * emultempl/pe.em (_after_open): Check for duplicate filename + pointers before renaming the dll. + * emultempl/pep.em (_after_open): Likewise. + 2020-04-08 Tamar Christina Backport from mainline. diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 97fb146..26fa746 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1652,13 +1652,26 @@ gld_${EMULATION_NAME}_after_open (void) else /* sentinel */ seq = 'c'; - new_name = xmalloc (strlen (is->the_bfd->filename) + 3); - sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); - bfd_set_filename (is->the_bfd, new_name); + /* PR 25993: It is possible that is->the_bfd-filename == is->filename. + In which case calling bfd_set_filename on one will free the memory + pointed to by the other. */ + if (is->filename == is->the_bfd->filename) + { + new_name = xmalloc (strlen (is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + bfd_set_filename (is->the_bfd, new_name); + is->filename = new_name; + } + else + { + new_name = xmalloc (strlen (is->the_bfd->filename) + 3); + sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); + bfd_set_filename (is->the_bfd, new_name); - new_name = xmalloc (strlen (is->filename) + 3); - sprintf (new_name, "%s.%c", is->filename, seq); - is->filename = new_name; + new_name = xmalloc (strlen (is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + is->filename = new_name; + } } } } diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index e8f5ca5..ef23221 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1620,13 +1620,26 @@ gld_${EMULATION_NAME}_after_open (void) else /* sentinel */ seq = 'c'; - new_name = xmalloc (strlen (is->the_bfd->filename) + 3); - sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); - bfd_set_filename (is->the_bfd, new_name); + /* PR 25993: It is possible that is->the_bfd-filename == is->filename. + In which case calling bfd_set_filename on one will free the memory + pointed to by the other. */ + if (is->filename == is->the_bfd->filename) + { + new_name = xmalloc (strlen (is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + bfd_set_filename (is->the_bfd, new_name); + is->filename = new_name; + } + else + { + new_name = xmalloc (strlen (is->the_bfd->filename) + 3); + sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); + bfd_set_filename (is->the_bfd, new_name); - new_name = xmalloc (strlen (is->filename) + 3); - sprintf (new_name, "%s.%c", is->filename, seq); - is->filename = new_name; + new_name = xmalloc (strlen (is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + is->filename = new_name; + } } } } -- cgit v1.1