RFC: Fix for CVE-2026-19548

Nick Clifton <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <[email protected]>
Hi Guys,

  CVE-2026-19548 points out a potential use-after-free bug in the
  add_archive_element() function in ld/ldmain.c.  After looking at
  it it seemed to me that the simplest solution was to keep a copy
  of the my_archive pointer so that there is no need to dereference
  the freed bfd structure.  As is done in the attached, proposed
  patch.  Any comments ?

Cheers
  Nick

PS. According to the SECURITY.txt statement this bug does not really
  qualify for CVE status, but that is a separate issue from actually
  fixing the bug.

https://nvd.nist.gov/vuln/detail/CVE-2026-19548
add_archive_element.patch (text/x-patch, 2.3 KB)
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 77b167fd642..eb4043a9f88 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -1386,6 +1386,7 @@ add_archive_element (struct bfd_link_info *info,
   lang_input_statement_type *input;
   lang_input_statement_type *parent;
   lang_input_statement_type orig_input;
+  bfd * my_archive;
 
   input = stat_alloc (sizeof (*input));
   memset (input, 0, sizeof (*input));
@@ -1394,6 +1395,11 @@ add_archive_element (struct bfd_link_info *info,
   input->local_sym_name = bfd_get_filename (abfd);
   input->the_bfd = abfd;
 
+  /* If abfd is closed by plugin_maybe_claim() then accessing
+     abfd->my_archive could dereference freed memory, so keep a
+     copy of the my_archive pointer here.  */
+  my_archive = abfd->my_archive;
+
   /* Save the original data for trace files/tries below, as plugins
      (if enabled) may possibly alter it to point to a replacement
      BFD, but we still want to output the original BFD filename.  */
@@ -1439,7 +1445,7 @@ add_archive_element (struct bfd_link_info *info,
 
   /* Set the file_chain pointer of archives to the last element loaded
      from the archive.  See ldlang.c:find_rescan_insertion.  */
-  parent = bfd_usrdata (abfd->my_archive);
+  parent = bfd_usrdata (my_archive);
   if (parent != NULL && !parent->flags.reload)
     parent->next = input;
 
@@ -1490,17 +1496,17 @@ add_archive_element (struct bfd_link_info *info,
 	  header_printed = true;
 	}
 
-      if (abfd->my_archive == NULL
-	  || bfd_is_thin_archive (abfd->my_archive))
+      if (my_archive == NULL
+	  || bfd_is_thin_archive (my_archive))
 	{
 	  minfo ("%s", bfd_get_filename (abfd));
 	  len = strlen (bfd_get_filename (abfd));
 	}
       else
 	{
-	  minfo ("%s(%s)", bfd_get_filename (abfd->my_archive),
+	  minfo ("%s(%s)", bfd_get_filename (my_archive),
 		 bfd_get_filename (abfd));
-	  len = (strlen (bfd_get_filename (abfd->my_archive))
+	  len = (strlen (bfd_get_filename (my_archive))
 		 + strlen (bfd_get_filename (abfd))
 		 + 2);
 	}
@@ -1522,7 +1528,7 @@ add_archive_element (struct bfd_link_info *info,
 
   if (verbose
       || trace_files > 1
-      || (trace_files && bfd_is_thin_archive (orig_input.the_bfd->my_archive)))
+      || (trace_files && bfd_is_thin_archive (my_archive)))
     info_msg ("%pI\n", &orig_input);
   return true;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.