diff --git a/backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch b/backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3b0df1564d9032499fa4a55f87cc15bc2d2a9c2 --- /dev/null +++ b/backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch @@ -0,0 +1,27 @@ +From c180f095f32ca62f138da9bc7fb96cac0365fb5d Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Fri, 5 Feb 2021 12:59:16 +1030 +Subject: [PATCH] PR27345, binutils/arsup.c: lstat() not available on all + targets + +We can just use stat here, the same as is done in ar.c:open_inarch. + + PR 27345 + * arsup.c (ar_save): Use stat rather than lstat. +--- + binutils/arsup.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/binutils/arsup.c b/binutils/arsup.c +index a60629f67618..fa7706f79e50 100644 +--- a/binutils/arsup.c ++++ b/binutils/arsup.c +@@ -357,7 +357,7 @@ ar_save (void) + #endif + 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 diff --git a/backport-PR27349-ar-breaks-symlinks.patch b/backport-PR27349-ar-breaks-symlinks.patch new file mode 100644 index 0000000000000000000000000000000000000000..67635ee08fc9734e9b255d0cdae0bdb2477ca723 --- /dev/null +++ b/backport-PR27349-ar-breaks-symlinks.patch @@ -0,0 +1,59 @@ +From 51a25252814f8b6f88ff5999a091e47ca1dbdeb9 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Fri, 5 Feb 2021 22:33:08 +1030 +Subject: [PATCH] PR27349, ar breaks symlinks + + PR 27349 + * rename.c (smart_rename): Test for existence and type of output + file with lstat. +--- + binutils/rename.c | 17 ++++++++++------- + 1 files changed, 10 insertions(+), 7 deletions(-) + +diff --git a/binutils/rename.c b/binutils/rename.c +index fece31179153..e36b75132ded 100644 +--- a/binutils/rename.c ++++ b/binutils/rename.c +@@ -179,7 +179,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, + 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 char *to, int fd ATTRIBUTE_UNUSED, + 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 char *to, int fd ATTRIBUTE_UNUSED, + 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 --git a/backport-PR27456-lstat-in-rename.c-on-MinGW.patch b/backport-PR27456-lstat-in-rename.c-on-MinGW.patch new file mode 100644 index 0000000000000000000000000000000000000000..d9a890db616b9e2b5c76d40cb524cf95e91a1415 --- /dev/null +++ b/backport-PR27456-lstat-in-rename.c-on-MinGW.patch @@ -0,0 +1,162 @@ +From cca8873dd5a6015d5557ea44bc1ea9c252435a29 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Tue, 23 Feb 2021 09:37:39 +1030 +Subject: [PATCH] PR27456, lstat in rename.c on MinGW + + PR 27456 + * rename.c: Tidy throughout. + (smart_rename): Always copy. Remove windows specific code. +--- + binutils/rename.c | 111 ++++++++++++++------------------------------- + 1 file changed, 35 insertions(+), 76 deletions(-) + +diff --git a/binutils/rename.c b/binutils/rename.c +index 2ff092ee22b5..72a9323d72c4 100644 +--- a/binutils/rename.c ++++ b/binutils/rename.c +@@ -24,14 +24,9 @@ + + #ifdef HAVE_GOOD_UTIME_H + #include +-#else /* ! HAVE_GOOD_UTIME_H */ +-#ifdef HAVE_UTIMES ++#elif defined HAVE_UTIMES + #include +-#endif /* HAVE_UTIMES */ +-#endif /* ! HAVE_GOOD_UTIME_H */ +- +-#if ! defined (_WIN32) || defined (__CYGWIN32__) +-static int simple_copy (const char *, const char *); ++#endif + + /* The number of bytes to copy at once. */ + #define COPY_BUF 8192 +@@ -82,7 +77,6 @@ simple_copy (const char *from, const char *to) + } + return 0; + } +-#endif /* __CYGWIN32__ or not _WIN32 */ + + /* Set the times of the file DESTINATION to be the same as those in + STATBUF. */ +@@ -91,87 +85,52 @@ void + set_times (const char *destination, const struct stat *statbuf) + { + int result; +- +- { + #ifdef HAVE_GOOD_UTIME_H +- 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 */ +- } ++ struct utimbuf tb; ++ ++ 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 ++ long tb[2]; ++ ++ tb[0] = statbuf->st_atime; ++ tb[1] = statbuf->st_mtime; ++ result = utime (destination, tb); ++#endif + + if (result != 0) + non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); + } + +-/* Rename FROM to TO, copying if TO exists. TARGET_STAT has the file status +- that, if non-NULL, is used to fix up timestamps after rename. Return 0 if +- ok, -1 if error. */ ++/* 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, +- struct stat *target_stat ATTRIBUTE_UNUSED) ++ struct stat *target_stat) + { +- 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. */ +- +- if (exists) +- remove (to); ++ int ret; + +- ret = rename (from, to); ++ ret = simple_copy (from, to); + 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 TO does not exist. */ +- if (!exists) +- { +- if ((ret = rename (from, to)) != 0) +- { +- /* 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)); ++ non_fatal (_("unable to copy file '%s'; reason: %s"), ++ to, strerror (errno)); + +- if (target_stat != NULL) +- set_times (to, target_stat); +- unlink (from); +- } +-#endif /* _WIN32 && !__CYGWIN32__ */ ++ if (target_stat != NULL) ++ set_times (to, target_stat); ++ unlink (from); + + return ret; + } diff --git a/backport-Use-make_tempname-file-descriptor-in-smart_rename.patch b/backport-Use-make_tempname-file-descriptor-in-smart_rename.patch new file mode 100644 index 0000000000000000000000000000000000000000..6da004d82db3a1babc5b9461bb0e789aec236aab --- /dev/null +++ b/backport-Use-make_tempname-file-descriptor-in-smart_rename.patch @@ -0,0 +1,320 @@ +From c42c71a1527dd70417d3966dce7ba9edbcf4bdb4 Mon Sep 17 00:00:00 2001 +From: Alan Modra +Date: Tue, 23 Feb 2021 12:10:58 +1030 +Subject: [PATCH] Use make_tempname file descriptor in smart_rename + +This patch makes use of the temp file descriptor in smart_rename +rather than reopening the file. I don't believe there is a security +issue in reopening the file, but this way is one less directory +operation. The patch also attempts to preserve S_ISUID and S_ISGID. + + PR 27456 + * bucomm.h (smart_rename): Update prototype. + * rename.c (smart_rename): Add fromfd and preserve_dates params. + Pass fromfd and target_stat to simple_copy. Call set_times + when preserve_dates. + (simple_copy): Accept fromfd rather than from filename. Add + target_stat param. Rewind fromfd rather than opening. Open + "to" file without O_CREAT. Try to preserve S_ISUID and S_ISGID. + * ar.c (write_archive): Rename ofd to tmpfd. Dup tmpfd before + closing output temp file, and pass tmpfd to smart_rename. + * arsup.c (temp_fd): Rename from real_fd. + (ar_save): Dup temp_fd and pass to smart_rename. + * objcopy.c (strip_main, copy_main): Likewise, and pass + preserve_dates. +--- + binutils/ar.c | 11 ++++++----- + binutils/arsup.c | 9 +++++---- + binutils/bucomm.h | 3 ++- + binutils/objcopy.c | 42 +++++++++++++++++++++++++++++++----------- + binutils/rename.c | 35 +++++++++++++++++++++-------------- + 5 files changed, 65 insertions(+), 35 deletions(-) + +diff --git a/binutils/ar.c b/binutils/ar.c +index 44df48c5c677..fb19b14fec57 100644 +--- a/binutils/ar.c ++++ b/binutils/ar.c +@@ -1252,21 +1252,21 @@ write_archive (bfd *iarch) + bfd *obfd; + char *old_name, *new_name; + bfd *contents_head = iarch->archive_next; +- int ofd = -1; ++ 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); + } + +@@ -1297,6 +1297,7 @@ write_archive (bfd *iarch) + if (!bfd_set_archive_head (obfd, contents_head)) + bfd_fatal (old_name); + ++ tmpfd = dup (tmpfd); + if (!bfd_close (obfd)) + bfd_fatal (old_name); + +@@ -1306,7 +1307,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, NULL) != 0) ++ if (smart_rename (new_name, old_name, tmpfd, NULL, FALSE) != 0) + xexit (1); + free (old_name); + free (new_name); +diff --git a/binutils/arsup.c b/binutils/arsup.c +index f7ce8f0bc820..9982484dbe0c 100644 +--- a/binutils/arsup.c ++++ b/binutils/arsup.c +@@ -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) + { +@@ -348,6 +348,7 @@ ar_save (void) + if (deterministic > 0) + obfd->flags |= BFD_DETERMINISTIC_OUTPUT; + ++ temp_fd = dup (temp_fd); + bfd_close (obfd); + + if (stat (real_name, &target_stat) != 0) +@@ -363,7 +364,7 @@ ar_save (void) + } + } + +- smart_rename (temp_name, real_name, NULL); ++ smart_rename (temp_name, real_name, temp_fd, NULL, FALSE); + obfd = 0; + free (temp_name); + free (real_name); +diff --git a/binutils/bucomm.h b/binutils/bucomm.h +index aa7e33d8cd15..f1ae47fa1b56 100644 +--- a/binutils/bucomm.h ++++ b/binutils/bucomm.h +@@ -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 *, struct stat *); ++extern int smart_rename (const char *, const char *, int, ++ struct stat *, bfd_boolean); + + + /* In libiberty. */ +diff --git a/binutils/objcopy.c b/binutils/objcopy.c +index abbcb7c51907..90ae0bd46bd0 100644 +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c +@@ -4837,6 +4837,7 @@ strip_main (int argc, char *argv[]) + struct stat statbuf; + char *tmpname; + int tmpfd = -1; ++ int copyfd = -1; + + if (get_file_size (argv[i]) < 1) + { +@@ -4846,7 +4847,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; + +@@ -4864,14 +4869,18 @@ strip_main (int argc, char *argv[]) + if (status == 0) + { + if (output_file != tmpname) +- status = (smart_rename (tmpname, +- output_file ? output_file : argv[i], +- preserve_dates ? &statbuf : NULL) != 0); ++ status = smart_rename (tmpname, ++ output_file ? output_file : argv[i], ++ copyfd, &statbuf, preserve_dates) != 0; + if (status == 0) + status = hold_status; + } + else +- unlink_if_ordinary (tmpname); ++ { ++ if (copyfd >= 0) ++ close (copyfd); ++ unlink_if_ordinary (tmpname); ++ } + if (output_file != tmpname) + free (tmpname); + } +@@ -5078,7 +5087,9 @@ copy_main (int argc, char *argv[]) + bfd_boolean formats_info = FALSE; + bfd_boolean use_globalize = FALSE; + bfd_boolean use_keep_global = FALSE; +- int c, tmpfd = -1; ++ int c; ++ int tmpfd = -1; ++ int copyfd; + struct stat statbuf; + const bfd_arch_info_type *input_arch = NULL; + +@@ -5916,10 +5927,15 @@ 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; + +@@ -5934,11 +5950,15 @@ copy_main (int argc, char *argv[]) + if (status == 0) + { + if (tmpname != output_filename) +- status = (smart_rename (tmpname, input_filename, +- preserve_dates ? &statbuf : NULL) != 0); ++ status = smart_rename (tmpname, input_filename, copyfd, ++ &statbuf, preserve_dates) != 0; + } + else +- unlink_if_ordinary (tmpname); ++ { ++ if (copyfd >= 0) ++ close (copyfd); ++ unlink_if_ordinary (tmpname); ++ } + + if (tmpname != output_filename) + free (tmpname); +diff --git a/binutils/rename.c b/binutils/rename.c +index 72a9323d72c4..f688f350d51f 100644 +--- a/binutils/rename.c ++++ b/binutils/rename.c +@@ -31,24 +31,21 @@ + /* 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) + { +- 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; +@@ -56,6 +53,7 @@ simple_copy (const char *from, const char *to) + errno = saved; + return -1; + } ++ + while ((nread = read (fromfd, buf, sizeof buf)) > 0) + { + if (write (tofd, buf, nread) != nread) +@@ -67,7 +65,16 @@ simple_copy (const char *from, const char *to) + 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) +@@ -118,17 +125,17 @@ set_times (const char *destination, const struct stat *statbuf) + various systems. So now we just copy. */ + + int +-smart_rename (const char *from, const char *to, +- struct stat *target_stat) ++smart_rename (const char *from, const char *to, int fromfd, ++ struct stat *target_stat, bfd_boolean preserve_dates) + { + int ret; + +- ret = simple_copy (from, to); ++ ret = simple_copy (fromfd, to, target_stat); + if (ret != 0) + non_fatal (_("unable to copy file '%s'; reason: %s"), + to, strerror (errno)); + +- if (target_stat != NULL) ++ if (preserve_dates) + set_times (to, target_stat); + unlink (from); + diff --git a/backport-binutils-Avoid-renaming-over-existing-files.patch b/backport-binutils-Avoid-renaming-over-existing-files.patch new file mode 100644 index 0000000000000000000000000000000000000000..ea6776c6eebfa2ee51daac967c735b0add15b8a0 --- /dev/null +++ b/backport-binutils-Avoid-renaming-over-existing-files.patch @@ -0,0 +1,353 @@ +From 3685de750e6a091663a0abe42528cad29e960e35 Mon Sep 17 00:00:00 2001 +From: Siddhesh Poyarekar +Date: Fri, 19 Feb 2021 08:05:33 +0530 +Subject: [PATCH] binutils: Avoid renaming over existing files + +Renaming over existing files needs additional care to restore +permissions and ownership, which may not always succeed. +Additionally, other properties of the file such as extended attributes +may be lost, making the operation flaky. + +For predictable results, resort to rename() only if the file does not +exist, otherwise copy the file contents into the existing file. This +ensures that no additional tricks are needed to retain file +properties. + +This also allows dropping of the redundant set_times on the tmpfile in +objcopy/strip since now we no longer rename over existing files. + +binutils/ + + * ar.c (write_archive): Remove TARGET_STAT. Adjust call to + SMART_RENAME. + * arsup.c (ar_save): Likewise. + * objcopy (strip_main): Don't copy TMPFD. Don't set times on + temporary file and adjust call to SMART_RENAME. + (copy_main): Likewise. + * rename.c [!S_ISLNK]: Remove definitions. + (try_preserve_permissions): Remove function. + (smart_rename): Remove FD, PRESERVE_DATES arguments. Use + rename system call only if TO does not exist. + * bucomm.h (smart_rename): Adjust declaration. +--- + binutils/ar.c | 9 +---- + binutils/arsup.c | 13 +------ + binutils/bucomm.h | 2 +- + binutils/objcopy.c | 42 ++++---------------- + binutils/rename.c | 95 +++++----------------------------------------- + 5 files changed, 19 insertions(+), 142 deletions(-) + +diff --git a/binutils/ar.c b/binutils/ar.c +index 0ecfa3372281..44df48c5c677 100644 +--- a/binutils/ar.c ++++ b/binutils/ar.c +@@ -1253,7 +1253,6 @@ write_archive (bfd *iarch) + char *old_name, *new_name; + bfd *contents_head = iarch->archive_next; + int ofd = -1; +- struct stat target_stat; + + old_name = xstrdup (bfd_get_filename (iarch)); + new_name = make_tempname (old_name, &ofd); +@@ -1298,12 +1297,6 @@ 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); +- + if (!bfd_close (obfd)) + bfd_fatal (old_name); + +@@ -1313,7 +1306,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, NULL) != 0) + xexit (1); + free (old_name); + free (new_name); +diff --git a/binutils/arsup.c b/binutils/arsup.c +index fa7706f79e50..f7ce8f0bc820 100644 +--- a/binutils/arsup.c ++++ b/binutils/arsup.c +@@ -343,18 +343,11 @@ 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 + bfd_close (obfd); + + if (stat (real_name, &target_stat) != 0) +@@ -363,9 +356,6 @@ ar_save (void) + 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,8 +363,7 @@ ar_save (void) + } + } + +- smart_rename (temp_name, real_name, ofd, +- skip_stat ? NULL : &target_stat, 0); ++ smart_rename (temp_name, real_name, NULL); + obfd = 0; + free (temp_name); + free (real_name); +diff --git a/binutils/bucomm.h b/binutils/bucomm.h +index 7a0adfae5659..aa7e33d8cd15 100644 +--- a/binutils/bucomm.h ++++ b/binutils/bucomm.h +@@ -71,7 +71,7 @@ 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 *, struct stat *); + + + /* In libiberty. */ +diff --git a/binutils/objcopy.c b/binutils/objcopy.c +index 54a59430f1b4..abbcb7c51907 100644 +--- a/binutils/objcopy.c ++++ b/binutils/objcopy.c +@@ -4837,7 +4837,6 @@ strip_main (int argc, char *argv[]) + struct stat statbuf; + char *tmpname; + int tmpfd = -1; +- int copyfd = -1; + + if (get_file_size (argv[i]) < 1) + { +@@ -4851,12 +4850,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")); +@@ -4869,23 +4863,15 @@ 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); ++ preserve_dates ? &statbuf : NULL) != 0); + if (status == 0) + status = hold_status; + } + else +- { +-#if !defined (_WIN32) || defined (__CYGWIN32__) +- if (copyfd >= 0) +- close (copyfd); +-#endif +- unlink_if_ordinary (tmpname); +- } ++ unlink_if_ordinary (tmpname); + if (output_file != tmpname) + free (tmpname); + } +@@ -5093,7 +5079,6 @@ copy_main (int argc, char *argv[]) + bfd_boolean use_globalize = FALSE; + bfd_boolean use_keep_global = FALSE; + int c, tmpfd = -1; +- int copyfd = -1; + struct stat statbuf; + const bfd_arch_info_type *input_arch = NULL; + +@@ -5938,12 +5923,7 @@ copy_main (int argc, char *argv[]) + 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)); +@@ -5953,20 +5933,12 @@ 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, ++ preserve_dates ? &statbuf : NULL) != 0); + } + else +- { +-#if !defined (_WIN32) || defined (__CYGWIN32__) +- if (copyfd >= 0) +- close (copyfd); +-#endif +- unlink_if_ordinary (tmpname); +- } ++ unlink_if_ordinary (tmpname); + + if (tmpname != output_filename) + free (tmpname); +diff --git a/binutils/rename.c b/binutils/rename.c +index e36b75132ded..2ff092ee22b5 100644 +--- a/binutils/rename.c ++++ b/binutils/rename.c +@@ -122,61 +122,13 @@ set_times (const char *destination, const struct stat *statbuf) + 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) +-#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; +- +- 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. */ ++/* Rename FROM to TO, copying if TO exists. TARGET_STAT has the file status ++ that, if non-NULL, is used to fix up timestamps after rename. Return 0 if ++ ok, -1 if error. */ + + 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, ++ struct stat *target_stat ATTRIBUTE_UNUSED) + { + int ret = 0; + struct stat to_stat; +@@ -199,37 +151,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, + unlink (from); + } + #else +- /* 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 +- || (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) +- ) ++ /* Avoid a full copy and use rename if TO does not exist. */ ++ if (!exists) + { +- ret = rename (from, to); +- if (ret == 0) +- { +- if (exists && target_stat != NULL) +- try_preserve_permissions (fd, target_stat); +- } +- else ++ if ((ret = rename (from, to)) != 0) + { + /* We have to clean up here. */ + non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno)); +@@ -242,12 +167,10 @@ smart_rename (const char *from, const char *to, int fd ATTRIBUTE_UNUSED, + if (ret != 0) + non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno)); + +- if (preserve_dates && target_stat != NULL) ++ if (target_stat != NULL) + set_times (to, target_stat); + unlink (from); + } +- if (fd >= 0) +- close (fd); + #endif /* _WIN32 && !__CYGWIN32__ */ + + return ret; diff --git a/binutils.spec b/binutils.spec index 8c9b39e4de99e456cc8ee132cca0f401334f3918..b592828094a5ceb1ccaac4219272562e96c24952 100644 --- a/binutils.spec +++ b/binutils.spec @@ -1,7 +1,7 @@ Summary: Binary utilities Name: binutils Version: 2.36.1 -Release: 1 +Release: 2 License: GPLv3+ URL: https://sourceware.org/binutils @@ -24,11 +24,16 @@ Patch3: binutils-2.27-aarch64-ifunc.patch #PATCH-CVE-UPSTREAM Patch4: CVE-2019-1010204.patch -Patch5: Fix-a-potential-use-of-an-uninitialised-value-in-the.patch -Patch6: backport-0003-CVE-2021-20197.patch -Patch7: backport-Fix-a-build-problem-when-using-FreeBSD-12.patch -Patch8: backport-0004-CVE-2021-20197.patch -Patch9: backport-CVE-2021-3549.patch +Patch5: Fix-a-potential-use-of-an-uninitialised-value-in-the.patch +Patch6: backport-0003-CVE-2021-20197.patch +Patch7: backport-Fix-a-build-problem-when-using-FreeBSD-12.patch +Patch8: backport-0004-CVE-2021-20197.patch +Patch9: backport-CVE-2021-3549.patch +Patch10: backport-PR27345-binutils-arsup.c-lstat-not-available-on-all.patch +Patch11: backport-PR27349-ar-breaks-symlinks.patch +Patch12: backport-binutils-Avoid-renaming-over-existing-files.patch +Patch13: backport-PR27456-lstat-in-rename.c-on-MinGW.patch +Patch14: backport-Use-make_tempname-file-descriptor-in-smart_rename.patch Provides: bundled(libiberty) @@ -342,6 +347,12 @@ fi %{_infodir}/bfd*info* %changelog +* Tue Sep 14 2021 panxiaohe - 2.36.1-2 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: fix issue about delete symlink when using the strip command + * Mon Jul 5 2021 yixiangzhike - 2.36.1-1 - Type:NA - ID:NA