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;
}