!87 fix issue about delete symlink when using the strip command

From: @panxh_purple
Reviewed-by: @overweight
Signed-off-by: @overweight
This commit is contained in:
openeuler-ci-bot 2021-09-14 06:07:53 +00:00 committed by Gitee
commit ac0784a979
6 changed files with 938 additions and 6 deletions

View File

@ -0,0 +1,27 @@
From c180f095f32ca62f138da9bc7fb96cac0365fb5d Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
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

View File

@ -0,0 +1,59 @@
From 51a25252814f8b6f88ff5999a091e47ca1dbdeb9 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
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);
}

View File

@ -0,0 +1,162 @@
From cca8873dd5a6015d5557ea44bc1ea9c252435a29 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
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 <utime.h>
-#else /* ! HAVE_GOOD_UTIME_H */
-#ifdef HAVE_UTIMES
+#elif defined HAVE_UTIMES
#include <sys/time.h>
-#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;
}

View File

@ -0,0 +1,320 @@
From c42c71a1527dd70417d3966dce7ba9edbcf4bdb4 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
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);

View File

@ -0,0 +1,353 @@
From 3685de750e6a091663a0abe42528cad29e960e35 Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@gotplt.org>
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;

View File

@ -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 <panxiaohe@huawei.com> - 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 <zhangxingliang3@huawei.com> - 2.36.1-1
- Type:NA
- ID:NA