aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2021-02-05 14:10:21 +0000
committerNick Clifton <nickc@redhat.com>2021-02-05 14:10:21 +0000
commit97c8a8cc3f72ffadec511013d9a2f5f853f84887 (patch)
tree5f365f8e29aa9730bf1ae6294322b15e5ab27fd5
parent86cb5ea5639c548be39f2a1de9c8bcac45f35121 (diff)
downloadbinutils-97c8a8cc3f72ffadec511013d9a2f5f853f84887.zip
binutils-97c8a8cc3f72ffadec511013d9a2f5f853f84887.tar.gz
binutils-97c8a8cc3f72ffadec511013d9a2f5f853f84887.tar.bz2
Revert "pr27270 and pr27284, ar segfaults and wrong file mode"
This reverts commit 95b91a043aeaeb546d2fea556d84a2de1e917770. Given the problems associated with this patch and the others intended to fix the smart_rename CVE, the decision has been taken to$
-rw-r--r--binutils/ChangeLog16
-rw-r--r--binutils/ar.c13
-rw-r--r--binutils/arsup.c46
-rw-r--r--binutils/objcopy.c3
4 files changed, 28 insertions, 50 deletions
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index c53a4b5..c7ad374 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,19 +1,3 @@
-2021-02-03 Alan Modra <amodra@gmail.com>
-
- 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.
-
2021-01-26 Frederic Cambus <fred@statdns.com>
* objcopy.c (copy_main): Fix a double free happening when both
diff --git a/binutils/ar.c b/binutils/ar.c
index 0ecfa33..24ff092 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -25,6 +25,7 @@
#include "sysdep.h"
#include "bfd.h"
+#include "libbfd.h"
#include "libiberty.h"
#include "progress.h"
#include "getopt.h"
@@ -1254,8 +1255,10 @@ write_archive (bfd *iarch)
bfd *contents_head = iarch->archive_next;
int ofd = -1;
struct stat target_stat;
+ bfd_boolean skip_stat = FALSE;
- old_name = xstrdup (bfd_get_filename (iarch));
+ old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
+ strcpy (old_name, bfd_get_filename (iarch));
new_name = make_tempname (old_name, &ofd);
if (new_name == NULL)
@@ -1300,9 +1303,11 @@ write_archive (bfd *iarch)
#if !defined (_WIN32) || defined (__CYGWIN32__)
ofd = dup (ofd);
-#endif
- if (ofd == -1 || bfd_stat (iarch, &target_stat) != 0)
+ 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 (!bfd_close (obfd))
bfd_fatal (old_name);
@@ -1313,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, ofd, &target_stat, 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 a60629f..837011b 100644
--- a/binutils/arsup.c
+++ b/binutils/arsup.c
@@ -42,8 +42,6 @@ extern int deterministic;
static bfd *obfd;
static char *real_name;
-static char *temp_name;
-static int real_ofd;
static FILE *outfile;
static void
@@ -151,24 +149,27 @@ maybequit (void)
void
ar_open (char *name, int t)
{
- real_name = xstrdup (name);
- temp_name = make_tempname (real_name, &real_ofd);
+ char *tname;
+ const char *bname = lbasename (name);
+ real_name = name;
- if (temp_name == NULL)
+ /* 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)
{
- fprintf (stderr, _("%s: Can't open temporary file (%s)\n"),
+ fprintf (stderr, _("%s: Can't allocate memory for temp name (%s)\n"),
program_name, strerror(errno));
maybequit ();
return;
}
- obfd = bfd_fdopenw (temp_name, NULL, real_ofd);
+ obfd = bfd_openw (tname, NULL);
if (!obfd)
{
fprintf (stderr,
_("%s: Can't open output archive %s\n"),
- program_name, temp_name);
+ program_name, tname);
maybequit ();
}
@@ -343,9 +344,10 @@ ar_save (void)
}
else
{
+ char *ofilename = xstrdup (bfd_get_filename (obfd));
bfd_boolean skip_stat = FALSE;
struct stat target_stat;
- int ofd = real_ofd;
+ int ofd = -1;
if (deterministic > 0)
obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
@@ -353,31 +355,17 @@ 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 (ofd);
+ ofd = dup (fileno ((FILE *) obfd->iostream));
+ if (lstat (real_name, &target_stat) != 0)
+ skip_stat = TRUE;
#endif
- bfd_close (obfd);
- 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);
- }
- }
+ bfd_close (obfd);
- smart_rename (temp_name, real_name, ofd,
+ smart_rename (ofilename, real_name, ofd,
skip_stat ? NULL : &target_stat, 0);
obfd = 0;
- free (temp_name);
- free (real_name);
+ free (ofilename);
}
}
diff --git a/binutils/objcopy.c b/binutils/objcopy.c
index 19eb436..a5cead1 100644
--- a/binutils/objcopy.c
+++ b/binutils/objcopy.c
@@ -20,6 +20,7 @@
#include "sysdep.h"
#include "bfd.h"
+#include "libbfd.h"
#include "progress.h"
#include "getopt.h"
#include "libiberty.h"
@@ -3768,7 +3769,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 || bfd_stat (ibfd, in_stat) != 0)
+ if (ibfd == NULL || fstat (fileno ((FILE *) ibfd->iostream), in_stat) != 0)
{
bfd_nonfatal_message (input_filename, NULL, NULL, NULL);
status = 1;