[PATCH] binutils: Attempt to retain permissions on copying file
Siddhesh Poyarekar
siddhesh@gotplt.org
Tue Feb 23 06:52:59 GMT 2021
Writing into an existing file clears its S_ISUID and S_ISGID bits.
Attempt to restore those permission bits but don't fail if it doesn't
work.
Also, since the output file always exists (all callers create an empty
file before calling smart_rename), open the file without any
permission hints or O_CREAT.
binutils/
* rename.c (simple_copy): Don't use O_CREAT.
(simple_copy)[!defined (_WIN32) || defined (__CYGWIN32__)]:
Attempt to retain permission bits.
---
Tested on x86_64 to verify that it retains setuid/setgid bits directly
as well as via symlink. The patch goes on top of Alan Modra's patch to
tidy up for Windows and unconditionally call simple_copy so that this
(hopefully) doesn't break WIN32 again:
https://sourceware.org/pipermail/binutils/2021-February/115472.html
binutils/rename.c | 24 +++++++++++++++++++-----
1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/binutils/rename.c b/binutils/rename.c
index 72a9323d72c..103f92866cd 100644
--- a/binutils/rename.c
+++ b/binutils/rename.c
@@ -41,14 +41,19 @@ simple_copy (const char *from, const char *to)
int saved;
char buf[COPY_BUF];
+#if !defined (_WIN32) || defined (__CYGWIN32__)
+ /* Note permissions of the destination file before it is written to so that
+ we can try to restore it later. */
+ struct stat to_stat;
+ mode_t to_mode = 0;
+ if (stat (to, &to_stat) == 0)
+ to_mode = to_stat.st_mode;
+#endif
+
fromfd = open (from, O_RDONLY | O_BINARY);
if (fromfd < 0)
return -1;
-#ifdef O_CREAT
- tofd = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0777);
-#else
- tofd = creat (to, 0777);
-#endif
+ tofd = open (to, O_WRONLY | O_TRUNC | O_BINARY);
if (tofd < 0)
{
saved = errno;
@@ -67,7 +72,16 @@ simple_copy (const char *from, const char *to)
return -1;
}
}
+
saved = errno;
+
+#if !defined (_WIN32) || defined (__CYGWIN32__)
+ /* Writing to a setuid/setgid file clears the S_ISUID and S_ISGID bits.
+ Try to restore them (ignore failure) before closing the file. */
+ if (to_mode > 0)
+ fchmod (tofd, to_mode);
+#endif
+
close (fromfd);
close (tofd);
if (nread < 0)
--
2.29.2
More information about the Binutils
mailing list