From 463ec189fe9eca199edf87cda2c31efbe850390d Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Wed, 3 Jun 2020 15:16:48 +0100 Subject: [PATCH] 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/emultempl/pe.em | 25 +++++++++++++++++++------ ld/emultempl/pep.em | 25 +++++++++++++++++++------ 3 files changed, 48 insertions(+), 12 deletions(-) diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 97fb1468aa..26fa7465c0 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 e8f5ca503f..ef23221c03 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; + } } } } -- 2.27.0