!93 Update to 2.37

From: @wangchen2020
Reviewed-by: @overweight
Signed-off-by: @overweight
This commit is contained in:
openeuler-ci-bot 2021-12-06 01:29:40 +00:00 committed by Gitee
commit b47ef10df5
12 changed files with 13 additions and 1717 deletions

View File

@ -1,368 +0,0 @@
From 014cc7f849e8209623fc99264814bce7b3b6faf2 Mon Sep 17 00:00:00 2001
From: Siddhesh Poyarekar <siddhesh@gotplt.org>
Date: Mon, 7 Dec 2020 20:48:33 +0530
Subject: [PATCH] binutils: Make smart_rename safe too
smart_rename is capable of handling symlinks by copying and it also
tries to preserve ownership and permissions of files when they're
overwritten during the rename. This is useful in objcopy where the
file properties need to be preserved.
However because smart_rename does this using file names, it leaves a
race window between renames and permission fixes. This change removes
this race window by using file descriptors from the original BFDs that
were used to manipulate these files wherever possible.
The file that is to be renamed is also passed as a file descriptor so
that we use fchown/fchmod on the file descriptor, thus making sure
that we only modify the file we have opened to write. Further, in
case the file is to be overwritten (as is the case in ar or objcopy),
the permissions that need to be restored are taken from the file
descriptor that was opened for input so that integrity of the file
status is maintained all the way through to the rename.
binutils/
* rename.c
* ar.c
(write_archive) [!defined (_WIN32) || defined (__CYGWIN32__)]:
Initialize TARGET_STAT and OFD to pass to SMART_RENAME.
* arsup.c
(ar_save) [defined (_WIN32) || defined (__CYGWIN32__)]:
Likewise.
* bucomm.h (smart_rename): Add new arguments to declaration.
* objcopy.c
(strip_main)[defined (_WIN32) || defined (__CYGWIN32__)]:
Initialize COPYFD and pass to SMART_RENAME.
(copy_main) [defined (_WIN32) || defined (__CYGWIN32__)]:
Likewise.
* rename.c (try_preserve_permissions): New function.
(smart_rename): Use it and add new arguments.
---
binutils/ChangeLog | 18 ++++++++++
binutils/ar.c | 12 ++++++-
binutils/arsup.c | 14 +++++++-
binutils/bucomm.h | 3 +-
binutils/objcopy.c | 42 +++++++++++++++++-----
binutils/rename.c | 101 +++++++++++++++++++++++++++++++++++++----------------
6 files changed, 148 insertions(+), 42 deletions(-)
diff --git a/binutils/ar.c b/binutils/ar.c
index 2253242..6598dd9 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -1254,6 +1254,8 @@ write_archive (bfd *iarch)
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));
@@ -1299,6 +1301,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);
@@ -1308,7 +1318,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 --git a/binutils/arsup.c b/binutils/arsup.c
index a668f27..8b4437f 100644
--- a/binutils/arsup.c
+++ b/binutils/arsup.c
@@ -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 --git a/binutils/bucomm.h b/binutils/bucomm.h
index afb8e09..9613b92 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 *, int);
+extern int smart_rename (const char *, const char *, int, struct stat *, int);
+
/* In libiberty. */
void *xmalloc (size_t);
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index b6cf6ea..04ba95e 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -4815,6 +4815,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)
{
@@ -4828,7 +4829,12 @@ strip_main (int argc, char *argv[])
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"));
@@ -4846,12 +4852,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);
}
@@ -5059,6 +5071,7 @@ 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;
@@ -5903,9 +5916,16 @@ copy_main (int argc, char *argv[])
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, tmpfd, &statbuf, input_target,
output_target, input_arch);
@@ -5914,11 +5934,17 @@ copy_main (int argc, char *argv[])
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 --git a/binutils/rename.c b/binutils/rename.c
index bf3b68d..6b9165e 100644
--- a/binutils/rename.c
+++ b/binutils/rename.c
@@ -131,17 +131,55 @@ set_times (const char *destination, const struct stat *statbuf)
#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 char *to, int preserve_dates ATTRIBUTE_UNU
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 char *to, int preserve_dates ATTRIBUTE_UNU
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;
--
1.8.3.1

View File

