summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch')
-rw-r--r--meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch572
1 files changed, 572 insertions, 0 deletions
diff --git a/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch b/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch
new file mode 100644
index 0000000000..423814f98d
--- /dev/null
+++ b/meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch
@@ -0,0 +1,572 @@
1From d3edaa91d4cf7202ec14342410194841e2f67f12 Mon Sep 17 00:00:00 2001
2From: Alan Modra <amodra@gmail.com>
3Date: Fri, 26 Feb 2021 11:30:32 +1030
4Subject: [PATCH v2] Reinstate various pieces backed out from smart_rename changes
5
6In the interests of a stable release various last minute smart_rename
7patches were backed out of the 2.36 branch. The main reason to
8reinstate some of those backed out changes here is to make necessary
9followup fixes to commit 8e03235147a9 simple cherry-picks from
10mainline. A secondary reason is that ar -M support isn't fixed for
11pr26945 without this patch.
12
13 PR 26945
14 * ar.c: Don't include libbfd.h.
15 (write_archive): Replace xmalloc+strcpy with xstrdup.
16 * arsup.c (temp_name, real_ofd): New static variables.
17 (ar_open): Use make_tempname and bfd_fdopenw.
18 (ar_save): Adjust to suit ar_open changes.
19 * objcopy.c: Don't include libbfd.h.
20 * rename.c: Rename and reorder variables.
21
22(cherry picked from commit 95b91a043aeaeb546d2fea556d84a2de1e917770)
23
24Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d3edaa91d4cf7202ec14342410194841e2f67f12]
25CVE: CVE-2021-20197
26Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
27---
28 bfd/bfd-in2.h | 2 +
29 bfd/opncls.c | 33 ++++++++++
30 binutils/ar.c | 15 +++--
31 binutils/arsup.c | 37 ++++++++----
32 binutils/bucomm.c | 4 +-
33 binutils/bucomm.h | 5 +-
34 binutils/objcopy.c | 37 +++++++-----
35 binutils/rename.c | 148 +++++++++++----------------------------------
36 8 files changed, 133 insertions(+), 148 deletions(-)
37
38diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
39index 2e453c50c18..e53f54a8ab7 100644
40--- a/bfd/bfd-in2.h
41+++ b/bfd/bfd-in2.h
42@@ -588,6 +588,8 @@ bfd *bfd_openr (const char *filename, const char *target);
43
44 bfd *bfd_fdopenr (const char *filename, const char *target, int fd);
45
46+bfd *bfd_fdopenw (const char *filename, const char *target, int fd);
47+
48 bfd *bfd_openstreamr (const char * filename, const char * target,
49 void * stream);
50
51diff --git a/bfd/opncls.c b/bfd/opncls.c
52index a03ad51c8fa..f9da97ed710 100644
53--- a/bfd/opncls.c
54+++ b/bfd/opncls.c
55@@ -370,6 +370,39 @@ bfd_fdopenr (const char *filename, const char *target, int fd)
56 return bfd_fopen (filename, target, mode, fd);
57 }
58
59+/*
60+FUNCTION
61+ bfd_fdopenw
62+
63+SYNOPSIS
64+ bfd *bfd_fdopenw (const char *filename, const char *target, int fd);
65+
66+DESCRIPTION
67+ <<bfd_fdopenw>> is exactly like <<bfd_fdopenr>> with the exception that
68+ the resulting BFD is suitable for output.
69+*/
70+
71+bfd *
72+bfd_fdopenw (const char *filename, const char *target, int fd)
73+{
74+ bfd *out = bfd_fdopenr (filename, target, fd);
75+
76+ if (out != NULL)
77+ {
78+ if (!bfd_write_p (out))
79+ {
80+ close (fd);
81+ _bfd_delete_bfd (out);
82+ out = NULL;
83+ bfd_set_error (bfd_error_invalid_operation);
84+ }
85+ else
86+ out->direction = write_direction;
87+ }
88+
89+ return out;
90+}
91+
92 /*
93 FUNCTION
94 bfd_openstreamr
95diff --git a/binutils/ar.c b/binutils/ar.c
96index 1057db9980e..c33a11e0d70 100644
97--- a/binutils/ar.c
98+++ b/binutils/ar.c
99@@ -1195,20 +1195,23 @@ write_archive (bfd *iarch)
100 bfd *obfd;
101 char *old_name, *new_name;
102 bfd *contents_head = iarch->archive_next;
103+ int ofd = -1;
104
105- old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
106- strcpy (old_name, bfd_get_filename (iarch));
107- new_name = make_tempname (old_name);
108+ old_name = xstrdup (bfd_get_filename (iarch));
109+ new_name = make_tempname (old_name, &ofd);
110
111 if (new_name == NULL)
112 bfd_fatal (_("could not create temporary file whilst writing archive"));
113
114 output_filename = new_name;
115
116- obfd = bfd_openw (new_name, bfd_get_target (iarch));
117+ obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), ofd);
118
119 if (obfd == NULL)
120- bfd_fatal (old_name);
121+ {
122+ close (ofd);
123+ bfd_fatal (old_name);
124+ }
125
126 output_bfd = obfd;
127
128@@ -1246,7 +1249,7 @@ write_archive (bfd *iarch)
129 /* We don't care if this fails; we might be creating the archive. */
130 bfd_close (iarch);
131
132- if (smart_rename (new_name, old_name, 0) != 0)
133+ if (smart_rename (new_name, old_name, NULL) != 0)
134 xexit (1);
135 free (old_name);
136 free (new_name);
137diff --git a/binutils/arsup.c b/binutils/arsup.c
138index 00967c972cd..b8ae4f7ec1a 100644
139--- a/binutils/arsup.c
140+++ b/binutils/arsup.c
141@@ -42,6 +42,8 @@ extern int deterministic;
142
143 static bfd *obfd;
144 static char *real_name;
145+static char *temp_name;
146+static int real_ofd;
147 static FILE *outfile;
148
149 static void
150@@ -149,27 +151,24 @@ maybequit (void)
151 void
152 ar_open (char *name, int t)
153 {
154- char *tname;
155- const char *bname = lbasename (name);
156- real_name = name;
157+ real_name = xstrdup (name);
158+ temp_name = make_tempname (real_name, &real_ofd);
159
160- /* Prepend tmp- to the beginning, to avoid file-name clashes after
161- truncation on filesystems with limited namespaces (DOS). */
162- if (asprintf (&tname, "%.*stmp-%s", (int) (bname - name), name, bname) == -1)
163+ if (temp_name == NULL)
164 {
165- fprintf (stderr, _("%s: Can't allocate memory for temp name (%s)\n"),
166+ fprintf (stderr, _("%s: Can't open temporary file (%s)\n"),
167 program_name, strerror(errno));
168 maybequit ();
169 return;
170 }
171
172- obfd = bfd_openw (tname, NULL);
173+ obfd = bfd_fdopenw (temp_name, NULL, real_ofd);
174
175 if (!obfd)
176 {
177 fprintf (stderr,
178 _("%s: Can't open output archive %s\n"),
179- program_name, tname);
180+ program_name, temp_name);
181
182 maybequit ();
183 }
184@@ -344,16 +343,30 @@ ar_save (void)
185 }
186 else
187 {
188- char *ofilename = xstrdup (bfd_get_filename (obfd));
189+ struct stat target_stat;
190
191 if (deterministic > 0)
192 obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
193
194 bfd_close (obfd);
195
196- smart_rename (ofilename, real_name, 0);
197+ if (stat (real_name, &target_stat) != 0)
198+ {
199+ /* The temp file created in ar_open has mode 0600 as per mkstemp.
200+ Create the real empty output file here so smart_rename will
201+ update the mode according to the process umask. */
202+ obfd = bfd_openw (real_name, NULL);
203+ if (obfd != NULL)
204+ {
205+ bfd_set_format (obfd, bfd_archive);
206+ bfd_close (obfd);
207+ }
208+ }
209+
210+ smart_rename (temp_name, real_name, NULL);
211 obfd = 0;
212- free (ofilename);
213+ free (temp_name);
214+ free (real_name);
215 }
216 }
217
218diff --git a/binutils/bucomm.c b/binutils/bucomm.c
219index 9e6a02843e6..53244201f89 100644
220--- a/binutils/bucomm.c
221+++ b/binutils/bucomm.c
222@@ -532,7 +532,7 @@ template_in_dir (const char *path)
223 as FILENAME. */
224
225 char *
226-make_tempname (const char *filename)
227+make_tempname (const char *filename, int *ofd)
228 {
229 char *tmpname = template_in_dir (filename);
230 int fd;
231@@ -550,7 +550,7 @@ make_tempname (const char *filename)
232 free (tmpname);
233 return NULL;
234 }
235- close (fd);
236+ *ofd = fd;
237 return tmpname;
238 }
239
240diff --git a/binutils/bucomm.h b/binutils/bucomm.h
241index d8318343f78..2b164e0af68 100644
242--- a/binutils/bucomm.h
243+++ b/binutils/bucomm.h
244@@ -51,7 +51,7 @@ int display_info (void);
245
246 void print_arelt_descr (FILE *, bfd *, bfd_boolean, bfd_boolean);
247
248-char *make_tempname (const char *);
249+char *make_tempname (const char *, int *);
250 char *make_tempdir (const char *);
251
252 bfd_vma parse_vma (const char *, const char *);
253@@ -71,7 +71,8 @@ extern void print_version (const char *);
254 /* In rename.c. */
255 extern void set_times (const char *, const struct stat *);
256
257-extern int smart_rename (const char *, const char *, int);
258+extern int smart_rename (const char *, const char *, struct stat *);
259+
260
261 /* In libiberty. */
262 void *xmalloc (size_t);
263diff --git a/binutils/objcopy.c b/binutils/objcopy.c
264index 212e25144e6..5ccbd926610 100644
265--- a/binutils/objcopy.c
266+++ b/binutils/objcopy.c
267@@ -3682,7 +3682,7 @@ set_long_section_mode (bfd *output_bfd, bfd *input_bfd, enum long_section_name_h
268 /* The top-level control. */
269
270 static void
271-copy_file (const char *input_filename, const char *output_filename,
272+copy_file (const char *input_filename, const char *output_filename, int ofd,
273 const char *input_target, const char *output_target,
274 const bfd_arch_info_type *input_arch)
275 {
276@@ -3757,9 +3757,14 @@ copy_file (const char *input_filename, const char *output_filename,
277 else
278 force_output_target = TRUE;
279
280- obfd = bfd_openw (output_filename, output_target);
281+ if (ofd >= 0)
282+ obfd = bfd_fdopenw (output_filename, output_target, ofd);
283+ else
284+ obfd = bfd_openw (output_filename, output_target);
285+
286 if (obfd == NULL)
287 {
288+ close (ofd);
289 bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
290 status = 1;
291 return;
292@@ -3787,13 +3792,19 @@ copy_file (const char *input_filename, const char *output_filename,
293 if (output_target == NULL)
294 output_target = bfd_get_target (ibfd);
295
296- obfd = bfd_openw (output_filename, output_target);
297+ if (ofd >= 0)
298+ obfd = bfd_fdopenw (output_filename, output_target, ofd);
299+ else
300+ obfd = bfd_openw (output_filename, output_target);
301+
302 if (obfd == NULL)
303 {
304+ close (ofd);
305 bfd_nonfatal_message (output_filename, NULL, NULL, NULL);
306 status = 1;
307 return;
308 }
309+
310 /* This is a no-op on non-Coff targets. */
311 set_long_section_mode (obfd, ibfd, long_section_names);
312
313@@ -4746,6 +4757,7 @@ strip_main (int argc, char *argv[])
314 int hold_status = status;
315 struct stat statbuf;
316 char *tmpname;
317+ int tmpfd = -1;
318
319 if (get_file_size (argv[i]) < 1)
320 {
321@@ -4760,7 +4772,7 @@ strip_main (int argc, char *argv[])
322
323 if (output_file == NULL
324 || filename_cmp (argv[i], output_file) == 0)
325- tmpname = make_tempname (argv[i]);
326+ tmpname = make_tempname (argv[i], &tmpfd);
327 else
328 tmpname = output_file;
329
330@@ -4773,15 +4785,13 @@ strip_main (int argc, char *argv[])
331 }
332
333 status = 0;
334- copy_file (argv[i], tmpname, input_target, output_target, NULL);
335+ copy_file (argv[i], tmpname, tmpfd, input_target, output_target, NULL);
336 if (status == 0)
337 {
338- if (preserve_dates)
339- set_times (tmpname, &statbuf);
340 if (output_file != tmpname)
341 status = (smart_rename (tmpname,
342 output_file ? output_file : argv[i],
343- preserve_dates) != 0);
344+ preserve_dates ? &statbuf : NULL) != 0);
345 if (status == 0)
346 status = hold_status;
347 }
348@@ -4993,7 +5003,7 @@ copy_main (int argc, char *argv[])
349 bfd_boolean formats_info = FALSE;
350 bfd_boolean use_globalize = FALSE;
351 bfd_boolean use_keep_global = FALSE;
352- int c;
353+ int c, tmpfd = -1;
354 struct stat statbuf;
355 const bfd_arch_info_type *input_arch = NULL;
356
357@@ -5839,7 +5849,7 @@ copy_main (int argc, char *argv[])
358 are the same, then create a temp and rename the result into the input. */
359 if (output_filename == NULL
360 || filename_cmp (input_filename, output_filename) == 0)
361- tmpname = make_tempname (input_filename);
362+ tmpname = make_tempname (input_filename, &tmpfd);
363 else
364 tmpname = output_filename;
365
366@@ -5847,14 +5857,13 @@ copy_main (int argc, char *argv[])
367 fatal (_("warning: could not create temporary file whilst copying '%s', (error: %s)"),
368 input_filename, strerror (errno));
369
370- copy_file (input_filename, tmpname, input_target, output_target, input_arch);
371+ copy_file (input_filename, tmpname, tmpfd, input_target, output_target,
372+ input_arch);
373 if (status == 0)
374 {
375- if (preserve_dates)
376- set_times (tmpname, &statbuf);
377 if (tmpname != output_filename)
378 status = (smart_rename (tmpname, input_filename,
379- preserve_dates) != 0);
380+ preserve_dates ? &statbuf : NULL) != 0);
381 }
382 else
383 unlink_if_ordinary (tmpname);
384diff --git a/binutils/rename.c b/binutils/rename.c
385index bf3b68d0462..07d44d0f314 100644
386--- a/binutils/rename.c
387+++ b/binutils/rename.c
388@@ -24,14 +24,9 @@
389
390 #ifdef HAVE_GOOD_UTIME_H
391 #include <utime.h>
392-#else /* ! HAVE_GOOD_UTIME_H */
393-#ifdef HAVE_UTIMES
394+#elif defined HAVE_UTIMES
395 #include <sys/time.h>
396-#endif /* HAVE_UTIMES */
397-#endif /* ! HAVE_GOOD_UTIME_H */
398-
399-#if ! defined (_WIN32) || defined (__CYGWIN32__)
400-static int simple_copy (const char *, const char *);
401+#endif
402
403 /* The number of bytes to copy at once. */
404 #define COPY_BUF 8192
405@@ -82,7 +77,6 @@ simple_copy (const char *from, const char *to)
406 }
407 return 0;
408 }
409-#endif /* __CYGWIN32__ or not _WIN32 */
410
411 /* Set the times of the file DESTINATION to be the same as those in
412 STATBUF. */
413@@ -91,122 +85,52 @@ void
414 set_times (const char *destination, const struct stat *statbuf)
415 {
416 int result;
417-
418- {
419 #ifdef HAVE_GOOD_UTIME_H
420- struct utimbuf tb;
421-
422- tb.actime = statbuf->st_atime;
423- tb.modtime = statbuf->st_mtime;
424- result = utime (destination, &tb);
425-#else /* ! HAVE_GOOD_UTIME_H */
426-#ifndef HAVE_UTIMES
427- long tb[2];
428-
429- tb[0] = statbuf->st_atime;
430- tb[1] = statbuf->st_mtime;
431- result = utime (destination, tb);
432-#else /* HAVE_UTIMES */
433- struct timeval tv[2];
434-
435- tv[0].tv_sec = statbuf->st_atime;
436- tv[0].tv_usec = 0;
437- tv[1].tv_sec = statbuf->st_mtime;
438- tv[1].tv_usec = 0;
439- result = utimes (destination, tv);
440-#endif /* HAVE_UTIMES */
441-#endif /* ! HAVE_GOOD_UTIME_H */
442- }
443+ struct utimbuf tb;
444+
445+ tb.actime = statbuf->st_atime;
446+ tb.modtime = statbuf->st_mtime;
447+ result = utime (destination, &tb);
448+#elif defined HAVE_UTIMES
449+ struct timeval tv[2];
450+
451+ tv[0].tv_sec = statbuf->st_atime;
452+ tv[0].tv_usec = 0;
453+ tv[1].tv_sec = statbuf->st_mtime;
454+ tv[1].tv_usec = 0;
455+ result = utimes (destination, tv);
456+#else
457+ long tb[2];
458+
459+ tb[0] = statbuf->st_atime;
460+ tb[1] = statbuf->st_mtime;
461+ result = utime (destination, tb);
462+#endif
463
464 if (result != 0)
465 non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
466 }
467
468-#ifndef S_ISLNK
469-#ifdef S_IFLNK
470-#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
471-#else
472-#define S_ISLNK(m) 0
473-#define lstat stat
474-#endif
475-#endif
476-
477-/* Rename FROM to TO, copying if TO is a link.
478- Return 0 if ok, -1 if error. */
479+/* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL,
480+ is used to fix up timestamps. Return 0 if ok, -1 if error.
481+ At one time this function renamed files, but file permissions are
482+ tricky to update given the number of different schemes used by
483+ various systems. So now we just copy. */
484
485 int
486-smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNUSED)
487+smart_rename (const char *from, const char *to,
488+ struct stat *target_stat)
489 {
490- bfd_boolean exists;
491- struct stat s;
492- int ret = 0;
493-
494- exists = lstat (to, &s) == 0;
495-
496-#if defined (_WIN32) && !defined (__CYGWIN32__)
497- /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
498- fail instead. Also, chown is not present. */
499+ int ret;
500
501- if (exists)
502- remove (to);
503-
504- ret = rename (from, to);
505+ ret = simple_copy (from, to);
506 if (ret != 0)
507- {
508- /* We have to clean up here. */
509- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
510- unlink (from);
511- }
512-#else
513- /* Use rename only if TO is not a symbolic link and has
514- only one hard link, and we have permission to write to it. */
515- if (! exists
516- || (!S_ISLNK (s.st_mode)
517- && S_ISREG (s.st_mode)
518- && (s.st_mode & S_IWUSR)
519- && s.st_nlink == 1)
520- )
521- {
522- ret = rename (from, to);
523- if (ret == 0)
524- {
525- if (exists)
526- {
527- /* Try to preserve the permission bits and ownership of
528- TO. First get the mode right except for the setuid
529- bit. Then change the ownership. Then fix the setuid
530- bit. We do the chmod before the chown because if the
531- chown succeeds, and we are a normal user, we won't be
532- able to do the chmod afterward. We don't bother to
533- fix the setuid bit first because that might introduce
534- a fleeting security problem, and because the chown
535- will clear the setuid bit anyhow. We only fix the
536- setuid bit if the chown succeeds, because we don't
537- want to introduce an unexpected setuid file owned by
538- the user running objcopy. */
539- chmod (to, s.st_mode & 0777);
540- if (chown (to, s.st_uid, s.st_gid) >= 0)
541- chmod (to, s.st_mode & 07777);
542- }
543- }
544- else
545- {
546- /* We have to clean up here. */
547- non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
548- unlink (from);
549- }
550- }
551- else
552- {
553- ret = simple_copy (from, to);
554- if (ret != 0)
555- non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno));
556+ non_fatal (_("unable to copy file '%s'; reason: %s"),
557+ to, strerror (errno));
558
559- if (preserve_dates)
560- set_times (to, &s);
561- unlink (from);
562- }
563-#endif /* _WIN32 && !__CYGWIN32__ */
564+ if (target_stat != NULL)
565+ set_times (to, target_stat);
566+ unlink (from);
567
568 return ret;
569 }
570--
5712.17.1
572