binutils/backport-0004-CVE-2021-20197.patch
2021-04-16 15:25:09 +08:00

194 lines
5.8 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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