diff --git a/SOURCES/binutils-CVE-2020-35448.patch b/SOURCES/binutils-CVE-2020-35448.patch new file mode 100644 index 0000000..4fab54c --- /dev/null +++ b/SOURCES/binutils-CVE-2020-35448.patch @@ -0,0 +1,53 @@ +diff -rup binutils.orig/bfd/elf.c binutils-2.35/bfd/elf.c +--- binutils.orig/bfd/elf.c 2021-04-19 10:49:21.757290990 +0100 ++++ binutils-2.35/bfd/elf.c 2021-04-19 10:50:28.309839285 +0100 +@@ -12534,7 +12534,9 @@ _bfd_elf_slurp_secondary_reloc_section ( + Elf_Internal_Shdr * hdr = & elf_section_data (relsec)->this_hdr; + + if (hdr->sh_type == SHT_SECONDARY_RELOC +- && hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx) ++ && hdr->sh_info == (unsigned) elf_section_data (sec)->this_idx ++ && (hdr->sh_entsize == ebd->s->sizeof_rel ++ || hdr->sh_entsize == ebd->s->sizeof_rela)) + { + bfd_byte * native_relocs; + bfd_byte * native_reloc; +diff -rup binutils.orig/bfd/elfcode.h binutils-2.35/bfd/elfcode.h +--- binutils.orig/bfd/elfcode.h 2021-04-19 10:49:21.767290922 +0100 ++++ binutils-2.35/bfd/elfcode.h 2021-04-19 10:52:22.196066303 +0100 +@@ -568,7 +568,7 @@ elf_object_p (bfd *abfd) + + /* If this is a relocatable file and there is no section header + table, then we're hosed. */ +- if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_type == ET_REL) ++ if (i_ehdrp->e_shoff < sizeof (x_ehdr) && i_ehdrp->e_type == ET_REL) + goto got_wrong_format_error; + + /* As a simple sanity check, verify that what BFD thinks is the +@@ -578,7 +578,7 @@ elf_object_p (bfd *abfd) + goto got_wrong_format_error; + + /* Further sanity check. */ +- if (i_ehdrp->e_shoff == 0 && i_ehdrp->e_shnum != 0) ++ if (i_ehdrp->e_shoff < sizeof (x_ehdr) && i_ehdrp->e_shnum != 0) + goto got_wrong_format_error; + + ebd = get_elf_backend_data (abfd); +@@ -615,7 +615,7 @@ elf_object_p (bfd *abfd) + && ebd->elf_osabi != ELFOSABI_NONE) + goto got_wrong_format_error; + +- if (i_ehdrp->e_shoff != 0) ++ if (i_ehdrp->e_shoff >= sizeof (x_ehdr)) + { + file_ptr where = (file_ptr) i_ehdrp->e_shoff; + +@@ -807,7 +807,7 @@ elf_object_p (bfd *abfd) + } + } + +- if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff != 0) ++ if (i_ehdrp->e_shstrndx != 0 && i_ehdrp->e_shoff >= sizeof (x_ehdr)) + { + unsigned int num_sec; + diff --git a/SOURCES/binutils-CVE-2021-20197.patch b/SOURCES/binutils-CVE-2021-20197.patch new file mode 100644 index 0000000..cea8953 --- /dev/null +++ b/SOURCES/binutils-CVE-2021-20197.patch @@ -0,0 +1,1287 @@ +diff -rup binutils.orig/bfd/bfd-in2.h binutils-2.35.1/bfd/bfd-in2.h +--- binutils.orig/bfd/bfd-in2.h 2021-01-29 11:14:51.848568548 +0000 ++++ binutils-2.35.1/bfd/bfd-in2.h 2021-01-29 11:15:33.431322133 +0000 +@@ -583,6 +583,8 @@ bfd *bfd_openr (const char *filename, co + + bfd *bfd_fdopenr (const char *filename, const char *target, int fd); + ++bfd *bfd_fdopenw (const char *filename, const char *target, int fd); ++ + bfd *bfd_openstreamr (const char * filename, const char * target, + void * stream); + +diff -rup binutils.orig/bfd/opncls.c binutils-2.35.1/bfd/opncls.c +--- binutils.orig/bfd/opncls.c 2021-01-29 11:14:51.846568560 +0000 ++++ binutils-2.35.1/bfd/opncls.c 2021-01-29 11:15:33.431322133 +0000 +@@ -395,6 +395,39 @@ bfd_fdopenr (const char *filename, const + + /* + FUNCTION ++ bfd_fdopenw ++ ++SYNOPSIS ++ bfd *bfd_fdopenw (const char *filename, const char *target, int fd); ++ ++DESCRIPTION ++ <> is exactly like <> with the exception that ++ the resulting BFD is suitable for output. ++*/ ++ ++bfd * ++bfd_fdopenw (const char *filename, const char *target, int fd) ++{ ++ bfd *out = bfd_fdopenr (filename, target, fd); ++ ++ if (out != NULL) ++ { ++ if (!bfd_write_p (out)) ++ { ++ close (fd); ++ _bfd_delete_bfd (out); ++ out = NULL; ++ bfd_set_error (bfd_error_invalid_operation); ++ } ++ else ++ out->direction = write_direction; ++ } ++ ++ return out; ++} ++ ++/* ++FUNCTION + bfd_openstreamr + + SYNOPSIS +diff -rup binutils.orig/binutils/ar.c binutils-2.35.1/binutils/ar.c +--- binutils.orig/binutils/ar.c 2021-01-29 11:14:51.344571539 +0000 ++++ binutils-2.35.1/binutils/ar.c 2021-01-29 11:15:56.174187367 +0000 +@@ -25,6 +25,7 @@ + + #include "sysdep.h" + #include "bfd.h" ++#include "libbfd.h" + #include "libiberty.h" + #include "progress.h" + #include "getopt.h" +@@ -1195,20 +1196,26 @@ write_archive (bfd *iarch) + bfd *obfd; + char *old_name, *new_name; + bfd *contents_head = iarch->archive_next; ++ int ofd = -1; ++ struct stat target_stat; ++ bfd_boolean skip_stat = FALSE; + + old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1); + strcpy (old_name, bfd_get_filename (iarch)); +- new_name = make_tempname (old_name); ++ new_name = make_tempname (old_name, &ofd); + + if (new_name == NULL) + bfd_fatal (_("could not create temporary file whilst writing archive")); + + output_filename = new_name; + +- obfd = bfd_openw (new_name, bfd_get_target (iarch)); ++ obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), ofd); + + if (obfd == NULL) +- bfd_fatal (old_name); ++ { ++ close (ofd); ++ bfd_fatal (old_name); ++ } + + output_bfd = obfd; + +@@ -1237,6 +1244,14 @@ write_archive (bfd *iarch) + if (!bfd_set_archive_head (obfd, contents_head)) + bfd_fatal (old_name); + ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ ofd = dup (ofd); ++ if (iarch == NULL || iarch->iostream == NULL) ++ skip_stat = TRUE; ++ else if (ofd == -1 || fstat (fileno (iarch->iostream), &target_stat) != 0) ++ bfd_fatal (old_name); ++#endif ++ + if (!bfd_close (obfd)) + bfd_fatal (old_name); + +@@ -1246,7 +1261,7 @@ write_archive (bfd *iarch) + /* We don't care if this fails; we might be creating the archive. */ + bfd_close (iarch); + +- if (smart_rename (new_name, old_name, 0) != 0) ++ if (smart_rename (new_name, old_name, ofd, skip_stat ? NULL : &target_stat, 0) != 0) + xexit (1); + free (old_name); + free (new_name); +diff -rup binutils.orig/binutils/arsup.c binutils-2.35.1/binutils/arsup.c +--- binutils.orig/binutils/arsup.c 2021-01-29 11:14:51.350571503 +0000 ++++ binutils-2.35.1/binutils/arsup.c 2021-01-29 11:15:56.174187367 +0000 +@@ -345,13 +345,25 @@ ar_save (void) + else + { + char *ofilename = xstrdup (bfd_get_filename (obfd)); ++ bfd_boolean skip_stat = FALSE; ++ struct stat target_stat; ++ int ofd = -1; + + if (deterministic > 0) + obfd->flags |= BFD_DETERMINISTIC_OUTPUT; + ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ /* It's OK to fail; at worst it will result in SMART_RENAME using a slow ++ copy fallback to write the output. */ ++ ofd = dup (fileno (obfd->iostream)); ++ if (lstat (real_name, &target_stat) != 0) ++ skip_stat = TRUE; ++#endif ++ + bfd_close (obfd); + +- smart_rename (ofilename, real_name, 0); ++ smart_rename (ofilename, real_name, ofd, ++ skip_stat ? NULL : &target_stat, 0); + obfd = 0; + free (ofilename); + } +diff -rup binutils.orig/binutils/bucomm.c binutils-2.35.1/binutils/bucomm.c +--- binutils.orig/binutils/bucomm.c 2021-01-29 11:14:51.422571073 +0000 ++++ binutils-2.35.1/binutils/bucomm.c 2021-01-29 11:15:33.431322133 +0000 +@@ -532,7 +532,7 @@ template_in_dir (const char *path) + as FILENAME. */ + + char * +-make_tempname (char *filename) ++make_tempname (const char *filename, int *ofd) + { + char *tmpname = template_in_dir (filename); + int fd; +@@ -550,7 +550,7 @@ make_tempname (const char *filename) + free (tmpname); + return NULL; + } +- close (fd); ++ *ofd = fd; + return tmpname; + } + +diff -rup binutils.orig/binutils/bucomm.h binutils-2.35.1/binutils/bucomm.h +--- binutils.orig/binutils/bucomm.h 2021-01-29 11:14:51.350571503 +0000 ++++ binutils-2.35.1/binutils/bucomm.h 2021-01-29 11:15:56.174187367 +0000 +@@ -51,7 +51,7 @@ int display_info (void); + + void print_arelt_descr (FILE *, bfd *, bfd_boolean); + +-char *make_tempname (char *); ++char *make_tempname (const char *, int *); + char *make_tempdir (char *); + + bfd_vma parse_vma (const char *, const char *); +@@ -71,7 +71,8 @@ extern void print_version (const char *) + /* In rename.c. */ + extern void set_times (const char *, const struct stat *); + +-extern int smart_rename (const char *, const char *, int); ++extern int smart_rename (const char *, const char *, int, struct stat *, int); ++ + + /* In libiberty. */ + void *xmalloc (size_t); +diff -rup binutils.orig/binutils/objcopy.c binutils-2.35.1/binutils/objcopy.c +--- binutils.orig/binutils/objcopy.c 2021-01-29 11:14:51.342571551 +0000 ++++ binutils-2.35.1/binutils/objcopy.c 2021-01-29 11:15:56.175187361 +0000 +@@ -20,6 +20,7 @@ + + #include "sysdep.h" + #include "bfd.h" ++#include "libbfd.h" + #include "progress.h" + #include "getopt.h" + #include "libiberty.h" +@@ -3711,9 +3712,9 @@ set_long_section_mode (bfd *output_bfd, + /* The top-level control. */ + + static void +-copy_file (const char *input_filename, const char *output_filename, +- const char *input_target, const char *output_target, +- const bfd_arch_info_type *input_arch) ++copy_file (const char *input_filename, const char *output_filename, int ofd, ++ struct stat *in_stat, const char *input_target, ++ const char *output_target, const bfd_arch_info_type *input_arch) + { + bfd *ibfd; + char **obj_matching; +@@ -3732,7 +3733,7 @@ copy_file (const char *input_filename, c + /* To allow us to do "strip *" without dying on the first + non-object file, failures are nonfatal. */ + ibfd = bfd_openr (input_filename, input_target); +- if (ibfd == NULL) ++ if (ibfd == NULL || fstat (fileno (ibfd->iostream), in_stat) != 0) + { + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + status = 1; +@@ -3786,9 +3787,14 @@ copy_file (const char *input_filename, c + else + force_output_target = TRUE; + +- obfd = bfd_openw (output_filename, output_target); ++ if (ofd >= 0) ++ obfd = bfd_fdopenw (output_filename, output_target, ofd); ++ else ++ obfd = bfd_openw (output_filename, output_target); ++ + if (obfd == NULL) + { ++ close (ofd); + bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + status = 1; + return; +@@ -3816,13 +3822,19 @@ copy_file (const char *input_filename, c + if (output_target == NULL) + output_target = bfd_get_target (ibfd); + +- obfd = bfd_openw (output_filename, output_target); ++ if (ofd >= 0) ++ obfd = bfd_fdopenw (output_filename, output_target, ofd); ++ else ++ obfd = bfd_openw (output_filename, output_target); ++ + if (obfd == NULL) + { ++ close (ofd); + bfd_nonfatal_message (output_filename, NULL, NULL, NULL); + status = 1; + return; + } ++ + /* This is a no-op on non-Coff targets. */ + set_long_section_mode (obfd, ibfd, long_section_names); + +@@ -4786,6 +4798,8 @@ strip_main (int argc, char *argv[]) + int hold_status = status; + struct stat statbuf; + char *tmpname; ++ int tmpfd = -1; ++ int copyfd = -1; + + if (get_file_size (argv[i]) < 1) + { +@@ -4793,18 +4807,18 @@ strip_main (int argc, char *argv[]) + continue; + } + +- if (preserve_dates) +- /* No need to check the return value of stat(). +- It has already been checked in get_file_size(). */ +- stat (argv[i], &statbuf); +- + if (output_file == NULL + || filename_cmp (argv[i], output_file) == 0) +- tmpname = make_tempname (argv[i]); ++ tmpname = make_tempname (argv[i], &tmpfd); + else + tmpname = output_file; + +- if (tmpname == NULL) ++ if (tmpname == NULL ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ ++ || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) ++#endif ++ ) + { + bfd_nonfatal_message (argv[i], NULL, NULL, + _("could not create temporary file to hold stripped copy")); +@@ -4813,7 +4827,8 @@ strip_main (int argc, char *argv[]) + } + + status = 0; +- copy_file (argv[i], tmpname, input_target, output_target, NULL); ++ copy_file (argv[i], tmpname, tmpfd, &statbuf, input_target, ++ output_target, NULL); + if (status == 0) + { + if (preserve_dates) +@@ -4821,12 +4836,18 @@ strip_main (int argc, char *argv[]) + if (output_file != tmpname) + status = (smart_rename (tmpname, + output_file ? output_file : argv[i], +- preserve_dates) != 0); ++ copyfd, &statbuf, preserve_dates) != 0); + if (status == 0) + status = hold_status; + } + else +- unlink_if_ordinary (tmpname); ++ { ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ if (copyfd >= 0) ++ close (copyfd); ++#endif ++ unlink_if_ordinary (tmpname); ++ } + if (output_file != tmpname) + free (tmpname); + } +@@ -5033,7 +5054,8 @@ copy_main (int argc, char *argv[]) + bfd_boolean show_version = FALSE; + bfd_boolean change_warn = TRUE; + bfd_boolean formats_info = FALSE; +- int c; ++ int c, tmpfd = -1; ++ int copyfd = -1; + struct stat statbuf; + const bfd_arch_info_type *input_arch = NULL; + +@@ -5870,34 +5892,43 @@ copy_main (int argc, char *argv[]) + convert_efi_target (efi); + } + +- if (preserve_dates) +- if (stat (input_filename, & statbuf) < 0) +- fatal (_("warning: could not locate '%s'. System error message: %s"), +- input_filename, strerror (errno)); +- + /* If there is no destination file, or the source and destination files + are the same, then create a temp and rename the result into the input. */ + if (output_filename == NULL + || filename_cmp (input_filename, output_filename) == 0) +- tmpname = make_tempname (input_filename); ++ tmpname = make_tempname (input_filename, &tmpfd); + else + tmpname = output_filename; + +- if (tmpname == NULL) +- fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), +- input_filename, strerror (errno)); ++ if (tmpname == NULL ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ ++ || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) ++#endif ++ ) ++ { ++ fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), ++ input_filename, strerror (errno)); ++ } + +- copy_file (input_filename, tmpname, input_target, output_target, input_arch); ++ copy_file (input_filename, tmpname, tmpfd, &statbuf, input_target, ++ output_target, input_arch); + if (status == 0) + { + if (preserve_dates) + set_times (tmpname, &statbuf); + if (tmpname != output_filename) +- status = (smart_rename (tmpname, input_filename, ++ status = (smart_rename (tmpname, input_filename, copyfd, &statbuf, + preserve_dates) != 0); + } + else +- unlink_if_ordinary (tmpname); ++ { ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ if (copyfd >= 0) ++ close (copyfd); ++#endif ++ unlink_if_ordinary (tmpname); ++ } + + if (tmpname != output_filename) + free (tmpname); +diff -rup binutils.orig/binutils/rename.c binutils-2.35.1/binutils/rename.c +--- binutils.orig/binutils/rename.c 2021-01-29 11:14:51.422571073 +0000 ++++ binutils-2.35.1/binutils/rename.c 2021-01-29 11:15:56.175187361 +0000 +@@ -131,17 +131,55 @@ set_times (const char *destination, cons + #endif + #endif + +-/* Rename FROM to TO, copying if TO is a link. +- Return 0 if ok, -1 if error. */ ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++/* Try to preserve the permission bits and ownership of an existing file when ++ rename overwrites it. FD is the file being renamed and TARGET_STAT has the ++ status of the file that was overwritten. */ ++static void ++try_preserve_permissions (int fd, struct stat *target_stat) ++{ ++ struct stat from_stat; ++ int ret = 0; ++ ++ if (fstat (fd, &from_stat) != 0) ++ return; ++ ++ int from_mode = from_stat.st_mode & 0777; ++ int to_mode = target_stat->st_mode & 0777; ++ ++ /* Fix up permissions before we potentially lose ownership with fchown. ++ Clear the setxid bits because in case the fchown below fails then we don't ++ want to end up with a sxid file owned by the invoking user. If the user ++ hasn't changed or if fchown succeeded, we add back the sxid bits at the ++ end. */ ++ if (from_mode != to_mode) ++ fchmod (fd, to_mode); ++ ++ /* Fix up ownership, this will clear the setxid bits. */ ++ if (from_stat.st_uid != target_stat->st_uid ++ || from_stat.st_gid != target_stat->st_gid) ++ ret = fchown (fd, target_stat->st_uid, target_stat->st_gid); ++ ++ /* Fix up the sxid bits if either the fchown wasn't needed or it ++ succeeded. */ ++ if (ret == 0) ++ fchmod (fd, target_stat->st_mode & 07777); ++} ++#endif ++ ++/* Rename FROM to TO, copying if TO is either a link or is not a regular file. ++ FD is an open file descriptor pointing to FROM that we can use to safely fix ++ up permissions of the file after renaming. TARGET_STAT has the file status ++ that is used to fix up permissions and timestamps after rename. Return 0 if ++ ok, -1 if error and FD is closed before returning. */ + + int +-smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNUSED) ++smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, ++ struct stat *target_stat ATTRIBUTE_UNUSED, ++ int preserve_dates ATTRIBUTE_UNUSED) + { +- bfd_boolean exists; +- struct stat s; + int ret = 0; +- +- exists = lstat (to, &s) == 0; ++ bfd_boolean exists = target_stat != NULL; + + #if defined (_WIN32) && !defined (__CYGWIN32__) + /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but +@@ -158,36 +196,35 @@ smart_rename (const char *from, const ch + unlink (from); + } + #else +- /* Use rename only if TO is not a symbolic link and has +- only one hard link, and we have permission to write to it. */ ++ /* Avoid a full copy and use rename if we can fix up permissions of the ++ file after renaming, i.e.: ++ ++ - TO is not a symbolic link ++ - TO is a regular file with only one hard link ++ - We have permission to write to TO ++ - FD is available to safely fix up permissions to be the same as the file ++ we overwrote with the rename. ++ ++ Note though that the actual file on disk that TARGET_STAT describes may ++ have changed and we're only trying to preserve the status we know about. ++ At no point do we try to interact with the new file changes, so there can ++ only be two outcomes, i.e. either the external file change survives ++ without knowledge of our change (if it happens after the rename syscall) ++ or our rename and permissions fixup survive without any knowledge of the ++ external change. */ + if (! exists +- || (!S_ISLNK (s.st_mode) +- && S_ISREG (s.st_mode) +- && (s.st_mode & S_IWUSR) +- && s.st_nlink == 1) ++ || (fd >= 0 ++ && !S_ISLNK (target_stat->st_mode) ++ && S_ISREG (target_stat->st_mode) ++ && (target_stat->st_mode & S_IWUSR) ++ && target_stat->st_nlink == 1) + ) + { + ret = rename (from, to); + if (ret == 0) + { + if (exists) +- { +- /* Try to preserve the permission bits and ownership of +- TO. First get the mode right except for the setuid +- bit. Then change the ownership. Then fix the setuid +- bit. We do the chmod before the chown because if the +- chown succeeds, and we are a normal user, we won't be +- able to do the chmod afterward. We don't bother to +- fix the setuid bit first because that might introduce +- a fleeting security problem, and because the chown +- will clear the setuid bit anyhow. We only fix the +- setuid bit if the chown succeeds, because we don't +- want to introduce an unexpected setuid file owned by +- the user running objcopy. */ +- chmod (to, s.st_mode & 0777); +- if (chown (to, s.st_uid, s.st_gid) >= 0) +- chmod (to, s.st_mode & 07777); +- } ++ try_preserve_permissions (fd, target_stat); + } + else + { +@@ -203,9 +240,11 @@ smart_rename (const char *from, const ch + non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); + + if (preserve_dates) +- set_times (to, &s); ++ set_times (to, target_stat); + unlink (from); + } ++ if (fd >= 0) ++ close (fd); + #endif /* _WIN32 && !__CYGWIN32__ */ + + return ret; +diff -rup binutils.orig/binutils/ar.c binutils-2.35.1/binutils/ar.c +--- binutils.orig/binutils/ar.c 2021-02-02 13:01:42.257734944 +0000 ++++ binutils-2.35.1/binutils/ar.c 2021-02-02 13:11:13.340958352 +0000 +@@ -25,7 +25,6 @@ + + #include "sysdep.h" + #include "bfd.h" +-#include "libbfd.h" + #include "libiberty.h" + #include "progress.h" + #include "getopt.h" +@@ -1198,10 +1197,8 @@ write_archive (bfd *iarch) + bfd *contents_head = iarch->archive_next; + int ofd = -1; + struct stat target_stat; +- bfd_boolean skip_stat = FALSE; + +- old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1); +- strcpy (old_name, bfd_get_filename (iarch)); ++ old_name = xstrdup (bfd_get_filename (iarch)); + new_name = make_tempname (old_name, &ofd); + + if (new_name == NULL) +@@ -1246,11 +1243,9 @@ write_archive (bfd *iarch) + + #if !defined (_WIN32) || defined (__CYGWIN32__) + ofd = dup (ofd); +- if (iarch == NULL || iarch->iostream == NULL) +- skip_stat = TRUE; +- else if (ofd == -1 || fstat (fileno (iarch->iostream), &target_stat) != 0) +- bfd_fatal (old_name); + #endif ++ if (ofd == -1 || bfd_stat (iarch, &target_stat) != 0) ++ bfd_fatal (old_name); + + if (!bfd_close (obfd)) + bfd_fatal (old_name); +@@ -1261,7 +1256,7 @@ write_archive (bfd *iarch) + /* We don't care if this fails; we might be creating the archive. */ + bfd_close (iarch); + +- if (smart_rename (new_name, old_name, ofd, skip_stat ? NULL : &target_stat, 0) != 0) ++ if (smart_rename (new_name, old_name, ofd, &target_stat, 0) != 0) + xexit (1); + free (old_name); + free (new_name); +Only in binutils-2.35.1/binutils/: ar.c.orig +Only in binutils-2.35.1/binutils/: ar.c.rej +diff -rup binutils.orig/binutils/arsup.c binutils-2.35.1/binutils/arsup.c +--- binutils.orig/binutils/arsup.c 2021-02-02 13:01:42.208735269 +0000 ++++ binutils-2.35.1/binutils/arsup.c 2021-02-02 13:11:55.725678308 +0000 +@@ -42,6 +42,8 @@ extern int deterministic; + + static bfd *obfd; + static char *real_name; ++static char *temp_name; ++static int real_ofd; + static FILE *outfile; + + static void +@@ -149,20 +151,24 @@ maybequit (void) + void + ar_open (char *name, int t) + { +- char *tname = (char *) xmalloc (strlen (name) + 10); +- const char *bname = lbasename (name); +- real_name = name; +- +- /* Prepend tmp- to the beginning, to avoid file-name clashes after +- truncation on filesystems with limited namespaces (DOS). */ +- sprintf (tname, "%.*stmp-%s", (int) (bname - name), name, bname); ++ real_name = xstrdup (name); ++ temp_name = make_tempname (real_name, &real_ofd); ++ ++ if (temp_name == NULL) ++ { ++ fprintf (stderr, _("%s: Can't open temporary file (%s)\n"), ++ program_name, strerror(errno)); ++ maybequit (); ++ return; ++ } ++ +- obfd = bfd_openw (tname, NULL); ++ obfd = bfd_fdopenw (temp_name, NULL, real_ofd); + + if (!obfd) + { + fprintf (stderr, + _("%s: Can't open output archive %s\n"), +- program_name, tname); ++ program_name, temp_name); + + maybequit (); + } +@@ -344,10 +343,9 @@ ar_save (void) + } + else + { +- char *ofilename = xstrdup (bfd_get_filename (obfd)); + bfd_boolean skip_stat = FALSE; + struct stat target_stat; +- int ofd = -1; ++ int ofd = real_ofd; + + if (deterministic > 0) + obfd->flags |= BFD_DETERMINISTIC_OUTPUT; +@@ -355,17 +353,18 @@ ar_save (void) + #if !defined (_WIN32) || defined (__CYGWIN32__) + /* It's OK to fail; at worst it will result in SMART_RENAME using a slow + copy fallback to write the output. */ +- ofd = dup (fileno (obfd->iostream)); +- if (lstat (real_name, &target_stat) != 0) +- skip_stat = TRUE; ++ ofd = dup (ofd); + #endif +- + bfd_close (obfd); + +- smart_rename (ofilename, real_name, ofd, ++ if (ofd == -1 || fstat (ofd, &target_stat) != 0) ++ skip_stat = TRUE; ++ ++ smart_rename (temp_name, real_name, ofd, + skip_stat ? NULL : &target_stat, 0); + obfd = 0; +- free (ofilename); ++ free (temp_name); ++ free (real_name); + } + } + +diff -rup binutils.orig/binutils/objcopy.c binutils-2.35.1/binutils/objcopy.c +--- binutils.orig/binutils/objcopy.c 2021-02-02 13:01:42.214735229 +0000 ++++ binutils-2.35.1/binutils/objcopy.c 2021-02-02 13:13:27.613071192 +0000 +@@ -20,7 +20,6 @@ + + #include "sysdep.h" + #include "bfd.h" +-#include "libbfd.h" + #include "progress.h" + #include "getopt.h" + #include "libiberty.h" +@@ -3733,7 +3732,7 @@ copy_file (const char *input_filename, c + /* To allow us to do "strip *" without dying on the first + non-object file, failures are nonfatal. */ + ibfd = bfd_openr (input_filename, input_target); +- if (ibfd == NULL || fstat (fileno (ibfd->iostream), in_stat) != 0) ++ if (ibfd == NULL || bfd_stat (ibfd, in_stat) != 0) + { + bfd_nonfatal_message (input_filename, NULL, NULL, NULL); + status = 1; +--- binutils.orig/binutils/arsup.c 2021-02-04 10:42:03.265729780 +0000 ++++ binutils-2.35.1/binutils/arsup.c 2021-02-04 10:45:48.439166658 +0000 +@@ -357,8 +357,21 @@ ar_save (void) + #endif + bfd_close (obfd); + +- if (ofd == -1 || fstat (ofd, &target_stat) != 0) +- skip_stat = TRUE; ++ if (lstat (real_name, &target_stat) != 0) ++ { ++ /* The temp file created in ar_open has mode 0600 as per mkstemp. ++ Create the real empty output file here so smart_rename will ++ update the mode according to the process umask. */ ++ obfd = bfd_openw (real_name, NULL); ++ if (obfd == NULL ++ || bfd_stat (obfd, &target_stat) != 0) ++ skip_stat = TRUE; ++ if (obfd != NULL) ++ { ++ bfd_set_format (obfd, bfd_archive); ++ bfd_close (obfd); ++ } ++ } + + smart_rename (temp_name, real_name, ofd, + skip_stat ? NULL : &target_stat, 0); +--- binutils.orig/binutils/rename.c 2021-02-08 11:02:58.767933783 +0000 ++++ binutils-2.35.1/binutils/rename.c 2021-02-08 11:20:37.539179363 +0000 +@@ -179,7 +179,10 @@ smart_rename (const char *from, const ch + int preserve_dates ATTRIBUTE_UNUSED) + { + int ret = 0; +- bfd_boolean exists = target_stat != NULL; ++ struct stat to_stat; ++ bfd_boolean exists; ++ ++ exists = lstat (to, &to_stat) == 0; + + #if defined (_WIN32) && !defined (__CYGWIN32__) + /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but +@@ -214,16 +217,16 @@ smart_rename (const char *from, const ch + external change. */ + if (! exists + || (fd >= 0 +- && !S_ISLNK (target_stat->st_mode) +- && S_ISREG (target_stat->st_mode) +- && (target_stat->st_mode & S_IWUSR) +- && target_stat->st_nlink == 1) ++ && !S_ISLNK (to_stat.st_mode) ++ && S_ISREG (to_stat.st_mode) ++ && (to_stat.st_mode & S_IWUSR) ++ && to_stat.st_nlink == 1) + ) + { + ret = rename (from, to); + if (ret == 0) + { +- if (exists) ++ if (exists && target_stat != NULL) + try_preserve_permissions (fd, target_stat); + } + else +@@ -239,7 +242,7 @@ smart_rename (const char *from, const ch + if (ret != 0) + non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); + +- if (preserve_dates) ++ if (preserve_dates && target_stat != NULL) + set_times (to, target_stat); + unlink (from); + } +diff -rup binutils.orig/binutils/ar.c binutils-2.35.1/binutils/ar.c +--- binutils.orig/binutils/ar.c 2021-03-11 12:38:18.183422774 +0000 ++++ binutils-2.35.1/binutils/ar.c 2021-03-11 12:45:09.279716067 +0000 +@@ -1195,22 +1195,21 @@ write_archive (bfd *iarch) + bfd *obfd; + char *old_name, *new_name; + bfd *contents_head = iarch->archive_next; +- int ofd = -1; +- struct stat target_stat; ++ int tmpfd = -1; + + old_name = xstrdup (bfd_get_filename (iarch)); +- new_name = make_tempname (old_name, &ofd); ++ new_name = make_tempname (old_name, &tmpfd); + + if (new_name == NULL) + bfd_fatal (_("could not create temporary file whilst writing archive")); + + output_filename = new_name; + +- obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), ofd); ++ obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), tmpfd); + + if (obfd == NULL) + { +- close (ofd); ++ close (tmpfd); + bfd_fatal (old_name); + } + +@@ -1241,12 +1240,7 @@ write_archive (bfd *iarch) + if (!bfd_set_archive_head (obfd, contents_head)) + bfd_fatal (old_name); + +-#if !defined (_WIN32) || defined (__CYGWIN32__) +- ofd = dup (ofd); +-#endif +- if (ofd == -1 || bfd_stat (iarch, &target_stat) != 0) +- bfd_fatal (old_name); +- ++ tmpfd = dup (tmpfd); + if (!bfd_close (obfd)) + bfd_fatal (old_name); + +@@ -1256,7 +1250,7 @@ write_archive (bfd *iarch) + /* We don't care if this fails; we might be creating the archive. */ + bfd_close (iarch); + +- if (smart_rename (new_name, old_name, ofd, &target_stat, 0) != 0) ++ if (smart_rename (new_name, old_name, tmpfd, NULL, FALSE) != 0) + xexit (1); + free (old_name); + free (new_name); +diff -rup binutils.orig/binutils/arsup.c binutils-2.35.1/binutils/arsup.c +--- binutils.orig/binutils/arsup.c 2021-03-11 12:38:18.182422781 +0000 ++++ binutils-2.35.1/binutils/arsup.c 2021-03-11 12:47:43.246702325 +0000 +@@ -43,7 +43,7 @@ extern int deterministic; + static bfd *obfd; + static char *real_name; + static char *temp_name; +-static int real_ofd; ++static int temp_fd; + static FILE *outfile; + + static void +@@ -152,7 +152,7 @@ void + ar_open (char *name, int t) + { + real_name = xstrdup (name); +- temp_name = make_tempname (real_name, &real_ofd); ++ temp_name = make_tempname (real_name, &temp_fd); + + if (temp_name == NULL) + { +@@ -162,7 +162,7 @@ ar_open (char *name, int t) + return; + } + +- obfd = bfd_fdopenw (temp_name, NULL, real_ofd); ++ obfd = bfd_fdopenw (temp_name, NULL, temp_fd); + + if (!obfd) + { +@@ -343,29 +343,20 @@ ar_save (void) + } + else + { +- bfd_boolean skip_stat = FALSE; + struct stat target_stat; +- int ofd = real_ofd; + + if (deterministic > 0) + obfd->flags |= BFD_DETERMINISTIC_OUTPUT; + +-#if !defined (_WIN32) || defined (__CYGWIN32__) +- /* It's OK to fail; at worst it will result in SMART_RENAME using a slow +- copy fallback to write the output. */ +- ofd = dup (ofd); +-#endif ++ temp_fd = dup (temp_fd); + bfd_close (obfd); + +- if (lstat (real_name, &target_stat) != 0) ++ if (stat (real_name, &target_stat) != 0) + { + /* The temp file created in ar_open has mode 0600 as per mkstemp. + Create the real empty output file here so smart_rename will + update the mode according to the process umask. */ + obfd = bfd_openw (real_name, NULL); +- if (obfd == NULL +- || bfd_stat (obfd, &target_stat) != 0) +- skip_stat = TRUE; + if (obfd != NULL) + { + bfd_set_format (obfd, bfd_archive); +@@ -373,9 +364,8 @@ ar_save (void) + } + } + +- smart_rename (temp_name, real_name, ofd, +- skip_stat ? NULL : &target_stat, 0); +- obfd = 0; ++ smart_rename (temp_name, real_name, temp_fd, NULL, FALSE); ++ obfd = NULL; + free (temp_name); + free (real_name); + } +diff -rup binutils.orig/binutils/bucomm.h binutils-2.35.1/binutils/bucomm.h +--- binutils.orig/binutils/bucomm.h 2021-03-11 12:38:18.183422774 +0000 ++++ binutils-2.35.1/binutils/bucomm.h 2021-03-11 12:42:22.320815334 +0000 +@@ -71,7 +71,8 @@ extern void print_version (const char *) + /* In rename.c. */ + extern void set_times (const char *, const struct stat *); + +-extern int smart_rename (const char *, const char *, int, struct stat *, int); ++extern int smart_rename (const char *, const char *, int, ++ struct stat *, bfd_boolean); + + + /* In libiberty. */ +diff -rup binutils.orig/binutils/objcopy.c binutils-2.35.1/binutils/objcopy.c +--- binutils.orig/binutils/objcopy.c 2021-03-11 12:38:18.181422787 +0000 ++++ binutils-2.35.1/binutils/objcopy.c 2021-03-11 12:51:09.486344417 +0000 +@@ -4802,12 +4802,7 @@ strip_main (int argc, char *argv[]) + else + tmpname = output_file; + +- if (tmpname == NULL +-#if !defined (_WIN32) || defined (__CYGWIN32__) +- /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ +- || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) +-#endif +- ) ++ if (tmpname == NULL) + { + bfd_nonfatal_message (argv[i], NULL, NULL, + _("could not create temporary file to hold stripped copy")); +@@ -4820,21 +4815,17 @@ strip_main (int argc, char *argv[]) + output_target, NULL); + if (status == 0) + { +- if (preserve_dates) +- set_times (tmpname, &statbuf); + if (output_file != tmpname) +- status = (smart_rename (tmpname, +- output_file ? output_file : argv[i], +- copyfd, &statbuf, preserve_dates) != 0); ++ status = smart_rename (tmpname, ++ output_file ? output_file : argv[i], ++ copyfd, &statbuf, preserve_dates) != 0; + if (status == 0) + status = hold_status; + } + else + { +-#if !defined (_WIN32) || defined (__CYGWIN32__) + if (copyfd >= 0) + close (copyfd); +-#endif + unlink_if_ordinary (tmpname); + } + if (output_file != tmpname) +@@ -5043,8 +5034,9 @@ copy_main (int argc, char *argv[]) + bfd_boolean show_version = FALSE; + bfd_boolean change_warn = TRUE; + bfd_boolean formats_info = FALSE; +- int c, tmpfd = -1; +- int copyfd = -1; ++ int c; ++ int tmpfd = -1; ++ int copyfd; + struct stat statbuf; + const bfd_arch_info_type *input_arch = NULL; + +@@ -5882,19 +5874,19 @@ copy_main (int argc, char *argv[]) + } + + /* If there is no destination file, or the source and destination files +- are the same, then create a temp and rename the result into the input. */ ++ are the same, then create a temp and copy the result into the input. */ ++ copyfd = -1; + if (output_filename == NULL + || filename_cmp (input_filename, output_filename) == 0) +- tmpname = make_tempname (input_filename, &tmpfd); ++ { ++ tmpname = make_tempname (input_filename, &tmpfd); ++ if (tmpfd >= 0) ++ copyfd = dup (tmpfd); ++ } + else + tmpname = output_filename; + +- if (tmpname == NULL +-#if !defined (_WIN32) || defined (__CYGWIN32__) +- /* Retain a copy of TMPFD since we will need it for SMART_RENAME. */ +- || (tmpfd >= 0 && (copyfd = dup (tmpfd)) == -1) +-#endif +- ) ++ if (tmpname == NULL) + { + fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"), + input_filename, strerror (errno)); +@@ -5904,18 +5896,14 @@ copy_main (int argc, char *argv[]) + output_target, input_arch); + if (status == 0) + { +- if (preserve_dates) +- set_times (tmpname, &statbuf); + if (tmpname != output_filename) +- status = (smart_rename (tmpname, input_filename, copyfd, &statbuf, +- preserve_dates) != 0); ++ status = smart_rename (tmpname, input_filename, copyfd, ++ &statbuf, preserve_dates) != 0; + } + else + { +-#if !defined (_WIN32) || defined (__CYGWIN32__) + if (copyfd >= 0) + close (copyfd); +-#endif + unlink_if_ordinary (tmpname); + } + +diff -rup binutils.orig/binutils/rename.c binutils-2.35.1/binutils/rename.c +--- binutils.orig/binutils/rename.c 2021-03-11 12:38:18.183422774 +0000 ++++ binutils-2.35.1/binutils/rename.c 2021-03-11 12:41:41.824081969 +0000 +@@ -30,30 +30,25 @@ + #endif /* HAVE_UTIMES */ + #endif /* ! HAVE_GOOD_UTIME_H */ + +-#if ! defined (_WIN32) || defined (__CYGWIN32__) +-static int simple_copy (const char *, const char *); +- + /* The number of bytes to copy at once. */ + #define COPY_BUF 8192 + +-/* Copy file FROM to file TO, performing no translations. ++/* Copy file FROMFD to file TO, performing no translations. + Return 0 if ok, -1 if error. */ + + static int +-simple_copy (const char *from, const char *to) ++simple_copy (int fromfd, const char *to, ++ struct stat *target_stat ATTRIBUTE_UNUSED) + { +- int fromfd, tofd, nread; ++ int tofd, nread; + int saved; + char buf[COPY_BUF]; + +- fromfd = open (from, O_RDONLY | O_BINARY); +- if (fromfd < 0) ++ if (fromfd < 0 ++ || lseek (fromfd, 0, SEEK_SET) != 0) + return -1; +-#ifdef O_CREAT +- tofd = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0777); +-#else +- tofd = creat (to, 0777); +-#endif ++ ++ tofd = open (to, O_WRONLY | O_TRUNC | O_BINARY); + if (tofd < 0) + { + saved = errno; +@@ -61,6 +56,7 @@ simple_copy (const char *from, const cha + errno = saved; + return -1; + } ++ + while ((nread = read (fromfd, buf, sizeof buf)) > 0) + { + if (write (tofd, buf, nread) != nread) +@@ -72,7 +68,16 @@ simple_copy (const char *from, const cha + return -1; + } + } ++ + saved = errno; ++ ++#if !defined (_WIN32) || defined (__CYGWIN32__) ++ /* Writing to a setuid/setgid file may clear S_ISUID and S_ISGID. ++ Try to restore them, ignoring failure. */ ++ if (target_stat != NULL) ++ fchmod (tofd, target_stat->st_mode); ++#endif ++ + close (fromfd); + close (tofd); + if (nread < 0) +@@ -82,7 +87,6 @@ simple_copy (const char *from, const cha + } + return 0; + } +-#endif /* __CYGWIN32__ or not _WIN32 */ + + /* Set the times of the file DESTINATION to be the same as those in + STATBUF. */ +@@ -91,164 +95,52 @@ void + set_times (const char *destination, const struct stat *statbuf) + { + int result; +- +- { + #ifdef HAVE_GOOD_UTIME_H +- struct utimbuf tb; ++ struct utimbuf tb; + +- tb.actime = statbuf->st_atime; +- tb.modtime = statbuf->st_mtime; +- result = utime (destination, &tb); +-#else /* ! HAVE_GOOD_UTIME_H */ +-#ifndef HAVE_UTIMES +- long tb[2]; +- +- tb[0] = statbuf->st_atime; +- tb[1] = statbuf->st_mtime; +- result = utime (destination, tb); +-#else /* HAVE_UTIMES */ +- struct timeval tv[2]; +- +- tv[0].tv_sec = statbuf->st_atime; +- tv[0].tv_usec = 0; +- tv[1].tv_sec = statbuf->st_mtime; +- tv[1].tv_usec = 0; +- result = utimes (destination, tv); +-#endif /* HAVE_UTIMES */ +-#endif /* ! HAVE_GOOD_UTIME_H */ +- } +- +- if (result != 0) +- non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); +-} +- +-#ifndef S_ISLNK +-#ifdef S_IFLNK +-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) ++ tb.actime = statbuf->st_atime; ++ tb.modtime = statbuf->st_mtime; ++ result = utime (destination, &tb); ++#elif defined HAVE_UTIMES ++ struct timeval tv[2]; ++ ++ tv[0].tv_sec = statbuf->st_atime; ++ tv[0].tv_usec = 0; ++ tv[1].tv_sec = statbuf->st_mtime; ++ tv[1].tv_usec = 0; ++ result = utimes (destination, tv); + #else +-#define S_ISLNK(m) 0 +-#define lstat stat +-#endif +-#endif +- +-#if !defined (_WIN32) || defined (__CYGWIN32__) +-/* Try to preserve the permission bits and ownership of an existing file when +- rename overwrites it. FD is the file being renamed and TARGET_STAT has the +- status of the file that was overwritten. */ +-static void +-try_preserve_permissions (int fd, struct stat *target_stat) +-{ +- struct stat from_stat; +- int ret = 0; +- +- if (fstat (fd, &from_stat) != 0) +- return; ++ long tb[2]; + +- int from_mode = from_stat.st_mode & 0777; +- int to_mode = target_stat->st_mode & 0777; ++ tb[0] = statbuf->st_atime; ++ tb[1] = statbuf->st_mtime; ++ result = utime (destination, tb); ++#endif + +- /* Fix up permissions before we potentially lose ownership with fchown. +- Clear the setxid bits because in case the fchown below fails then we don't +- want to end up with a sxid file owned by the invoking user. If the user +- hasn't changed or if fchown succeeded, we add back the sxid bits at the +- end. */ +- if (from_mode != to_mode) +- fchmod (fd, to_mode); +- +- /* Fix up ownership, this will clear the setxid bits. */ +- if (from_stat.st_uid != target_stat->st_uid +- || from_stat.st_gid != target_stat->st_gid) +- ret = fchown (fd, target_stat->st_uid, target_stat->st_gid); +- +- /* Fix up the sxid bits if either the fchown wasn't needed or it +- succeeded. */ +- if (ret == 0) +- fchmod (fd, target_stat->st_mode & 07777); ++ if (result != 0) ++ non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); + } +-#endif + +-/* Rename FROM to TO, copying if TO is either a link or is not a regular file. +- FD is an open file descriptor pointing to FROM that we can use to safely fix +- up permissions of the file after renaming. TARGET_STAT has the file status +- that is used to fix up permissions and timestamps after rename. Return 0 if +- ok, -1 if error and FD is closed before returning. */ ++/* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL, ++ is used to fix up timestamps. Return 0 if ok, -1 if error. ++ At one time this function renamed files, but file permissions are ++ tricky to update given the number of different schemes used by ++ various systems. So now we just copy. */ + + int +-smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, +- struct stat *target_stat ATTRIBUTE_UNUSED, +- int preserve_dates ATTRIBUTE_UNUSED) ++smart_rename (const char *from, const char *to, int fromfd, ++ struct stat *target_stat, bfd_boolean preserve_dates) + { +- int ret = 0; +- struct stat to_stat; +- bfd_boolean exists; +- +- exists = lstat (to, &to_stat) == 0; +- +-#if defined (_WIN32) && !defined (__CYGWIN32__) +- /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but +- fail instead. Also, chown is not present. */ ++ int ret; + +- if (exists) +- remove (to); +- +- ret = rename (from, to); ++ ret = simple_copy (fromfd, to, target_stat); + if (ret != 0) +- { +- /* We have to clean up here. */ +- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); +- unlink (from); +- } +-#else +- /* Avoid a full copy and use rename if we can fix up permissions of the +- file after renaming, i.e.: ++ non_fatal (_("unable to copy file '%s'; reason: %s"), ++ to, strerror (errno)); + +- - TO is not a symbolic link +- - TO is a regular file with only one hard link +- - We have permission to write to TO +- - FD is available to safely fix up permissions to be the same as the file +- we overwrote with the rename. +- +- Note though that the actual file on disk that TARGET_STAT describes may +- have changed and we're only trying to preserve the status we know about. +- At no point do we try to interact with the new file changes, so there can +- only be two outcomes, i.e. either the external file change survives +- without knowledge of our change (if it happens after the rename syscall) +- or our rename and permissions fixup survive without any knowledge of the +- external change. */ +- if (! exists +- || (fd >= 0 +- && !S_ISLNK (to_stat.st_mode) +- && S_ISREG (to_stat.st_mode) +- && (to_stat.st_mode & S_IWUSR) +- && to_stat.st_nlink == 1) +- ) +- { +- ret = rename (from, to); +- if (ret == 0) +- { +- if (exists && target_stat != NULL) +- try_preserve_permissions (fd, target_stat); +- } +- else +- { +- /* We have to clean up here. */ +- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); +- unlink (from); +- } +- } +- else +- { +- ret = simple_copy (from, to); +- if (ret != 0) +- non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); +- +- if (preserve_dates && target_stat != NULL) +- set_times (to, target_stat); +- unlink (from); +- } +- if (fd >= 0) +- close (fd); +-#endif /* _WIN32 && !__CYGWIN32__ */ ++ if (preserve_dates) ++ set_times (to, target_stat); ++ unlink (from); + + return ret; + } +diff -rup binutils.orig/binutils/objcopy.c binutils-2.35.1/binutils/objcopy.c +--- binutils.orig/binutils/objcopy.c 2021-03-11 13:21:44.780223078 +0000 ++++ binutils-2.35.1/binutils/objcopy.c 2021-03-11 13:23:01.041718818 +0000 +@@ -4798,7 +4798,11 @@ strip_main (int argc, char *argv[]) + + if (output_file == NULL + || filename_cmp (argv[i], output_file) == 0) +- tmpname = make_tempname (argv[i], &tmpfd); ++ { ++ tmpname = make_tempname (argv[i], &tmpfd); ++ if (tmpfd >= 0) ++ copyfd = dup (tmpfd); ++ } + else + tmpname = output_file; + diff --git a/SOURCES/binutils-CVE-2021-20284.patch b/SOURCES/binutils-CVE-2021-20284.patch new file mode 100644 index 0000000..457b652 --- /dev/null +++ b/SOURCES/binutils-CVE-2021-20284.patch @@ -0,0 +1,62 @@ +diff -rup binutils.orig/bfd/elf-bfd.h binutils-2.30/bfd/elf-bfd.h +--- binutils.orig/bfd/elf-bfd.h 2021-05-19 15:05:30.988901261 +0100 ++++ binutils-2.30/bfd/elf-bfd.h 2021-05-19 15:05:55.477815716 +0100 +@@ -1487,7 +1487,7 @@ struct elf_backend_data + bfd_boolean (*init_secondary_reloc_section) (bfd *, Elf_Internal_Shdr *, const char *, unsigned int); + + /* Called when after loading the normal relocs for a section. */ +- bfd_boolean (*slurp_secondary_relocs) (bfd *, asection *, asymbol **); ++ bfd_boolean (*slurp_secondary_relocs) (bfd *, asection *, asymbol **, bfd_boolean); + + /* Called after writing the normal relocs for a section. */ + bfd_boolean (*write_secondary_relocs) (bfd *, asection *); +@@ -2721,7 +2721,7 @@ extern bfd_vma elf32_r_sym (bfd_vma); + extern bfd_boolean _bfd_elf_init_secondary_reloc_section + (bfd *, Elf_Internal_Shdr *, const char *, unsigned int); + extern bfd_boolean _bfd_elf_slurp_secondary_reloc_section +- (bfd *, asection *, asymbol **); ++(bfd *, asection *, asymbol **, bfd_boolean); + extern bfd_boolean _bfd_elf_copy_special_section_fields + (const bfd *, bfd *, const Elf_Internal_Shdr *, Elf_Internal_Shdr *); + extern bfd_boolean _bfd_elf_write_secondary_reloc_section +Only in binutils-2.30/bfd: elf-bfd.h.orig +diff -rup binutils.orig/bfd/elf.c binutils-2.30/bfd/elf.c +--- binutils.orig/bfd/elf.c 2021-05-19 15:05:30.989901257 +0100 ++++ binutils-2.30/bfd/elf.c 2021-05-19 15:05:55.478815712 +0100 +@@ -11663,7 +11663,8 @@ _bfd_elf_init_secondary_reloc_section (b + bfd_boolean + _bfd_elf_slurp_secondary_reloc_section (bfd * abfd, + asection * sec, +- asymbol ** symbols) ++ asymbol ** symbols, ++ bfd_boolean dynamic) + { + const struct elf_backend_data * const ebd = get_elf_backend_data (abfd); + asection * relsec; +@@ -11728,7 +11729,10 @@ _bfd_elf_slurp_secondary_reloc_section ( + continue; + } + +- symcount = bfd_get_symcount (abfd); ++ if (dynamic) ++ symcount = bfd_get_dynamic_symcount (abfd); ++ else ++ symcount = bfd_get_symcount (abfd); + + for (i = 0, internal_reloc = internal_relocs, native_reloc = native_relocs; + i < reloc_count; +Only in binutils-2.30/bfd: elf.c.orig +diff -rup binutils.orig/bfd/elfcode.h binutils-2.30/bfd/elfcode.h +--- binutils.orig/bfd/elfcode.h 2021-05-19 15:05:30.990901254 +0100 ++++ binutils-2.30/bfd/elfcode.h 2021-05-19 15:07:34.098471218 +0100 +@@ -1577,7 +1577,7 @@ elf_slurp_reloc_table (bfd *abfd, + return FALSE; + + if (bed->slurp_secondary_relocs != NULL +- && ! bed->slurp_secondary_relocs (abfd, asect, symbols)) ++ && ! bed->slurp_secondary_relocs (abfd, asect, symbols, dynamic)) + return FALSE; + + asect->relocation = relents; +Only in binutils-2.30/bfd: elfcode.h.orig +Only in binutils-2.30/bfd: elfcode.h.rej diff --git a/SOURCES/binutils-CVE-2021-3487.patch b/SOURCES/binutils-CVE-2021-3487.patch new file mode 100644 index 0000000..f6eb1e5 --- /dev/null +++ b/SOURCES/binutils-CVE-2021-3487.patch @@ -0,0 +1,38 @@ +--- binutils.orig/bfd/dwarf2.c 2021-04-14 14:24:18.945917267 +0100 ++++ binutils-2.30/bfd/dwarf2.c 2021-04-14 14:25:51.908614106 +0100 +@@ -532,6 +532,10 @@ read_section (bfd * abfd, + /* The section may have already been read. */ + if (contents == NULL) + { ++ bfd_size_type amt; ++ asection *msec; ++ ufile_ptr filesize; ++ + msec = bfd_get_section_by_name (abfd, section_name); + if (! msec) + { +@@ -547,10 +551,22 @@ read_section (bfd * abfd, + return FALSE; + } + +- *section_size = msec->rawsize ? msec->rawsize : msec->size; ++ amt = bfd_get_section_limit_octets (abfd, msec); ++ filesize = bfd_get_file_size (abfd); ++ if (amt >= filesize) ++ { ++ /* PR 26946 */ ++ _bfd_error_handler (_("DWARF error: section %s is larger than its filesize! (0x%lx vs 0x%lx)"), ++ section_name, (long) amt, (long) filesize); ++ bfd_set_error (bfd_error_bad_value); ++ return FALSE; ++ } ++ *section_size = amt; ++ + /* Paranoia - alloc one extra so that we can make sure a string + section is NUL terminated. */ +- amt = *section_size + 1; ++ amt += 1; ++ + if (amt == 0) + { + bfd_set_error (bfd_error_no_memory); diff --git a/SOURCES/binutils-clearing-discarded-relocs.patch b/SOURCES/binutils-clearing-discarded-relocs.patch new file mode 100644 index 0000000..dce82a5 --- /dev/null +++ b/SOURCES/binutils-clearing-discarded-relocs.patch @@ -0,0 +1,306 @@ +diff -rup binutils.orig/bfd/cofflink.c binutils-2.30/bfd/cofflink.c +--- binutils.orig/bfd/cofflink.c 2021-06-15 15:38:31.578170486 +0100 ++++ binutils-2.30/bfd/cofflink.c 2021-06-15 15:59:12.394611963 +0100 +@@ -3084,8 +3084,8 @@ _bfd_coff_generic_relocate_section (bfd + then zero this reloc field. */ + if (sec != NULL && discarded_section (sec)) + { +- _bfd_clear_contents (howto, input_bfd, input_section, +- contents + (rel->r_vaddr - input_section->vma)); ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, ++ contents, (rel->r_vaddr - input_section->vma)); + continue; + } + +diff -rup binutils.orig/bfd/dwarf2.c binutils-2.30/bfd/dwarf2.c +--- binutils.orig/bfd/dwarf2.c 2021-06-15 15:38:31.597170370 +0100 ++++ binutils-2.30/bfd/dwarf2.c 2021-06-15 15:42:19.979779516 +0100 +@@ -2865,7 +2865,9 @@ find_abstract_instance_name (struct comp + info_ptr = unit->stash->info_ptr_memory; + info_ptr_end = unit->stash->info_ptr_end; + total = info_ptr_end - info_ptr; +- if (!die_ref || die_ref >= total) ++ if (!die_ref) ++ return TRUE; ++ if (die_ref >= total) + { + _bfd_error_handler + (_("Dwarf Error: Invalid abstract instance DIE ref.")); +diff -rup binutils.orig/bfd/elf-bfd.h binutils-2.30/bfd/elf-bfd.h +--- binutils.orig/bfd/elf-bfd.h 2021-06-15 15:38:31.595170382 +0100 ++++ binutils-2.30/bfd/elf-bfd.h 2021-06-15 15:58:55.365715715 +0100 +@@ -2829,8 +2829,8 @@ extern asection _bfd_elf_large_com_secti + howto, index, contents) \ + { \ + int i_; \ +- _bfd_clear_contents (howto, input_bfd, input_section, \ +- contents + rel[index].r_offset); \ ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, \ ++ contents, rel[index].r_offset); \ + \ + if (bfd_link_relocatable (info) \ + && (input_section->flags & SEC_DEBUGGING)) \ +diff -rup binutils.orig/bfd/elf32-arc.c binutils-2.30/bfd/elf32-arc.c +--- binutils.orig/bfd/elf32-arc.c 2021-06-15 15:38:31.579170480 +0100 ++++ binutils-2.30/bfd/elf32-arc.c 2021-06-15 15:58:28.869877138 +0100 +@@ -1532,8 +1532,8 @@ elf_arc_relocate_section (bfd * outp + /* Clean relocs for symbols in discarded sections. */ + if (sec != NULL && discarded_section (sec)) + { +- _bfd_clear_contents (howto, input_bfd, input_section, +- contents + rel->r_offset); ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, ++ contents, rel->r_offset); + rel->r_offset = rel->r_offset; + rel->r_info = 0; + rel->r_addend = 0; +diff -rup binutils.orig/bfd/elf32-i386.c binutils-2.30/bfd/elf32-i386.c +--- binutils.orig/bfd/elf32-i386.c 2021-06-15 15:38:31.578170486 +0100 ++++ binutils-2.30/bfd/elf32-i386.c 2021-06-15 15:58:12.694975692 +0100 +@@ -2165,8 +2165,8 @@ elf_i386_relocate_section (bfd *output_b + + if (sec != NULL && discarded_section (sec)) + { +- _bfd_clear_contents (howto, input_bfd, input_section, +- contents + rel->r_offset); ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, ++ contents, rel->r_offset); + wrel->r_offset = rel->r_offset; + wrel->r_info = 0; + wrel->r_addend = 0; +diff -rup binutils.orig/bfd/elf32-metag.c binutils-2.30/bfd/elf32-metag.c +--- binutils.orig/bfd/elf32-metag.c 2021-06-15 15:38:31.593170394 +0100 ++++ binutils-2.30/bfd/elf32-metag.c 2021-06-15 15:57:48.039125909 +0100 +@@ -1392,8 +1392,8 @@ metag_final_link_relocate (reloc_howto_t + #define METAG_RELOC_AGAINST_DISCARDED_SECTION(info, input_bfd, input_section, \ + rel, relend, howto, contents) \ + { \ +- _bfd_clear_contents (howto, input_bfd, input_section, \ +- contents + rel->r_offset); \ ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, \ ++ contents, rel->r_offset); \ + \ + if (bfd_link_relocatable (info) \ + && (input_section->flags & SEC_DEBUGGING)) \ +diff -rup binutils.orig/bfd/elf32-nds32.c binutils-2.30/bfd/elf32-nds32.c +--- binutils.orig/bfd/elf32-nds32.c 2021-06-15 15:38:31.589170419 +0100 ++++ binutils-2.30/bfd/elf32-nds32.c 2021-06-15 15:56:30.184600239 +0100 +@@ -12771,18 +12771,17 @@ nds32_elf_get_relocated_section_contents + symbol = *(*parent)->sym_ptr_ptr; + if (symbol->section && discarded_section (symbol->section)) + { +- bfd_byte *p; ++ bfd_vma off; + static reloc_howto_type none_howto + = HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, + "unused", FALSE, 0, 0, FALSE); + +- p = data + (*parent)->address * bfd_octets_per_byte (input_bfd); +- _bfd_clear_contents ((*parent)->howto, input_bfd, input_section, +- p); +- (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; ++ off = (*parent)->address * bfd_octets_per_byte (input_bfd); ++ r = _bfd_clear_contents ((*parent)->howto, input_bfd, ++ input_section, data, off); ++ (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*parent)->addend = 0; + (*parent)->howto = &none_howto; +- r = bfd_reloc_ok; + } + else + r = bfd_perform_relocation (input_bfd, *parent, data, +diff -rup binutils.orig/bfd/elf32-ppc.c binutils-2.30/bfd/elf32-ppc.c +--- binutils.orig/bfd/elf32-ppc.c 2021-06-15 15:38:31.597170370 +0100 ++++ binutils-2.30/bfd/elf32-ppc.c 2021-06-15 15:56:39.367544293 +0100 +@@ -7778,8 +7778,8 @@ ppc_elf_relocate_section (bfd *output_bf + if (r_type < R_PPC_max) + howto = ppc_elf_howto_table[r_type]; + +- _bfd_clear_contents (howto, input_bfd, input_section, +- contents + rel->r_offset); ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, ++ contents, rel->r_offset); + wrel->r_offset = rel->r_offset; + wrel->r_info = 0; + wrel->r_addend = 0; +diff -rup binutils.orig/bfd/elf32-visium.c binutils-2.30/bfd/elf32-visium.c +--- binutils.orig/bfd/elf32-visium.c 2021-06-15 15:38:31.580170473 +0100 ++++ binutils-2.30/bfd/elf32-visium.c 2021-06-15 15:57:29.271240254 +0100 +@@ -616,8 +616,8 @@ visium_elf_relocate_section (bfd *output + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ +- _bfd_clear_contents (howto, input_bfd, input_section, +- contents + rel->r_offset); ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, ++ contents, rel->r_offset); + + rel->r_info = 0; + rel->r_addend = 0; +diff -rup binutils.orig/bfd/elf64-ppc.c binutils-2.30/bfd/elf64-ppc.c +--- binutils.orig/bfd/elf64-ppc.c 2021-06-15 15:38:31.578170486 +0100 ++++ binutils-2.30/bfd/elf64-ppc.c 2021-06-15 15:57:01.529409265 +0100 +@@ -13526,9 +13526,9 @@ ppc64_elf_relocate_section (bfd *output_ + + if (sec != NULL && discarded_section (sec)) + { +- _bfd_clear_contents (ppc64_elf_howto_table[r_type], +- input_bfd, input_section, +- contents + rel->r_offset); ++ (void) _bfd_clear_contents (ppc64_elf_howto_table[r_type], ++ input_bfd, input_section, ++ contents, rel->r_offset); + wrel->r_offset = rel->r_offset; + wrel->r_info = 0; + wrel->r_addend = 0; +diff -rup binutils.orig/bfd/elf64-x86-64.c binutils-2.30/bfd/elf64-x86-64.c +--- binutils.orig/bfd/elf64-x86-64.c 2021-06-15 15:38:31.585170443 +0100 ++++ binutils-2.30/bfd/elf64-x86-64.c 2021-06-15 15:57:09.831358693 +0100 +@@ -2457,8 +2457,8 @@ elf_x86_64_relocate_section (bfd *output + + if (sec != NULL && discarded_section (sec)) + { +- _bfd_clear_contents (howto, input_bfd, input_section, +- contents + rel->r_offset); ++ (void) _bfd_clear_contents (howto, input_bfd, input_section, ++ contents, rel->r_offset); + wrel->r_offset = rel->r_offset; + wrel->r_info = 0; + wrel->r_addend = 0; +diff -rup binutils.orig/bfd/libbfd-in.h binutils-2.30/bfd/libbfd-in.h +--- binutils.orig/bfd/libbfd-in.h 2021-06-15 15:38:31.593170394 +0100 ++++ binutils-2.30/bfd/libbfd-in.h 2021-06-15 15:54:10.856449129 +0100 +@@ -674,8 +674,9 @@ extern bfd_reloc_status_type _bfd_reloca + (reloc_howto_type *, bfd *, bfd_vma, bfd_byte *); + + /* Clear a given location using a given howto. */ +-extern void _bfd_clear_contents (reloc_howto_type *howto, bfd *input_bfd, +- asection *input_section, bfd_byte *location); ++extern bfd_reloc_status_type _bfd_clear_contents ++ (reloc_howto_type *howto, bfd *input_bfd, ++ asection *input_section, bfd_byte *, bfd_vma); + + /* Link stabs in sections in the first pass. */ + +diff -rup binutils.orig/bfd/libbfd.h binutils-2.30/bfd/libbfd.h +--- binutils.orig/bfd/libbfd.h 2021-06-15 15:38:31.581170467 +0100 ++++ binutils-2.30/bfd/libbfd.h 2021-06-15 15:53:55.863540475 +0100 +@@ -679,8 +679,9 @@ extern bfd_reloc_status_type _bfd_reloca + (reloc_howto_type *, bfd *, bfd_vma, bfd_byte *); + + /* Clear a given location using a given howto. */ +-extern void _bfd_clear_contents (reloc_howto_type *howto, bfd *input_bfd, +- asection *input_section, bfd_byte *location); ++extern bfd_reloc_status_type _bfd_clear_contents ++ (reloc_howto_type *howto, bfd *input_bfd, ++ asection *input_section, bfd_byte *, bfd_vma); + + /* Link stabs in sections in the first pass. */ + +diff -rup binutils.orig/bfd/reloc.c binutils-2.30/bfd/reloc.c +--- binutils.orig/bfd/reloc.c 2021-06-15 15:38:31.593170394 +0100 ++++ binutils-2.30/bfd/reloc.c 2021-06-15 15:51:59.449249747 +0100 +@@ -1604,23 +1604,29 @@ _bfd_relocate_contents (reloc_howto_type + relocations against discarded symbols, to make ignorable debug or unwind + information more obvious. */ + +-void ++bfd_reloc_status_type + _bfd_clear_contents (reloc_howto_type *howto, + bfd *input_bfd, + asection *input_section, +- bfd_byte *location) ++ bfd_byte *buf, ++ bfd_vma off) + { + int size; + bfd_vma x = 0; ++ bfd_byte *location; ++ ++ if (!bfd_reloc_offset_in_range (howto, input_bfd, input_section, off)) ++ return bfd_reloc_outofrange; + + /* Get the value we are going to relocate. */ +- size = bfd_get_reloc_size (howto); ++ location = buf + off; ++ size = bfd_get_reloc_size (howto); + switch (size) + { + default: +- abort (); ++ return bfd_reloc_notsupported; + case 0: +- return; ++ return bfd_reloc_ok; + case 1: + x = bfd_get_8 (input_bfd, location); + break; +@@ -1634,7 +1640,7 @@ _bfd_clear_contents (reloc_howto_type *h + #ifdef BFD64 + x = bfd_get_64 (input_bfd, location); + #else +- abort (); ++ return bfd_reloc_notsupported; + #endif + break; + } +@@ -1654,7 +1660,7 @@ _bfd_clear_contents (reloc_howto_type *h + { + default: + case 0: +- abort (); ++ return bfd_reloc_notsupported; + case 1: + bfd_put_8 (input_bfd, x, location); + break; +@@ -1668,10 +1674,12 @@ _bfd_clear_contents (reloc_howto_type *h + #ifdef BFD64 + bfd_put_64 (input_bfd, x, location); + #else +- abort (); ++ return bfd_reloc_notsupported; + #endif + break; + } ++ ++ return bfd_reloc_ok; + } + + /* +@@ -8209,20 +8217,30 @@ bfd_generic_get_relocated_section_conten + goto error_return; + } + +- if (symbol->section && discarded_section (symbol->section)) ++ /* Zap reloc field when the symbol is from a discarded ++ section, ignoring any addend. Do the same when called ++ from bfd_simple_get_relocated_section_contents for ++ undefined symbols in debug sections. This is to keep ++ debug info reasonably sane, in particular so that ++ DW_FORM_ref_addr to another file's .debug_info isn't ++ confused with an offset into the current file's ++ .debug_info. */ ++ if ((symbol->section != NULL && discarded_section (symbol->section)) ++ || (symbol->section == bfd_und_section_ptr ++ && (input_section->flags & SEC_DEBUGGING) != 0 ++ && link_info->input_bfds == link_info->output_bfd)) + { +- bfd_byte *p; ++ bfd_vma off; + static reloc_howto_type none_howto + = HOWTO (0, 0, 0, 0, FALSE, 0, complain_overflow_dont, NULL, + "unused", FALSE, 0, 0, FALSE); + +- p = data + (*parent)->address * bfd_octets_per_byte (input_bfd); +- _bfd_clear_contents ((*parent)->howto, input_bfd, input_section, +- p); ++ off = (*parent)->address * bfd_octets_per_byte (input_bfd); ++ r = _bfd_clear_contents ((*parent)->howto, input_bfd, ++ input_section, data, off); + (*parent)->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr; + (*parent)->addend = 0; + (*parent)->howto = &none_howto; +- r = bfd_reloc_ok; + } + else + r = bfd_perform_relocation (input_bfd, diff --git a/SOURCES/binutils-gold-i386-gnu-property-notes.patch b/SOURCES/binutils-gold-i386-gnu-property-notes.patch new file mode 100644 index 0000000..dacf749 --- /dev/null +++ b/SOURCES/binutils-gold-i386-gnu-property-notes.patch @@ -0,0 +1,355 @@ +diff --git a/gold/i386.cc b/gold/i386.cc +index bf209fe9a86..31161ff091c 100644 +--- a/gold/i386.cc ++++ b/gold/i386.cc +@@ -360,7 +360,11 @@ class Target_i386 : public Sized_target<32, false> + got_(NULL), plt_(NULL), got_plt_(NULL), got_irelative_(NULL), + got_tlsdesc_(NULL), global_offset_table_(NULL), rel_dyn_(NULL), + rel_irelative_(NULL), copy_relocs_(elfcpp::R_386_COPY), +- got_mod_index_offset_(-1U), tls_base_symbol_defined_(false) ++ got_mod_index_offset_(-1U), tls_base_symbol_defined_(false), ++ isa_1_used_(0), isa_1_needed_(0), ++ feature_1_(0), feature_2_used_(0), feature_2_needed_(0), ++ object_isa_1_used_(0), object_feature_1_(0), ++ object_feature_2_used_(0), seen_first_object_(false) + { } + + // Process the relocations to determine unreferenced sections for +@@ -859,6 +863,21 @@ class Target_i386 : public Sized_target<32, false> + this->rel_dyn_section(layout)); + } + ++ // Record a target-specific program property in the .note.gnu.property ++ // section. ++ void ++ record_gnu_property(unsigned int, unsigned int, size_t, ++ const unsigned char*, const Object*); ++ ++ // Merge the target-specific program properties from the current object. ++ void ++ merge_gnu_properties(const Object*); ++ ++ // Finalize the target-specific program properties and add them back to ++ // the layout. ++ void ++ do_finalize_gnu_properties(Layout*) const; ++ + // Information about this specific target which we pass to the + // general Target structure. + static const Target::Target_info i386_info; +@@ -898,6 +917,26 @@ class Target_i386 : public Sized_target<32, false> + unsigned int got_mod_index_offset_; + // True if the _TLS_MODULE_BASE_ symbol has been defined. + bool tls_base_symbol_defined_; ++ ++ // Target-specific program properties, from .note.gnu.property section. ++ // Each bit represents a specific feature. ++ uint32_t isa_1_used_; ++ uint32_t isa_1_needed_; ++ uint32_t feature_1_; ++ uint32_t feature_2_used_; ++ uint32_t feature_2_needed_; ++ // Target-specific properties from the current object. ++ // These bits get ORed into ISA_1_USED_ after all properties for the object ++ // have been processed. But if either is all zeroes (as when the property ++ // is absent from an object), the result should be all zeroes. ++ // (See PR ld/23486.) ++ uint32_t object_isa_1_used_; ++ // These bits get ANDed into FEATURE_1_ after all properties for the object ++ // have been processed. ++ uint32_t object_feature_1_; ++ uint32_t object_feature_2_used_; ++ // Whether we have seen our first object, for use in initializing FEATURE_1_. ++ bool seen_first_object_; + }; + + const Target::Target_info Target_i386::i386_info = +@@ -1042,6 +1081,126 @@ Target_i386::rel_irelative_section(Layout* layout) + return this->rel_irelative_; + } + ++// Record a target-specific program property from the .note.gnu.property ++// section. ++void ++Target_i386::record_gnu_property( ++ unsigned int, unsigned int pr_type, ++ size_t pr_datasz, const unsigned char* pr_data, ++ const Object* object) ++{ ++ uint32_t val = 0; ++ ++ switch (pr_type) ++ { ++ case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_USED: ++ case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED: ++ case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_USED: ++ case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_NEEDED: ++ case elfcpp::GNU_PROPERTY_X86_ISA_1_USED: ++ case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED: ++ case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND: ++ case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED: ++ case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED: ++ if (pr_datasz != 4) ++ { ++ gold_warning(_("%s: corrupt .note.gnu.property section " ++ "(pr_datasz for property %d is not 4)"), ++ object->name().c_str(), pr_type); ++ return; ++ } ++ val = elfcpp::Swap<32, false>::readval(pr_data); ++ break; ++ default: ++ gold_warning(_("%s: unknown program property type 0x%x " ++ "in .note.gnu.property section"), ++ object->name().c_str(), pr_type); ++ break; ++ } ++ ++ switch (pr_type) ++ { ++ case elfcpp::GNU_PROPERTY_X86_ISA_1_USED: ++ this->object_isa_1_used_ |= val; ++ break; ++ case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED: ++ this->isa_1_needed_ |= val; ++ break; ++ case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND: ++ // If we see multiple feature props in one object, OR them together. ++ this->object_feature_1_ |= val; ++ break; ++ case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED: ++ this->object_feature_2_used_ |= val; ++ break; ++ case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED: ++ this->feature_2_needed_ |= val; ++ break; ++ } ++} ++ ++// Merge the target-specific program properties from the current object. ++void ++Target_i386::merge_gnu_properties(const Object*) ++{ ++ if (this->seen_first_object_) ++ { ++ // If any object is missing the ISA_1_USED property, we must omit ++ // it from the output file. ++ if (this->object_isa_1_used_ == 0) ++ this->isa_1_used_ = 0; ++ else if (this->isa_1_used_ != 0) ++ this->isa_1_used_ |= this->object_isa_1_used_; ++ this->feature_1_ &= this->object_feature_1_; ++ // If any object is missing the FEATURE_2_USED property, we must ++ // omit it from the output file. ++ if (this->object_feature_2_used_ == 0) ++ this->feature_2_used_ = 0; ++ else if (this->feature_2_used_ != 0) ++ this->feature_2_used_ |= this->object_feature_2_used_; ++ } ++ else ++ { ++ this->isa_1_used_ = this->object_isa_1_used_; ++ this->feature_1_ = this->object_feature_1_; ++ this->feature_2_used_ = this->object_feature_2_used_; ++ this->seen_first_object_ = true; ++ } ++ this->object_isa_1_used_ = 0; ++ this->object_feature_1_ = 0; ++ this->object_feature_2_used_ = 0; ++} ++ ++static inline void ++add_property(Layout* layout, unsigned int pr_type, uint32_t val) ++{ ++ unsigned char buf[4]; ++ elfcpp::Swap<32, false>::writeval(buf, val); ++ layout->add_gnu_property(elfcpp::NT_GNU_PROPERTY_TYPE_0, pr_type, 4, buf); ++} ++ ++// Finalize the target-specific program properties and add them back to ++// the layout. ++void ++Target_i386::do_finalize_gnu_properties(Layout* layout) const ++{ ++ if (this->isa_1_used_ != 0) ++ add_property(layout, elfcpp::GNU_PROPERTY_X86_ISA_1_USED, ++ this->isa_1_used_); ++ if (this->isa_1_needed_ != 0) ++ add_property(layout, elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED, ++ this->isa_1_needed_); ++ if (this->feature_1_ != 0) ++ add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND, ++ this->feature_1_); ++ if (this->feature_2_used_ != 0) ++ add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED, ++ this->feature_2_used_); ++ if (this->feature_2_needed_ != 0) ++ add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED, ++ this->feature_2_needed_); ++} ++ + // Write the first three reserved words of the .got.plt section. + // The remainder of the section is written while writing the PLT + // in Output_data_plt_i386::do_write. +--- binutils.orig/elfcpp/elfcpp.h 2021-06-23 12:31:04.550738064 +0100 ++++ binutils-2.30/elfcpp/elfcpp.h 2021-06-23 12:33:18.068875079 +0100 +@@ -1008,9 +1008,21 @@ enum + GNU_PROPERTY_STACK_SIZE = 1, + GNU_PROPERTY_NO_COPY_ON_PROTECTED = 2, + GNU_PROPERTY_LOPROC = 0xc0000000, +- GNU_PROPERTY_X86_ISA_1_USED = 0xc0000000, +- GNU_PROPERTY_X86_ISA_1_NEEDED = 0xc0000001, +- GNU_PROPERTY_X86_FEATURE_1_AND = 0xc0000002, ++ GNU_PROPERTY_X86_COMPAT_ISA_1_USED = 0xc0000000, ++ GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED = 0xc0000001, ++ GNU_PROPERTY_X86_UINT32_AND_LO = 0xc0000002, ++ GNU_PROPERTY_X86_UINT32_AND_HI = 0xc0007fff, ++ GNU_PROPERTY_X86_UINT32_OR_LO = 0xc0008000, ++ GNU_PROPERTY_X86_UINT32_OR_HI = 0xc000ffff, ++ GNU_PROPERTY_X86_UINT32_OR_AND_LO = 0xc0010000, ++ GNU_PROPERTY_X86_UINT32_OR_AND_HI = 0xc0017fff, ++ GNU_PROPERTY_X86_COMPAT_2_ISA_1_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 0, ++ GNU_PROPERTY_X86_COMPAT_2_ISA_1_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 0, ++ GNU_PROPERTY_X86_FEATURE_1_AND = GNU_PROPERTY_X86_UINT32_AND_LO + 0, ++ GNU_PROPERTY_X86_ISA_1_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 2, ++ GNU_PROPERTY_X86_FEATURE_2_NEEDED = GNU_PROPERTY_X86_UINT32_OR_LO + 1, ++ GNU_PROPERTY_X86_ISA_1_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 2, ++ GNU_PROPERTY_X86_FEATURE_2_USED = GNU_PROPERTY_X86_UINT32_OR_AND_LO + 1, + GNU_PROPERTY_HIPROC = 0xdfffffff, + GNU_PROPERTY_LOUSER = 0xe0000000, + GNU_PROPERTY_HIUSER = 0xffffffff +--- binutils.orig/gold/i386.cc 2021-07-07 14:15:34.369441519 +0100 ++++ binutils-2.30/gold/i386.cc 2021-07-07 14:36:11.932838272 +0100 +@@ -362,9 +362,8 @@ class Target_i386 : public Sized_target< + rel_irelative_(NULL), copy_relocs_(elfcpp::R_386_COPY), + got_mod_index_offset_(-1U), tls_base_symbol_defined_(false), + isa_1_used_(0), isa_1_needed_(0), +- feature_1_(0), feature_2_used_(0), feature_2_needed_(0), +- object_isa_1_used_(0), object_feature_1_(0), +- object_feature_2_used_(0), seen_first_object_(false) ++ feature_1_(0), object_feature_1_(0), ++ seen_first_object_(false) + { } + + // Process the relocations to determine unreferenced sections for +@@ -866,7 +865,7 @@ class Target_i386 : public Sized_target< + // Record a target-specific program property in the .note.gnu.property + // section. + void +- record_gnu_property(unsigned int, unsigned int, size_t, ++ record_gnu_property(int, int, size_t, + const unsigned char*, const Object*); + + // Merge the target-specific program properties from the current object. +@@ -923,18 +922,10 @@ class Target_i386 : public Sized_target< + uint32_t isa_1_used_; + uint32_t isa_1_needed_; + uint32_t feature_1_; +- uint32_t feature_2_used_; +- uint32_t feature_2_needed_; + // Target-specific properties from the current object. +- // These bits get ORed into ISA_1_USED_ after all properties for the object +- // have been processed. But if either is all zeroes (as when the property +- // is absent from an object), the result should be all zeroes. +- // (See PR ld/23486.) +- uint32_t object_isa_1_used_; + // These bits get ANDed into FEATURE_1_ after all properties for the object + // have been processed. + uint32_t object_feature_1_; +- uint32_t object_feature_2_used_; + // Whether we have seen our first object, for use in initializing FEATURE_1_. + bool seen_first_object_; + }; +@@ -1084,7 +1075,7 @@ Target_i386::rel_irelative_section(Layou + // section. + void + Target_i386::record_gnu_property( +- unsigned int, unsigned int pr_type, ++ int, int pr_type, + size_t pr_datasz, const unsigned char* pr_data, + const Object* object) + { +@@ -1092,15 +1083,9 @@ Target_i386::record_gnu_property( + + switch (pr_type) + { +- case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_USED: +- case elfcpp::GNU_PROPERTY_X86_COMPAT_ISA_1_NEEDED: +- case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_USED: +- case elfcpp::GNU_PROPERTY_X86_COMPAT_2_ISA_1_NEEDED: + case elfcpp::GNU_PROPERTY_X86_ISA_1_USED: + case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED: + case elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND: +- case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED: +- case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED: + if (pr_datasz != 4) + { + gold_warning(_("%s: corrupt .note.gnu.property section " +@@ -1120,7 +1105,7 @@ Target_i386::record_gnu_property( + switch (pr_type) + { + case elfcpp::GNU_PROPERTY_X86_ISA_1_USED: +- this->object_isa_1_used_ |= val; ++ this->isa_1_used_ |= val; + break; + case elfcpp::GNU_PROPERTY_X86_ISA_1_NEEDED: + this->isa_1_needed_ |= val; +@@ -1129,12 +1114,6 @@ Target_i386::record_gnu_property( + // If we see multiple feature props in one object, OR them together. + this->object_feature_1_ |= val; + break; +- case elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED: +- this->object_feature_2_used_ |= val; +- break; +- case elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED: +- this->feature_2_needed_ |= val; +- break; + } + } + +@@ -1143,31 +1122,13 @@ void + Target_i386::merge_gnu_properties(const Object*) + { + if (this->seen_first_object_) +- { +- // If any object is missing the ISA_1_USED property, we must omit +- // it from the output file. +- if (this->object_isa_1_used_ == 0) +- this->isa_1_used_ = 0; +- else if (this->isa_1_used_ != 0) +- this->isa_1_used_ |= this->object_isa_1_used_; +- this->feature_1_ &= this->object_feature_1_; +- // If any object is missing the FEATURE_2_USED property, we must +- // omit it from the output file. +- if (this->object_feature_2_used_ == 0) +- this->feature_2_used_ = 0; +- else if (this->feature_2_used_ != 0) +- this->feature_2_used_ |= this->object_feature_2_used_; +- } ++ this->feature_1_ &= this->object_feature_1_; + else + { +- this->isa_1_used_ = this->object_isa_1_used_; + this->feature_1_ = this->object_feature_1_; +- this->feature_2_used_ = this->object_feature_2_used_; + this->seen_first_object_ = true; + } +- this->object_isa_1_used_ = 0; + this->object_feature_1_ = 0; +- this->object_feature_2_used_ = 0; + } + + static inline void +@@ -1192,12 +1153,6 @@ Target_i386::do_finalize_gnu_properties( + if (this->feature_1_ != 0) + add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_1_AND, + this->feature_1_); +- if (this->feature_2_used_ != 0) +- add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_USED, +- this->feature_2_used_); +- if (this->feature_2_needed_ != 0) +- add_property(layout, elfcpp::GNU_PROPERTY_X86_FEATURE_2_NEEDED, +- this->feature_2_needed_); + } + + // Write the first three reserved words of the .got.plt section. diff --git a/SOURCES/binutils-mark-all-weak-aliases.patch b/SOURCES/binutils-mark-all-weak-aliases.patch new file mode 100644 index 0000000..dd8b47d --- /dev/null +++ b/SOURCES/binutils-mark-all-weak-aliases.patch @@ -0,0 +1,123 @@ +--- binutils.orig/bfd/elflink.c 2021-03-19 13:03:56.464793790 +0000 ++++ binutils-2.30/bfd/elflink.c 2021-03-19 13:05:17.475264954 +0000 +@@ -12825,7 +12825,7 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_i + bfd_boolean *start_stop) + { + unsigned long r_symndx; +- struct elf_link_hash_entry *h; ++ struct elf_link_hash_entry *h, *hw; + + r_symndx = cookie->rel->r_info >> cookie->r_sym_shift; + if (r_symndx == STN_UNDEF) +@@ -12845,12 +12845,16 @@ _bfd_elf_gc_mark_rsec (struct bfd_link_i + || h->root.type == bfd_link_hash_warning) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + h->mark = 1; +- /* If this symbol is weak and there is a non-weak definition, we +- keep the non-weak definition because many backends put +- dynamic reloc info on the non-weak definition for code +- handling copy relocs. */ +- if (h->is_weakalias) +- weakdef (h)->mark = 1; ++ /* Keep all aliases of the symbol too. If an object symbol ++ needs to be copied into .dynbss then all of its aliases ++ should be present as dynamic symbols, not just the one used ++ on the copy relocation. */ ++ hw = h; ++ while (hw->is_weakalias) ++ { ++ hw = hw->u.alias; ++ hw->mark = 1; ++ } + + if (start_stop != NULL) + { +Only in binutils-2.30/ld/testsuite/ld-elf: pr25458.map +Only in binutils-2.30/ld/testsuite/ld-elf: pr25458.rd +Only in binutils-2.30/ld/testsuite/ld-elf: pr25458a.s +Only in binutils-2.30/ld/testsuite/ld-elf: pr25458b.s +diff -rup binutils.orig/ld/testsuite/ld-elf/shared.exp binutils-2.30/ld/testsuite/ld-elf/shared.exp +--- binutils.orig/ld/testsuite/ld-elf/shared.exp 2021-03-19 13:03:56.141795899 +0000 ++++ binutils-2.30/ld/testsuite/ld-elf/shared.exp 2021-03-19 13:08:57.839826387 +0000 +@@ -296,6 +296,38 @@ if { [check_gc_sections_available] } { + "pr22150" \ + ] \ + ] ++ ++ switch -glob $target_triplet { ++ # Exclude targets that don't support copy relocs. ++ bfin-*-* { } ++ frv-*-* { } ++ lm32-*-* { } ++ mips*-*-* { } ++ tic6x-*-* { } ++ xtensa-*-* { } ++ default { ++ run_ld_link_tests [list \ ++ [list \ ++ "Build pr25458.so" \ ++ "$LFLAGS -shared --version-script=pr25458.map" \ ++ "" \ ++ "$AFLAGS_PIC" \ ++ {pr25458b.s} \ ++ {} \ ++ "pr25458.so" \ ++ ] \ ++ [list \ ++ "Build pr25458" \ ++ "$LFLAGS -e _start --gc-sections" \ ++ "tmpdir/pr25458.so" \ ++ "$AFLAGS_PIC" \ ++ {pr25458a.s} \ ++ {{readelf {--dyn-sym --wide} pr25458.rd}} \ ++ "pr25458" \ ++ ] \ ++ ] ++ } ++ } + } + + set ASFLAGS $old_ASFLAGS +--- /dev/null 2021-03-19 08:56:47.991465597 +0000 ++++ binutils-2.30/ld/testsuite/ld-elf/pr25458.map 2021-03-19 13:06:34.859759781 +0000 +@@ -0,0 +1,4 @@ ++FOO { ++global: ++ __environ; _environ; environ; ++}; +--- /dev/null 2021-03-19 08:56:47.991465597 +0000 ++++ binutils-2.30/ld/testsuite/ld-elf/pr25458.rd 2021-03-19 13:06:34.860759774 +0000 +@@ -0,0 +1,10 @@ ++#... ++Symbol table '\.dynsym' contains [0-9]+ entries: ++ +Num: +Value +Size Type +Bind +Vis +Ndx Name ++#... ++ +[0-9]+: [0-9a-f]+ +(4|8)+ OBJECT +(WEAK|GLOBAL) +DEFAULT +[0-9]+ _*environ@FOO \(2\) ++#... ++ +[0-9]+: [0-9a-f]+ +(4|8)+ OBJECT +(WEAK|GLOBAL) +DEFAULT +[0-9]+ _*environ@FOO \(2\) ++#... ++ +[0-9]+: [0-9a-f]+ +(4|8)+ OBJECT +(WEAK|GLOBAL) +DEFAULT +[0-9]+ _*environ@FOO \(2\) ++#pass +--- /dev/null 2021-03-19 08:56:47.991465597 +0000 ++++ binutils-2.30/ld/testsuite/ld-elf/pr25458a.s 2021-03-19 13:06:34.860759774 +0000 +@@ -0,0 +1,6 @@ ++ .text ++ .globl _start ++ .type _start, %function ++_start: ++ .dc.a environ ++ .size _start, .-_start +--- /dev/null 2021-03-19 08:56:47.991465597 +0000 ++++ binutils-2.30/ld/testsuite/ld-elf/pr25458b.s 2021-03-19 13:06:34.860759774 +0000 +@@ -0,0 +1,11 @@ ++ .data ++ .globl __environ ++ .type __environ,%object ++__environ: ++ .dc.a 0 ++ .size __environ, .-__environ ++ .weak _environ ++ .globl _environ ++ .set _environ, __environ ++ .weak environ ++ .set environ, __environ diff --git a/SOURCES/binutils-plugin-as-needed-2.patch b/SOURCES/binutils-plugin-as-needed-2.patch new file mode 100644 index 0000000..f718e66 --- /dev/null +++ b/SOURCES/binutils-plugin-as-needed-2.patch @@ -0,0 +1,212 @@ +diff -rup binutils.orig/bfd/elflink.c binutils-2.30/bfd/elflink.c +--- binutils.orig/bfd/elflink.c 2021-03-18 14:33:03.462295923 +0000 ++++ binutils-2.30/bfd/elflink.c 2021-03-18 14:37:34.110465450 +0000 +@@ -4661,7 +4661,10 @@ error_free_dyn: + object and a shared object. */ + bfd_boolean dynsym = FALSE; + +- if (! dynamic) ++ /* Plugin symbols aren't normal. Don't set def/ref flags. */ ++ if ((abfd->flags & BFD_PLUGIN) != 0) ++ ; ++ else if (!dynamic) + { + if (! definition) + { +@@ -4678,14 +4681,6 @@ error_free_dyn: + h->ref_dynamic = 1; + } + } +- +- /* If the indirect symbol has been forced local, don't +- make the real symbol dynamic. */ +- if ((h == hi || !hi->forced_local) +- && (bfd_link_dll (info) +- || h->def_dynamic +- || h->ref_dynamic)) +- dynsym = TRUE; + } + else + { +@@ -4699,14 +4694,25 @@ error_free_dyn: + h->def_dynamic = 1; + hi->def_dynamic = 1; + } ++ } + +- /* If the indirect symbol has been forced local, don't +- make the real symbol dynamic. */ +- if ((h == hi || !hi->forced_local) +- && (h->def_regular +- || h->ref_regular +- || (h->is_weakalias +- && weakdef (h)->dynindx != -1))) ++ /* If an indirect symbol has been forced local, don't ++ make the real symbol dynamic. */ ++ if (h != hi && hi->forced_local) ++ ; ++ else if (!dynamic) ++ { ++ if (bfd_link_dll (info) ++ || h->def_dynamic ++ || h->ref_dynamic) ++ dynsym = TRUE; ++ } ++ else ++ { ++ if (h->def_regular ++ || h->ref_regular ++ || (h->is_weakalias ++ && weakdef (h)->dynindx != -1)) + dynsym = TRUE; + } + +@@ -4841,6 +4847,10 @@ error_free_dyn: + && !bfd_link_relocatable (info)) + dynsym = FALSE; + ++ /* Nor should we make plugin symbols dynamic. */ ++ if ((abfd->flags & BFD_PLUGIN) != 0) ++ dynsym = FALSE; ++ + if (definition) + { + h->target_internal = isym->st_target_internal; +@@ -4866,8 +4876,8 @@ error_free_dyn: + nondeflt_vers[nondeflt_vers_cnt++] = h; + } + } +- +- if (dynsym && (abfd->flags & BFD_PLUGIN) == 0 && h->dynindx == -1) ++ ++ if (dynsym && h->dynindx == -1) + { + if (! bfd_elf_link_record_dynamic_symbol (info, h)) + goto error_free_vers; +@@ -4897,9 +4907,10 @@ error_free_dyn: + && matched + && definition + && ((dynsym +- && h->ref_regular_nonweak +- && (old_bfd == NULL +- || (old_bfd->flags & BFD_PLUGIN) == 0)) ++ && h->ref_regular_nonweak) ++ || (old_bfd != NULL ++ && (old_bfd->flags & BFD_PLUGIN) != 0 ++ && bind != STB_WEAK) + || (h->ref_dynamic_nonweak + && (elf_dyn_lib_class (abfd) & DYN_AS_NEEDED) != 0 + && !on_needed_list (elf_dt_name (abfd), +Only in binutils-2.30/ld/testsuite/ld-plugin: lto-19.h +Only in binutils-2.30/ld/testsuite/ld-plugin: lto-19a.c +Only in binutils-2.30/ld/testsuite/ld-plugin: lto-19b.c +Only in binutils-2.30/ld/testsuite/ld-plugin: lto-19c.c +diff -rup binutils.orig/ld/testsuite/ld-plugin/lto.exp binutils-2.30/ld/testsuite/ld-plugin/lto.exp +--- binutils.orig/ld/testsuite/ld-plugin/lto.exp 2021-03-18 14:33:02.366303344 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/lto.exp 2021-03-18 14:41:51.419725611 +0000 +@@ -133,7 +133,16 @@ set lto_link_tests [list \ + {lto-15a.c} {} ""] \ + [list "Build liblto-15.a" \ + "$plug_opt" "-flto" \ +- {lto-15b.c} {} "liblto-15.a"] \ ++ {lto-15b.c} {} "liblto-15.a"] \ ++ [list {liblto-19.a} \ ++ "$plug_opt" {-flto -O2 -fPIC} \ ++ {lto-19a.c} {} {liblto-19.a}] \ ++ [list {compile lto-19b.c} \ ++ "$plug_opt" {-flto -O2 -fPIC} \ ++ {lto-19b.c} {} {} {c}] \ ++ [list {liblto-19.so} \ ++ {-shared tmpdir/lto-19b.o tmpdir/liblto-19.a} {-O2 -fPIC} \ ++ {dummy.c} {} {liblto-19.so}] \ + [list "PR ld/12696" \ + "-O2 -flto -fuse-linker-plugin -r -nostdlib" "-O2 -flto" \ + {pr12696-1.cc} {} "pr12696-1r.o" "c++"] \ +@@ -244,6 +253,9 @@ set lto_link_tests [list \ + {dummy.c} \ + {{error_output "pr26267.err"}} \ + "pr26267b"] \ ++ [list {pr26806.so} \ ++ {-shared} {-fpic -O2 -flto} \ ++ {pr26806.c} {{nm {-D} pr26806.d}} {pr26806.so}] \ + ] + + if { [at_least_gcc_version 4 7] } { +@@ -438,6 +450,10 @@ set lto_run_elf_shared_tests [list \ + [list {pr22220b} \ + {-flto -fuse-linker-plugin -Wl,--no-as-needed tmpdir/pr22220lib.so tmpdir/pr22220main.o} {} \ + {dummy.c} {pr22220b.exe} {pass.out} {} {c++}] \ ++ [list {lto-19} \ ++ {-Wl,--as-needed,-R,tmpdir} {} \ ++ {lto-19a.c lto-19b.c lto-19c.c} {lto-19.exe} {pass.out} {-flto -O2} {c} {} \ ++ {tmpdir/liblto-19.so tmpdir/liblto-19.a}] \ + ] + + # LTO run-time tests for ELF +Only in binutils-2.30/ld/testsuite/ld-plugin: pr26806.c +Only in binutils-2.30/ld/testsuite/ld-plugin: pr26806.d +--- /dev/null 2021-03-18 09:46:54.398732368 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/lto-19.h 2021-03-18 14:38:53.903925902 +0000 +@@ -0,0 +1,6 @@ ++struct re_dfa_t { ++ const int *sb_char; ++}; ++struct re_dfa_t *xregcomp (void); ++struct re_dfa_t *rpl_regcomp (void); ++void rpl_regfree (struct re_dfa_t *); +--- /dev/null 2021-03-18 09:46:54.398732368 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/lto-19a.c 2021-03-18 14:38:53.903925902 +0000 +@@ -0,0 +1,19 @@ ++#include ++#include ++#include "lto-19.h" ++ ++static const int utf8_sb_map[4] = { 0x12, 0x34, 0x56, 0x78 }; ++ ++struct re_dfa_t * ++rpl_regcomp () ++{ ++ struct re_dfa_t *dfa = malloc (sizeof (struct re_dfa_t)); ++ dfa->sb_char = utf8_sb_map; ++ return dfa; ++} ++ ++void ++rpl_regfree (struct re_dfa_t *dfa) ++{ ++ puts (dfa->sb_char == utf8_sb_map ? "PASS" : "FAIL"); ++} +--- /dev/null 2021-03-18 09:46:54.398732368 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/lto-19b.c 2021-03-18 14:38:53.903925902 +0000 +@@ -0,0 +1,7 @@ ++#include "lto-19.h" ++ ++struct re_dfa_t * ++xregcomp (void) ++{ ++ return rpl_regcomp (); ++} +--- /dev/null 2021-03-18 09:46:54.398732368 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/lto-19c.c 2021-03-18 14:38:53.903925902 +0000 +@@ -0,0 +1,9 @@ ++#include "lto-19.h" ++ ++int ++main () ++{ ++ struct re_dfa_t *dfa = xregcomp (); ++ rpl_regfree (dfa); ++ return 0; ++} +--- /dev/null 2021-03-18 09:46:54.398732368 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/pr26806.c 2021-03-18 14:39:16.319774345 +0000 +@@ -0,0 +1,2 @@ ++#include ++int foo (int x) { if (__builtin_constant_p (x)) return getpid (); return 0; } +--- /dev/null 2021-03-18 09:46:54.398732368 +0000 ++++ binutils-2.30/ld/testsuite/ld-plugin/pr26806.d 2021-03-18 14:39:16.319774345 +0000 +@@ -0,0 +1,4 @@ ++#failif ++#... ++.* _*getpid[@ ].* ++#... diff --git a/SPECS/binutils.spec b/SPECS/binutils.spec index 7f2e146..d571952 100644 --- a/SPECS/binutils.spec +++ b/SPECS/binutils.spec @@ -43,7 +43,7 @@ Summary: A GNU collection of binary utilities Name: binutils%{?name_cross}%{?_with_debug:-debug} Version: 2.30 -Release: 93%{?dist} +Release: 108%{?dist} License: GPLv3+ URL: https://sourceware.org/binutils @@ -118,6 +118,11 @@ URL: https://sourceware.org/binutils %undefine with_testsuite %endif +# BZ 1924068. Since applications that use the BFD library are +# required to link against the static version, ensure that it retains +# its debug informnation. +%undefine __brp_strip_static_archive + #---------------------------------------------------------------------------- # Note - the Linux Kernel binutils releases are too unstable and contain @@ -553,6 +558,39 @@ Patch83: binutils-common-sym-versioning.patch # Lifetime: Fixed in 2.37 Patch84: binutils-ppc64le-note-merge.patch +# Purpose: Another fix for weak symbol handling with LTO. +# Lifetime: Fixed in 2.36 +Patch85: binutils-plugin-as-needed-2.patch + +# Purpose: Fix a potential vulnerability involing symlink overwriting. +# Lifetime: Fixed in 2.37 +Patch86: binutils-CVE-2021-20197.patch + +# Purpose: Fix copy relocs that refer to weak aliases +# Lifetime: Fixed in 2.35 +Patch87: binutils-mark-all-weak-aliases.patch + +# Purpose: Fix excessive memory consumption when attempting to parse corrupt +# DWARF debug information. +# Lifetime: Fixed in 2.36 +Patch88: binutils-CVE-2021-3487.patch + +# Purpose: Fix illegal memory access when parsing corrupt ELF files. +# Lifetime: Fixed in 2.36 +Patch89: binutils-CVE-2020-35448.patch + +# Purpose: Fixed heap-based buffer overflow in _bfd_elf_slurp_secondary_reloc_section. +# Lifetime: Fixed in 2.36 +Patch90: binutils-CVE-2021-20284.patch + +# Purpose: Fixed the handling of relocations against discarded sections. +# Lifetime: Fixed in 2.34 +Patch91: binutils-clearing-discarded-relocs.patch + +# Purpose: Fix the GOLD linker's generation of .note.gnu.property sections for x86. +# Lifetime: Fixed in 2.37 (maybe) +Patch92: binutils-gold-i386-gnu-property-notes.patch + #---------------------------------------------------------------------------- Provides: bundled(libiberty) @@ -678,6 +716,14 @@ dynamic libraries. Developers starting new projects are strongly encouraged to consider using libelf instead of BFD. +# BZ 1924068. Since applications that use the BFD library are +# required to link against the static version, ensure that it retains +# its debug informnation. +# FIXME: Yes - this is being done twice. I have no idea why this +# second invocation is necessary but if both are not present the +# static archives will be stripped. +%undefine __brp_strip_static_archive + #---------------------------------------------------------------------------- %prep @@ -766,6 +812,14 @@ using libelf instead of BFD. %patch82 -p1 %patch83 -p1 %patch84 -p1 +%patch85 -p1 +%patch86 -p1 +%patch87 -p1 +%patch88 -p1 +%patch89 -p1 +%patch90 -p1 +%patch91 -p1 +%patch92 -p1 # We cannot run autotools as there is an exact requirement of autoconf-2.59. # FIXME - this is no longer true. Maybe try reinstating autotool use ? @@ -1215,6 +1269,49 @@ exit 0 #---------------------------------------------------------------------------- %changelog +* Wed Jul 07 2021 Nick Clifton - 2.30-108 +- Fix thinko in previous delta. (#1970961) + +* Wed Jun 23 2021 Nick Clifton - 2.30-107 +- Fix the GOLD linker's generation of .note.gnu.property sections for x86. (#1970961) + +* Tue Jun 15 2021 Nick Clifton - 2.30-105 +- Fix the handling of relocations against discarded sections. (#1969775) + +* Wed May 19 2021 Nick Clifton - 2.30-104 +- Fix heap-based buffer overflow in _bfd_elf_slurp_secondary_reloc_section. (#1961526) + +* Tue May 04 2021 Nick Clifton - 2.30-103 +- Fix an illegal memory access when parsing a corrupt ELF file. (#1953659) + +* Mon Apr 26 2021 Nick Clifton - 2.30-102 +- Bump NVR to allow rebuild against binutils-2.30-101. + +* Wed Apr 14 2021 Nick Clifton - 2.30-101 +- Fix excessive memory consumption in the BFD librart when parsing corrupt DWARF information. (#1947134) + +* Fri Apr 09 2021 Nick Clifton - 2.30-100 +- Do not strip the static BFD library. (For real this time). (#1924068) +- Remove support for ARM v8.6 ISA. (#1875912) + +* Thu Mar 25 2021 Nick Clifton - 2.30-99 +- Fix bug in previous patch to enable support for ARM v8.6 ISA. (#1875912) + +* Wed Mar 24 2021 Nick Clifton - 2.30-98 +- Do not strip the static BFD library. (#1924068) + +* Tue Mar 23 2021 Nick Clifton - 2.30-97 +- Enable support for ARM v8.6 ISA. (#1875912) + +* Fri Mar 19 2021 Nick Clifton - 2.30-96 +- Fix problems involving copy relocs that refer to weak aliases. (#1935785) + +* Thu Mar 18 2021 Nick Clifton - 2.30-95 +- Fix CVE involivng overwriting symlinks. (#1920642) + +* Thu Mar 18 2021 Nick Clifton - 2.30-94 +- Fix LTO and weak symbols again. (#1930988) + * Thu Feb 18 2021 Nick Clifton - 2.30-93 - Fix merging ppc64le notes. (#1928936)