@ -1,193 +0,0 @@
From 95b91a043aeaeb546d2fea556d84a2de1e917770 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Mon, 1 Feb 2021 02:04:41 +1030
Subject: [PATCH] pr27270 and pr27284, ar segfaults and wrong file mode
PR 27270
PR 27284
PR 26945
* ar.c: Don't include libbfd.h.
(write_archive): Replace xmalloc+strcpy with xstrdup. Use
bfd_stat rather than fstat on iostream. Move stat and fd tests
outside of _WIN32 ifdef. Delete skip_stat variable.
* arsup.c (temp_name, real_ofd): New static variables.
(ar_open): Use make_tempname and bfd_fdopenw.
(ar_save): Adjust to suit ar_open changes. Move stat output
of _WIN32 ifdef.
* objcopy.c: Don't include libbfd.h.
(copy_file): Use bfd_stat.
---
binutils/ChangeLog | 16 ++++++++++++++++
binutils/ar.c | 13 ++++---------
binutils/arsup.c | 46 +++++++++++++++++++++++++++++-----------------
binutils/objcopy.c | 3 +--
4 files changed, 50 insertions(+), 28 deletions(-)
diff --git a/binutils/ar.c b/binutils/ar.c
index 24ff092..0ecfa33 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -25,7 +25,6 @@
#include "sysdep.h"
#include "bfd.h"
-#include "libbfd.h"
#include "libiberty.h"
#include "progress.h"
#include "getopt.h"
@@ -1255,10 +1254,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)
@@ -1303,11 +1300,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 ((FILE *) 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);
@@ -1318,7 +1313,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);
diff --git a/binutils/arsup.c b/binutils/arsup.c
index 837011b..a60629f 100644
--- a/binutils/arsup.c
+++ b/binutils/arsup.c
@@ -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,27 +151,24 @@ maybequit (void)
void
ar_open (char *name, int t)
{
- char *tname;
- const char *bname = lbasename (name);
- real_name = name;
+ real_name = xstrdup (name);
+ temp_name = make_tempname (real_name, &real_ofd);
- /* Prepend tmp- to the beginning, to avoid file-name clashes after
- truncation on filesystems with limited namespaces (DOS). */
- if (asprintf (&tname, "%.*stmp-%s", (int) (bname - name), name, bname) == -1)
+ if (temp_name == NULL)
{
- fprintf (stderr, _("%s: Can't allocate memory for temp name (%s)\n"),
+ 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,31 @@ 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 ((FILE *) 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 (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);
obfd = 0;
- free (ofilename);
+ free (temp_name);
+ free (real_name);
}
}
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 39a1ccb..0e1047e 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -20,7 +20,6 @@
#include "sysdep.h"
#include "bfd.h"
-#include "libbfd.h"
#include "progress.h"
#include "getopt.h"
#include "libiberty.h"
@@ -3768,7 +3767,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
/* 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 ((FILE *) ibfd->iostream), in_stat) != 0)
+ if (ibfd == NULL || bfd_stat (ibfd, in_stat) != 0)
{
bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
status = 1;
--
1.8.3.1

View File

@ -1,162 +0,0 @@
From 1cfcf3004e1830f8fe9112cfcd15285508d2c2b7 Mon Sep 17 00:00:00 2001
From: Alan Modra <amodra@gmail.com>
Date: Thu, 11 Feb 2021 16:56:42 +1030
Subject: [PATCH] PR27290, PR27293, PR27295, various avr objdump fixes
Adds missing sanity checks for avr device info note, to avoid
potential buffer overflows. Uses bfd_malloc_and_get_section for
sanity checking section size.
PR 27290
PR 27293
PR 27295
* od-elf32_avr.c (elf32_avr_get_note_section_contents): Formatting.
Use bfd_malloc_and_get_section.
(elf32_avr_get_note_desc): Formatting. Return descsz. Sanity
check namesz. Return NULL if descsz is too small. Ensure
string table is terminated.
(elf32_avr_get_device_info): Formatting. Add note_size param.
Sanity check note.
(elf32_avr_dump_mem_usage): Adjust to suit.
---
binutils/od-elf32_avr.c | 66 +++++++++++++++++++++++++++++++------------------
1 files changed, 56 insertions(+), 24 deletions(-)
diff --git a/binutils/od-elf32_avr.c b/binutils/od-elf32_avr.c
index 11800e7..4377a7c 100644
--- a/binutils/od-elf32_avr.c
+++ b/binutils/od-elf32_avr.c
@@ -77,23 +77,29 @@ elf32_avr_filter (bfd *abfd)
return bfd_get_flavour (abfd) == bfd_target_elf_flavour;
}
-static char*
+static char *
elf32_avr_get_note_section_contents (bfd *abfd, bfd_size_type *size)
{
asection *section;
+ bfd_byte *contents;
- if ((section = bfd_get_section_by_name (abfd, ".note.gnu.avr.deviceinfo")) == NULL)
+ section = bfd_get_section_by_name (abfd, ".note.gnu.avr.deviceinfo");
+ if (section == NULL)
return NULL;
- *size = bfd_section_size (section);
- char *contents = (char *) xmalloc (*size);
- bfd_get_section_contents (abfd, section, contents, 0, *size);
+ if (!bfd_malloc_and_get_section (abfd, section, &contents))
+ {
+ free (contents);
+ contents = NULL;
+ }
- return contents;
+ *size = bfd_section_size (section);
+ return (char *) contents;
}
-static char* elf32_avr_get_note_desc (bfd *abfd, char *contents,
- bfd_size_type size)
+static char *
+elf32_avr_get_note_desc (bfd *abfd, char *contents, bfd_size_type size,
+ bfd_size_type *descsz)
{
Elf_External_Note *xnp = (Elf_External_Note *) contents;
Elf_Internal_Note in;
@@ -107,42 +113,54 @@ static char* elf32_avr_get_note_desc (bfd *abfd, char *contents,
if (in.namesz > contents - in.namedata + size)
return NULL;
+ if (in.namesz != 4 || strcmp (in.namedata, "AVR") != 0)
+ return NULL;
+
in.descsz = bfd_get_32 (abfd, xnp->descsz);
in.descdata = in.namedata + align_power (in.namesz, 2);
- if (in.descsz != 0
- && (in.descdata >= contents + size
- || in.descsz > contents - in.descdata + size))
+ if (in.descsz < 6 * sizeof (uint32_t)
+ || in.descdata >= contents + size
+ || in.descsz > contents - in.descdata + size)
return NULL;
- if (strcmp (in.namedata, "AVR") != 0)
- return NULL;
+ /* If the note has a string table, ensure it is 0 terminated. */
+ if (in.descsz > 8 * sizeof (uint32_t))
+ in.descdata[in.descsz - 1] = 0;
+ *descsz = in.descsz;
return in.descdata;
}
static void
elf32_avr_get_device_info (bfd *abfd, char *description,
- deviceinfo *device)
+ bfd_size_type desc_size, deviceinfo *device)
{
if (description == NULL)
return;
const bfd_size_type memory_sizes = 6;
- memcpy (device, description, memory_sizes * sizeof(uint32_t));
- device->name = NULL;
+ memcpy (device, description, memory_sizes * sizeof (uint32_t));
+ desc_size -= memory_sizes * sizeof (uint32_t);
+ if (desc_size < 8)
+ return;
- uint32_t *stroffset_table = ((uint32_t *) description) + memory_sizes;
+ uint32_t *stroffset_table = (uint32_t *) description + memory_sizes;
bfd_size_type stroffset_table_size = bfd_get_32 (abfd, stroffset_table);
- char *str_table = ((char *) stroffset_table) + stroffset_table_size;
/* If the only content is the size itself, there's nothing in the table */
- if (stroffset_table_size == 4)
+ if (stroffset_table_size < 8)
return;
+ if (desc_size <= stroffset_table_size)
+ return;
+ desc_size -= stroffset_table_size;
/* First entry is the device name index. */
uint32_t device_name_index = bfd_get_32 (abfd, stroffset_table + 1);
+ if (device_name_index >= desc_size)
+ return;
+ char *str_table = (char *) stroffset_table + stroffset_table_size;
device->name = str_table + device_name_index;
}
@@ -183,7 +201,7 @@ static void
elf32_avr_dump_mem_usage (bfd *abfd)
{
char *description = NULL;
- bfd_size_type note_section_size = 0;
+ bfd_size_type sec_size, desc_size;
deviceinfo device = { 0, 0, 0, 0, 0, 0, NULL };
device.name = "Unknown";
@@ -192,13 +210,13 @@ elf32_avr_dump_mem_usage (bfd *abfd)
bfd_size_type text_usage = 0;
bfd_size_type eeprom_usage = 0;
- char *contents = elf32_avr_get_note_section_contents (abfd,
- &note_section_size);
+ char *contents = elf32_avr_get_note_section_contents (abfd, &sec_size);
if (contents != NULL)
{
- description = elf32_avr_get_note_desc (abfd, contents, note_section_size);
- elf32_avr_get_device_info (abfd, description, &device);
+ description = elf32_avr_get_note_desc (abfd, contents, sec_size,
+ &desc_size);
+ elf32_avr_get_device_info (abfd, description, desc_size, &device);
}
elf32_avr_get_memory_usage (abfd, &text_usage, &data_usage,
--
1.8.3.1

View File

@ -1,57 +0,0 @@
From b143e2d506bee1020752597f979d5af174edc36d Mon Sep 17 00:00:00 2001
From: Sebastian Huber <sebastian.huber@embedded-brains.de>
Date: Fri, 11 Dec 2020 13:27:45 +0000
Subject: [PATCH] Fix a build problem when using FreeBSD 12.
* ar.c (write_archive): Cast iostream pointer to FILE *.
* arsup.c (ar_save): Likewise.
* objcopy.c (copy_file): Likewise.
---
binutils/ChangeLog | 6 ++++++
binutils/ar.c | 2 +-
binutils/arsup.c | 2 +-
binutils/objcopy.c | 2 +-
4 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/binutils/ar.c b/binutils/ar.c
index 6598dd9..8329223 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -1305,7 +1305,7 @@ write_archive (bfd *iarch)
ofd = dup (ofd);
if (iarch == NULL || iarch->iostream == NULL)
skip_stat = TRUE;
- else if (ofd == -1 || fstat (fileno (iarch->iostream), &target_stat) != 0)
+ else if (ofd == -1 || fstat (fileno ((FILE *) iarch->iostream), &target_stat) != 0)
bfd_fatal (old_name);
#endif
diff --git a/binutils/arsup.c b/binutils/arsup.c
index 8b4437f..dad4174 100644
--- a/binutils/arsup.c
+++ b/binutils/arsup.c
@@ -355,7 +355,7 @@ 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));
+ ofd = dup (fileno ((FILE *) obfd->iostream));
if (lstat (real_name, &target_stat) != 0)
skip_stat = TRUE;
#endif
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 06ecf3e..0ea3ea1 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -3745,7 +3745,7 @@ copy_file (const char *input_filename, const char *output_filename, int ofd,
/* 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 || fstat (fileno ((FILE *) ibfd->iostream), in_stat) != 0)
{
bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
status = 1;
--
1.8.3.1

View File

@ -1,27 +0,0 @@
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

@ -1,59 +0,0 @@
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

@ -1,162 +0,0 @@
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

@ -1,320 +0,0 @@
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

@ -1,353 +0,0 @@
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: 3
Version: 2.37
Release: 1
License: GPLv3+
URL: https://sourceware.org/binutils
@ -25,15 +25,6 @@ Patch3: binutils-2.27-aarch64-ifunc.patch
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
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)
@ -356,6 +347,12 @@ fi
%{_infodir}/bfd*info*
%changelog
* Thu Dec 2 2021 wangchen <wangchen137@huawei.com> - 2.37-1
- Type:requirements
- ID:NA
- SUG:NA
- DESC:update to 2.37
* Tue Sep 14 2021 panxiaohe <panxiaohe@huawei.com> - 2.36.1-3
- Type:bugfix
- ID:NA

View File

@ -16,8 +16,8 @@ index 6a39ef5..ddc3b54 100644
bfdincludedir = @bfdincludedir@
bfdlib_LTLIBRARIES = libbfd.la
bfdinclude_HEADERS = $(BFD_H) $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \
- bfd_stdint.h $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h
+ bfd_stdint.h $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h $(INCDIR)/demangle.h
- $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h
+ $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h $(INCDIR)/demangle.h
else !INSTALL_LIBBFD
# Empty these so that the respective installation directories will not be created.
bfdlibdir =
@ -28,7 +28,7 @@ index 80499d6..09a93b9 100644
@@ -249,7 +249,7 @@ am__can_run_installinfo = \
esac
am__bfdinclude_HEADERS_DIST = $(INCDIR)/plugin-api.h bfd.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h bfd_stdint.h \
$(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \
- $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h
+ $(INCDIR)/diagnostics.h $(INCDIR)/bfdlink.h $(INCDIR)/demangle.h
HEADERS = $(bfdinclude_HEADERS)
@ -38,8 +38,8 @@ index 80499d6..09a93b9 100644
@INSTALL_LIBBFD_FALSE@bfdinclude_HEADERS = $(am__append_2)
@INSTALL_LIBBFD_TRUE@bfdinclude_HEADERS = $(BFD_H) \
@INSTALL_LIBBFD_TRUE@ $(INCDIR)/ansidecl.h $(INCDIR)/symcat.h \
-@INSTALL_LIBBFD_TRUE@ bfd_stdint.h $(INCDIR)/diagnostics.h \
+@INSTALL_LIBBFD_TRUE@ bfd_stdint.h $(INCDIR)/diagnostics.h $(INCDIR)/demangle.h \
-@INSTALL_LIBBFD_TRUE@ $(INCDIR)/diagnostics.h \
+@INSTALL_LIBBFD_TRUE@ $(INCDIR)/diagnostics.h $(INCDIR)/demangle.h \
@INSTALL_LIBBFD_TRUE@ $(INCDIR)/bfdlink.h $(am__append_2)
@INSTALL_LIBBFD_FALSE@rpath_bfdlibdir = @bfdlibdir@
@INSTALL_LIBBFD_FALSE@noinst_LTLIBRARIES = libbfd.la