[binutils-gdb/binutils-2_36-branch] Revert "pr27270 and pr27284, ar segfaults and wrong file mode"

Nick Clifton nickc@sourceware.org
Fri Feb 5 14:14:28 GMT 2021


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=97c8a8cc3f72ffadec511013d9a2f5f853f84887

commit 97c8a8cc3f72ffadec511013d9a2f5f853f84887
Author: Nick Clifton <nickc@redhat.com>
Date:   Fri Feb 5 14:10:21 2021 +0000

    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$

Diff:
---
 binutils/ChangeLog | 16 ----------------
 binutils/ar.c      | 13 +++++++++----
 binutils/arsup.c   | 46 +++++++++++++++++-----------------------------
 binutils/objcopy.c |  3 ++-
 4 files changed, 28 insertions(+), 50 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index c53a4b5eb1e..c7ad3742ccb 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 0ecfa337228..24ff0920f40 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 a60629f6761..837011bdfd2 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 19eb4361446..a5cead1cf8e 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;


More information about the Binutils-cvs mailing list