diff options
author | Vinay Kumar <vinay.m.engg@gmail.com> | 2021-04-27 01:24:14 -0700 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2021-05-04 22:57:55 +0100 |
commit | 79998ab952c4e4d3c311ed85e6e5e126f537802c (patch) | |
tree | 6d7729365a4533f924e6f038f1538ee051a4100d /meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch | |
parent | 320f059a9b7d7cf9b493778933469d5c604be42b (diff) | |
download | poky-79998ab952c4e4d3c311ed85e6e5e126f537802c.tar.gz |
Binutils: Fix CVE-2021-20197
Source: git://sourceware.org/git/binutils-gdb.git
Tracking -- https://sourceware.org/bugzilla/show_bug.cgi?id=26945
Backported upstream commit d3edaa91d4cf7202ec14342410194841e2f67f12 to
binutils-2.34 source, along with commit id dependencies
(8e03235147a9e774d3ba084e93c2daaa94d1cec, 365f5fb6d0f0da83817431a275e99e6f6babbe04 and 8b69e61d4be276bb862698aaafddc3e779d23c8f).
Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d3edaa91d4cf7202ec14342410194841e2f67f12]
(From OE-Core rev: c98f3563937dc55605cc1f09c096f7cd716a78ce)
Signed-off-by: Vinay Kumar <vinay.m.engg@gmail.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch')
-rw-r--r-- | meta/recipes-devtools/binutils/binutils/CVE-2021-20197.patch | 572 |
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 @@ | |||
1 | From d3edaa91d4cf7202ec14342410194841e2f67f12 Mon Sep 17 00:00:00 2001 | ||
2 | From: Alan Modra <amodra@gmail.com> | ||
3 | Date: Fri, 26 Feb 2021 11:30:32 +1030 | ||
4 | Subject: [PATCH v2] Reinstate various pieces backed out from smart_rename changes | ||
5 | |||
6 | In the interests of a stable release various last minute smart_rename | ||
7 | patches were backed out of the 2.36 branch. The main reason to | ||
8 | reinstate some of those backed out changes here is to make necessary | ||
9 | followup fixes to commit 8e03235147a9 simple cherry-picks from | ||
10 | mainline. A secondary reason is that ar -M support isn't fixed for | ||
11 | pr26945 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 | |||
24 | Upstream-Status: Backport [https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=d3edaa91d4cf7202ec14342410194841e2f67f12] | ||
25 | CVE: CVE-2021-20197 | ||
26 | Signed-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 | |||
38 | diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h | ||
39 | index 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 | |||
51 | diff --git a/bfd/opncls.c b/bfd/opncls.c | ||
52 | index 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 | ||
95 | diff --git a/binutils/ar.c b/binutils/ar.c | ||
96 | index 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); | ||
137 | diff --git a/binutils/arsup.c b/binutils/arsup.c | ||
138 | index 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 | |||
218 | diff --git a/binutils/bucomm.c b/binutils/bucomm.c | ||
219 | index 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 | |||
240 | diff --git a/binutils/bucomm.h b/binutils/bucomm.h | ||
241 | index 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); | ||
263 | diff --git a/binutils/objcopy.c b/binutils/objcopy.c | ||
264 | index 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); | ||
384 | diff --git a/binutils/rename.c b/binutils/rename.c | ||
385 | index 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 | -- | ||
571 | 2.17.1 | ||
572 | |||