aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools
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/tools
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/tools')
-rw-r--r--llvm/tools/llvm-objcopy/Buffer.cpp7
-rw-r--r--llvm/tools/llvm-objcopy/Buffer.h5
-rw-r--r--llvm/tools/llvm-objcopy/llvm-objcopy.cpp5
3 files changed, 15 insertions, 2 deletions
diff --git a/llvm/tools/llvm-objcopy/Buffer.cpp b/llvm/tools/llvm-objcopy/Buffer.cpp
index 06b2a20..3049794 100644
--- a/llvm/tools/llvm-objcopy/Buffer.cpp
+++ b/llvm/tools/llvm-objcopy/Buffer.cpp
@@ -36,7 +36,12 @@ Error FileBuffer::allocate(size_t Size) {
}
Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(getName(), Size, FileOutputBuffer::F_executable);
+ FileOutputBuffer::create(getName(), Size,
+ KeepOwnership
+ ? FileOutputBuffer::F_executable |
+ FileOutputBuffer::F_keep_ownership
+ : FileOutputBuffer::F_executable,
+ UserID, GroupID);
// FileOutputBuffer::create() returns an Error that is just a wrapper around
// std::error_code. Wrap it in FileError to include the actual filename.
if (!BufferOrErr)
diff --git a/llvm/tools/llvm-objcopy/Buffer.h b/llvm/tools/llvm-objcopy/Buffer.h
index 487d558..e439e98 100644
--- a/llvm/tools/llvm-objcopy/Buffer.h
+++ b/llvm/tools/llvm-objcopy/Buffer.h
@@ -40,6 +40,9 @@ class FileBuffer : public Buffer {
// Indicates that allocate(0) was called, and commit() should create or
// truncate a file instead of using a FileOutputBuffer.
bool EmptyFile = false;
+ bool KeepOwnership = false;
+ unsigned UserID = 0;
+ unsigned GroupID = 0;
public:
Error allocate(size_t Size) override;
@@ -47,6 +50,8 @@ public:
Error commit() override;
explicit FileBuffer(StringRef FileName) : Buffer(FileName) {}
+ explicit FileBuffer(StringRef FileName, bool Keep, unsigned UID, unsigned GID)
+ : Buffer(FileName), KeepOwnership(Keep), UserID(UID), GroupID(GID) {}
};
class MemBuffer : public Buffer {
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 7fd2acd..42d97b2 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -310,7 +310,10 @@ static Error executeObjcopy(CopyConfig &Config) {
if (Error E = executeObjcopyOnArchive(Config, *Ar))
return E;
} else {
- FileBuffer FB(Config.OutputFilename);
+ FileBuffer FB(Config.OutputFilename,
+ Config.InputFilename != "-" &&
+ Config.InputFilename == Config.OutputFilename,
+ Stat.getUser(), Stat.getGroup());
if (Error E = executeObjcopyOnBinary(Config,
*BinaryOrErr.get().getBinary(), FB))
return E;