diff options
author | Jian Cai <jiancai@google.com> | 2021-02-02 18:47:03 -0800 |
---|---|---|
committer | Jian Cai <jiancai@google.com> | 2021-02-12 18:01:43 -0800 |
commit | c2a84771bb63947695ea50b89160c02b36fb634d (patch) | |
tree | cef9522e99bd7058bf4e3e731a854dbe740e2d92 /llvm/lib/Support/FileOutputBuffer.cpp | |
parent | 5631842d181016207e85e4d035d0c4383f34337a (diff) | |
download | llvm-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.cpp | 16 |
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); } |