aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/FileOutputBuffer.cpp
diff options
context:
space:
mode:
authorJian Cai <jiancai@google.com>2021-02-02 18:47:03 -0800
committerJian Cai <jiancai@google.com>2021-02-12 18:01:43 -0800
commitc2a84771bb63947695ea50b89160c02b36fb634d (patch)
treecef9522e99bd7058bf4e3e731a854dbe740e2d92 /llvm/lib/Support/FileOutputBuffer.cpp
parent5631842d181016207e85e4d035d0c4383f34337a (diff)
downloadllvm-c2a84771bb63947695ea50b89160c02b36fb634d.zip
llvm-c2a84771bb63947695ea50b89160c02b36fb634d.tar.gz
llvm-c2a84771bb63947695ea50b89160c02b36fb634d.tar.bz2
[llvm-objcopy] preserve file ownership when overwritten by root
As of binutils 2.36, GNU strip calls chown(2) for "sudo strip foo" and "sudo strip foo -o foo", but no "sudo strip foo -o bar" or "sudo strip foo -o ./foo". In other words, while "sudo strip foo -o bar" creates a new file bar with root access, "sudo strip foo" will keep the owner and group of foo unchanged. Currently llvm-objcopy and llvm-strip behave differently, always changing the owner and gropu to root. The discrepancy prevents Chrome OS from migrating to llvm-objcopy and llvm-strip as they change file ownership and cause intended users/groups to lose access when invoked by sudo with the following sequence (recommended in man page of GNU strip). 1.<Link the executable as normal.> 1.<Copy "foo" to "foo.full"> 1.<Run "strip --strip-debug foo"> 1.<Run "objcopy --add-gnu-debuglink=foo.full foo"> This patch makes llvm-objcopy and llvm-strip follow GNU's behavior. Link: crbug.com/1108880
Diffstat (limited to 'llvm/lib/Support/FileOutputBuffer.cpp')
-rw-r--r--llvm/lib/Support/FileOutputBuffer.cpp16
1 files changed, 13 insertions, 3 deletions
diff --git a/llvm/lib/Support/FileOutputBuffer.cpp b/llvm/lib/Support/FileOutputBuffer.cpp
index 3342682..7b2a512 100644
--- a/llvm/lib/Support/FileOutputBuffer.cpp
+++ b/llvm/lib/Support/FileOutputBuffer.cpp
@@ -125,7 +125,8 @@ createInMemoryBuffer(StringRef Path, size_t Size, unsigned Mode) {
}
static Expected<std::unique_ptr<FileOutputBuffer>>
-createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {
+createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode,
+ bool KeepOwnership, unsigned UserID, unsigned GroupID) {
Expected<fs::TempFile> FileOrErr =
fs::TempFile::create(Path + ".tmp%%%%%%%", Mode);
if (!FileOrErr)
@@ -133,6 +134,13 @@ createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {
fs::TempFile File = std::move(*FileOrErr);
#ifndef _WIN32
+ // Try to preserve file ownership if requested.
+ if (KeepOwnership) {
+ fs::file_status Stat;
+ if (!fs::status(File.FD, Stat) && Stat.getUser() == 0)
+ fs::changeFileOwnership(File.FD, UserID, GroupID);
+ }
+
// On Windows, CreateFileMapping (the mmap function on Windows)
// automatically extends the underlying file. We don't need to
// extend the file beforehand. _chsize (ftruncate on Windows) is
@@ -163,7 +171,8 @@ createOnDiskBuffer(StringRef Path, size_t Size, unsigned Mode) {
// Create an instance of FileOutputBuffer.
Expected<std::unique_ptr<FileOutputBuffer>>
-FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) {
+FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags,
+ unsigned UserID, unsigned GroupID) {
// Handle "-" as stdout just like llvm::raw_ostream does.
if (Path == "-")
return createInMemoryBuffer("-", Size, /*Mode=*/0);
@@ -196,7 +205,8 @@ FileOutputBuffer::create(StringRef Path, size_t Size, unsigned Flags) {
if (Flags & F_no_mmap)
return createInMemoryBuffer(Path, Size, Mode);
else
- return createOnDiskBuffer(Path, Size, Mode);
+ return createOnDiskBuffer(Path, Size, Mode, Flags & F_keep_ownership,
+ UserID, GroupID);
default:
return createInMemoryBuffer(Path, Size, Mode);
}