[compiler-rt] r350590 - [asan] Support running without /proc
Evgeniy Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Mon Jan 7 17:07:35 PST 2019
Author: eugenis
Date: Mon Jan 7 17:07:34 2019
New Revision: 350590
URL: http://llvm.org/viewvc/llvm-project?rev=350590&view=rev
Log:
[asan] Support running without /proc
Summary:
This patch lets ASan run when /proc is not accessible (ex. not mounted
yet). It includes a special test-only flag that emulates this condition
in an unpriviledged process.
This only matters on Linux, where /proc is necessary to enumerate
virtual memory mappings.
Reviewers: vitalybuka, pcc, krytarowski
Subscribers: kubamracek, llvm-commits
Differential Revision: https://reviews.llvm.org/D56141
Modified:
compiler-rt/trunk/lib/asan/asan_thread.cc
compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h
compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_bsd.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc
compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_solaris.cc
compiler-rt/trunk/test/asan/TestCases/Posix/no-fd.cc
Modified: compiler-rt/trunk/lib/asan/asan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_thread.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_thread.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_thread.cc Mon Jan 7 17:07:34 2019
@@ -223,9 +223,11 @@ void AsanThread::Init(const InitOptions
atomic_store(&stack_switching_, false, memory_order_release);
CHECK_EQ(this->stack_size(), 0U);
SetThreadStackAndTls(options);
- CHECK_GT(this->stack_size(), 0U);
- CHECK(AddrIsInMem(stack_bottom_));
- CHECK(AddrIsInMem(stack_top_ - 1));
+ if (stack_top_ != stack_bottom_) {
+ CHECK_GT(this->stack_size(), 0U);
+ CHECK(AddrIsInMem(stack_bottom_));
+ CHECK(AddrIsInMem(stack_top_ - 1));
+ }
ClearShadowForThreadStackAndTLS();
fake_stack_ = nullptr;
if (__asan_option_detect_stack_use_after_return)
@@ -295,14 +297,17 @@ void AsanThread::SetThreadStackAndTls(co
tls_end_ = tls_begin_ + tls_size;
dtls_ = DTLS_Get();
- int local;
- CHECK(AddrIsInStack((uptr)&local));
+ if (stack_top_ != stack_bottom_) {
+ int local;
+ CHECK(AddrIsInStack((uptr)&local));
+ }
}
#endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
void AsanThread::ClearShadowForThreadStackAndTLS() {
- PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
+ if (stack_top_ != stack_bottom_)
+ PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
if (tls_begin_ != tls_end_) {
uptr tls_begin_aligned = RoundDownTo(tls_begin_, SHADOW_GRANULARITY);
uptr tls_end_aligned = RoundUpTo(tls_end_, SHADOW_GRANULARITY);
@@ -314,6 +319,9 @@ void AsanThread::ClearShadowForThreadSta
bool AsanThread::GetStackFrameAccessByAddr(uptr addr,
StackFrameAccess *access) {
+ if (stack_top_ == stack_bottom_)
+ return false;
+
uptr bottom = 0;
if (AddrIsInStack(addr)) {
bottom = stack_bottom();
Modified: compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_thread.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.cc Mon Jan 7 17:07:34 2019
@@ -43,27 +43,18 @@ void Thread::Init(uptr stack_buffer_star
// ScopedTaggingDisable needs GetCurrentThread to be set up.
ScopedTaggingDisabler disabler;
- // If this process is "init" (pid 1), /proc may not be mounted yet.
- if (IsMainThread() && !FileExists("/proc/self/maps")) {
- stack_top_ = stack_bottom_ = 0;
- tls_begin_ = tls_end_ = 0;
- } else {
- uptr tls_size;
- uptr stack_size;
- GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size,
- &tls_begin_, &tls_size);
- stack_top_ = stack_bottom_ + stack_size;
- tls_end_ = tls_begin_ + tls_size;
+ uptr tls_size;
+ uptr stack_size;
+ GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size, &tls_begin_,
+ &tls_size);
+ stack_top_ = stack_bottom_ + stack_size;
+ tls_end_ = tls_begin_ + tls_size;
+ if (stack_bottom_) {
int local;
CHECK(AddrIsInStack((uptr)&local));
CHECK(MemIsApp(stack_bottom_));
CHECK(MemIsApp(stack_top_ - 1));
-
- if (stack_bottom_) {
- CHECK(MemIsApp(stack_bottom_));
- CHECK(MemIsApp(stack_top_ - 1));
- }
}
if (flags()->verbose_threads) {
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_flags.inc Mon Jan 7 17:07:34 2019
@@ -243,3 +243,6 @@ COMMON_FLAG(bool, dump_registers, true,
COMMON_FLAG(bool, detect_write_exec, false,
"If true, triggers warning when writable-executable pages requests "
"are being made")
+COMMON_FLAG(bool, test_only_emulate_no_memorymap, false,
+ "TEST ONLY fail to read memory mappings to emulate sanitized "
+ "\"init\"")
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux.cc Mon Jan 7 17:07:34 2019
@@ -453,6 +453,8 @@ uptr internal_execve(const char *filenam
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
+ if (ShouldMockFailureToOpen(filename))
+ return false;
struct stat st;
#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
if (internal_syscall(SYSCALL(newfstatat), AT_FDCWD, filename, &st, 0))
@@ -1008,6 +1010,8 @@ static uptr GetKernelAreaSize() {
// Firstly check if there are writable segments
// mapped to top gigabyte (e.g. stack).
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ if (proc_maps.Error())
+ return 0;
MemoryMappedSegment segment;
while (proc_maps.Next(&segment)) {
if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0;
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_linux_libcdep.cc Mon Jan 7 17:07:34 2019
@@ -100,6 +100,10 @@ void GetThreadStackTopAndBottom(bool at_
// Find the mapping that contains a stack variable.
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ if (proc_maps.Error()) {
+ *stack_top = *stack_bottom = 0;
+ return;
+ }
MemoryMappedSegment segment;
uptr prev_end = 0;
while (proc_maps.Next(&segment)) {
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_mac.cc Mon Jan 7 17:07:34 2019
@@ -282,6 +282,8 @@ uptr internal_waitpid(int pid, int *stat
// ----------------- sanitizer_common.h
bool FileExists(const char *filename) {
+ if (ShouldMockFailureToOpen(filename))
+ return false;
struct stat st;
if (stat(filename, &st))
return false;
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.cc Mon Jan 7 17:07:34 2019
@@ -18,6 +18,7 @@
#include "sanitizer_common.h"
#include "sanitizer_file.h"
+#include "sanitizer_flags.h"
#include "sanitizer_libc.h"
#include "sanitizer_posix.h"
#include "sanitizer_procmaps.h"
@@ -157,6 +158,8 @@ void MprotectMallocZones(void *addr, int
#endif
fd_t OpenFile(const char *filename, FileAccessMode mode, error_t *errno_p) {
+ if (ShouldMockFailureToOpen(filename))
+ return kInvalidFd;
int flags;
switch (mode) {
case RdOnly: flags = O_RDONLY; break;
@@ -230,6 +233,8 @@ static inline bool IntervalsAreSeparate(
// memory).
bool MemoryRangeIsAvailable(uptr range_start, uptr range_end) {
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
+ if (proc_maps.Error())
+ return true; // and hope for the best
MemoryMappedSegment segment;
while (proc_maps.Next(&segment)) {
if (segment.start == segment.end) continue; // Empty range.
@@ -334,6 +339,11 @@ fd_t ReserveStandardFds(fd_t fd) {
return fd;
}
+bool ShouldMockFailureToOpen(const char *path) {
+ return common_flags()->test_only_emulate_no_memorymap &&
+ internal_strncmp(path, "/proc/", 6) == 0;
+}
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.h?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix.h Mon Jan 7 17:07:34 2019
@@ -103,6 +103,8 @@ bool IsStateDetached(int state);
// Move the fd out of {0, 1, 2} range.
fd_t ReserveStandardFds(fd_t fd);
+bool ShouldMockFailureToOpen(const char *path);
+
} // namespace __sanitizer
#endif // SANITIZER_POSIX_H
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps.h Mon Jan 7 17:07:34 2019
@@ -70,6 +70,7 @@ class MemoryMappingLayout {
explicit MemoryMappingLayout(bool cache_enabled);
~MemoryMappingLayout();
bool Next(MemoryMappedSegment *segment);
+ bool Error() const;
void Reset();
// In some cases, e.g. when running under a sandbox on Linux, ASan is unable
// to obtain the memory mappings. It should fall back to pre-cached data
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_bsd.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_bsd.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_bsd.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_bsd.cc Mon Jan 7 17:07:34 2019
@@ -99,6 +99,7 @@ void ReadProcMaps(ProcSelfMapsBuff *proc
}
bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ CHECK(!Error()); // can not fail
char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
if (data_.current >= last)
return false;
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_common.cc Mon Jan 7 17:07:34 2019
@@ -80,12 +80,14 @@ MemoryMappingLayout::MemoryMappingLayout
ReadProcMaps(&data_.proc_self_maps);
if (cache_enabled && data_.proc_self_maps.mmaped_size == 0)
LoadFromCache();
- CHECK_GT(data_.proc_self_maps.mmaped_size, 0);
- CHECK_GT(data_.proc_self_maps.len, 0);
Reset();
}
+bool MemoryMappingLayout::Error() const {
+ return data_.current == nullptr;
+}
+
MemoryMappingLayout::~MemoryMappingLayout() {
// Only unmap the buffer if it is different from the cached one. Otherwise
// it will be unmapped when the cache is refreshed.
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_linux.cc Mon Jan 7 17:07:34 2019
@@ -31,6 +31,7 @@ static bool IsOneOf(char c, char c1, cha
}
bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ if (Error()) return false; // simulate empty maps
char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
if (data_.current >= last) return false;
char *next_line =
Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_solaris.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_solaris.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_solaris.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_procmaps_solaris.cc Mon Jan 7 17:07:34 2019
@@ -21,11 +21,16 @@
namespace __sanitizer {
void ReadProcMaps(ProcSelfMapsBuff *proc_maps) {
- ReadFileToBuffer("/proc/self/xmap", &proc_maps->data, &proc_maps->mmaped_size,
- &proc_maps->len);
+ if (!ReadFileToBuffer("/proc/self/xmap", &proc_maps->data,
+ &proc_maps->mmaped_size, &proc_maps->len)) {
+ proc_maps->data = nullptr;
+ proc_maps->mmaped_size = 0;
+ proc_maps->len = 0;
+ }
}
bool MemoryMappingLayout::Next(MemoryMappedSegment *segment) {
+ if (Error()) return false; // simulate empty maps
char *last = data_.proc_self_maps.data + data_.proc_self_maps.len;
if (data_.current >= last) return false;
Modified: compiler-rt/trunk/test/asan/TestCases/Posix/no-fd.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Posix/no-fd.cc?rev=350590&r1=350589&r2=350590&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Posix/no-fd.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Posix/no-fd.cc Mon Jan 7 17:07:34 2019
@@ -9,6 +9,10 @@
#include <stdlib.h>
#include <unistd.h>
+extern "C" const char *__asan_default_options() {
+ return "test_only_emulate_no_memorymap=1";
+}
+
void parent(int argc, char **argv) {
fprintf(stderr, "hello\n");
// CHECK: hello
More information about the llvm-commits
mailing list