From 5e365e474b7561318ddb1a107f05cf0c002e8284 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 18 May 2020 10:28:52 +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/ChangeLog | 7 +++++++ ld/emultempl/pe.em | 26 ++++++++++++++++++++------ ld/emultempl/pep.em | 25 +++++++++++++++++++------ 3 files changed, 46 insertions(+), 12 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 5923e4ca36b..49c697023d8 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,10 @@ +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-05-13 Nick Clifton PR 25979 diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 4fe195ec32a..ad5d65d024a 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -1655,13 +1655,27 @@ 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); - new_name = xmalloc (strlen (is->filename) + 3); - sprintf (new_name, "%s.%c", is->filename, seq); - is->filename = 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; + } } } } diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 3e03eb3a6e0..aa8bac5f816 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1623,13 +1623,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.30.2