diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-07-28 20:27:51 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2015-07-28 20:27:51 +0000 |
commit | 88355c5dc907d1b088c0ce48e08bb65583366551 (patch) | |
tree | 57ad9f6883e3a1d8ef0e5d83e3afe8cf42fe15d8 | |
parent | f36d0cbdfa9c1d3579a9890642b153d32376ded6 (diff) |
[asan] Read process name from /proc/self/cmdline on Linux.
Rename getBinaryBasename() to getProcessName() and, on Linux,
read it from /proc/self/cmdline instead of /proc/self/exe. The former
can be modified by the process. The main motivation is Android, where
application processes re-write cmdline to a package name. This lets
us setup per-application ASAN_OPTIONS through include=/some/path/%b.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@243473 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/asan/asan_activation.cc | 2 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.cc | 14 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_common.h | 4 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_flags.cc | 2 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_linux.cc | 26 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_printf.cc | 2 | ||||
-rw-r--r-- | test/asan/TestCases/Linux/activation-options.cc | 70 |
7 files changed, 112 insertions, 8 deletions
diff --git a/lib/asan/asan_activation.cc b/lib/asan/asan_activation.cc index 8d86245b4..1d3582c16 100644 --- a/lib/asan/asan_activation.cc +++ b/lib/asan/asan_activation.cc @@ -124,6 +124,8 @@ void AsanActivate() { if (!asan_is_deactivated) return; VReport(1, "Activating ASan\n"); + UpdateProcessName(); + asan_deactivated_flags.OverrideFromActivationFlags(); SetCanPoisonMemory(asan_deactivated_flags.poison_heap); diff --git a/lib/sanitizer_common/sanitizer_common.cc b/lib/sanitizer_common/sanitizer_common.cc index 541308c32..28c2c0cae 100644 --- a/lib/sanitizer_common/sanitizer_common.cc +++ b/lib/sanitizer_common/sanitizer_common.cc @@ -57,7 +57,7 @@ void ReportFile::ReopenIfNecessary() { CloseFile(fd); } - const char *exe_name = GetBinaryBasename(); + const char *exe_name = GetProcessName(); if (common_flags()->log_exe_name && exe_name) { internal_snprintf(full_path, kMaxPathLength, "%s.%s.%zu", path_prefix, exe_name, pid); @@ -345,10 +345,14 @@ bool TemplateMatch(const char *templ, const char *str) { } static char binary_name_cache_str[kMaxPathLength]; -static const char *binary_basename_cache_str; +static char process_name_cache_str[kMaxPathLength]; -const char *GetBinaryBasename() { - return binary_basename_cache_str; +const char *GetProcessName() { + return process_name_cache_str; +} + +void UpdateProcessName() { + ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str)); } // Call once to make sure that binary_name_cache_str is initialized @@ -356,7 +360,7 @@ void CacheBinaryName() { if (binary_name_cache_str[0] != '\0') return; ReadBinaryName(binary_name_cache_str, sizeof(binary_name_cache_str)); - binary_basename_cache_str = StripModuleName(binary_name_cache_str); + ReadProcessName(process_name_cache_str, sizeof(process_name_cache_str)); } uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len) { diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h index 805454a18..94fa044c6 100644 --- a/lib/sanitizer_common/sanitizer_common.h +++ b/lib/sanitizer_common/sanitizer_common.h @@ -251,7 +251,9 @@ const char *StripModuleName(const char *module); // OS uptr ReadBinaryName(/*out*/char *buf, uptr buf_len); uptr ReadBinaryNameCached(/*out*/char *buf, uptr buf_len); -const char *GetBinaryBasename(); +uptr ReadProcessName(/*out*/char *buf, uptr buf_len); +const char *GetProcessName(); +void UpdateProcessName(); void CacheBinaryName(); void DisableCoreDumperIfNecessary(); void DumpProcessMap(); diff --git a/lib/sanitizer_common/sanitizer_flags.cc b/lib/sanitizer_common/sanitizer_flags.cc index ea73ad8dc..18b9ea3df 100644 --- a/lib/sanitizer_common/sanitizer_flags.cc +++ b/lib/sanitizer_common/sanitizer_flags.cc @@ -50,7 +50,7 @@ static void SubstituteBinaryName(const char *s, char *out, uptr out_size) { char *out_end = out + out_size; while (*s && out < out_end - 1) { if (s[0] != '%' || s[1] != 'b') { *out++ = *s++; continue; } - const char *base = GetBinaryBasename(); + const char *base = GetProcessName(); CHECK(base); while (*base && out < out_end - 1) *out++ = *base++; diff --git a/lib/sanitizer_common/sanitizer_linux.cc b/lib/sanitizer_common/sanitizer_linux.cc index 4e978ea07..18bd185f2 100644 --- a/lib/sanitizer_common/sanitizer_linux.cc +++ b/lib/sanitizer_common/sanitizer_linux.cc @@ -730,6 +730,32 @@ uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { return module_name_len; } +static uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { +#if SANITIZER_LINUX + char *tmpbuf; + uptr tmpsize; + uptr tmplen; + if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen, + 1024 * 1024)) { + internal_strncpy(buf, tmpbuf, buf_len); + UnmapOrDie(tmpbuf, tmpsize); + return internal_strlen(buf); + } +#endif + return ReadBinaryName(buf, buf_len); +} + +uptr ReadProcessName(/*out*/ char *buf, uptr buf_len) { + ReadLongProcessName(buf, buf_len); + char *s = const_cast<char *>(StripModuleName(buf)); + uptr len = internal_strlen(s); + if (s != buf) { + internal_memmove(buf, s, len); + buf[len] = '\0'; + } + return len; +} + // Match full names of the form /path/to/base_name{-,.}* bool LibraryNameIs(const char *full_name, const char *base_name) { const char *name = full_name; diff --git a/lib/sanitizer_common/sanitizer_printf.cc b/lib/sanitizer_common/sanitizer_printf.cc index 7a71722eb..852cdd4b2 100644 --- a/lib/sanitizer_common/sanitizer_printf.cc +++ b/lib/sanitizer_common/sanitizer_printf.cc @@ -260,7 +260,7 @@ static void SharedPrintfCode(bool append_pid, const char *format, } if (append_pid) { int pid = internal_getpid(); - const char *exe_name = GetBinaryBasename(); + const char *exe_name = GetProcessName(); if (common_flags()->log_exe_name && exe_name) { needed_length += internal_snprintf(buffer, buffer_size, "==%s", exe_name); diff --git a/test/asan/TestCases/Linux/activation-options.cc b/test/asan/TestCases/Linux/activation-options.cc new file mode 100644 index 000000000..28a653abe --- /dev/null +++ b/test/asan/TestCases/Linux/activation-options.cc @@ -0,0 +1,70 @@ +// Test for ASAN_OPTIONS=start_deactivated=1 mode. +// Main executable is uninstrumented, but linked to ASan runtime. The shared +// library is instrumented. + +// RUN: %clangxx_asan -O0 -DSHARED_LIB %s -fPIC -shared -o %t-so.so +// RUN: %clangxx -O0 %s -c -o %t.o +// RUN: %clangxx_asan -O0 %t.o %libdl -o %t + +// RUN: rm -f %t.asan.options.activation-options.cc.tmp +// RUN: rm -f %t.asan.options.ABCDE +// RUN: echo "help=1" >%t.asan.options.activation-options.cc.tmp + +// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \ +// RUN: ASAN_ACTIVATION_OPTIONS=include=%t.asan.options.%b %run %t 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-HELP --check-prefix=CHECK-FOUND + +// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \ +// RUN: ASAN_ACTIVATION_OPTIONS=include=%t.asan.options not %run %t 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-HELP --check-prefix=CHECK-MISSING + +// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \ +// RUN: ASAN_ACTIVATION_OPTIONS=include=%t.asan.options.%b not %run %t --fix-name 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-NO-HELP --check-prefix=CHECK-MISSING + +// RUN: echo "help=1" >%t.asan.options.ABCDE + +// RUN: env ASAN_OPTIONS=$ASAN_OPTIONS:start_deactivated=1 \ +// RUN: ASAN_ACTIVATION_OPTIONS=include=%t.asan.options.%b %run %t --fix-name 2>&1 | \ +// RUN: FileCheck %s --check-prefix=CHECK-HELP --check-prefix=CHECK-FOUND + +// XFAIL: arm-linux-gnueabi + +#if !defined(SHARED_LIB) +#include <assert.h> +#include <dlfcn.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <string> + +#include "sanitizer/asan_interface.h" + +typedef void (*Fn)(); + +int main(int argc, char *argv[]) { + std::string path = std::string(argv[0]) + "-so.so"; + + if (argc > 1 && strcmp(argv[1], "--fix-name") == 0) { + assert(strlen(argv[0]) > 5); + strcpy(argv[0], "ABCDE"); + } + + void *dso = dlopen(path.c_str(), RTLD_NOW); + if (!dso) { + fprintf(stderr, "dlopen failed: %s\n", dlerror()); + return 1; + } + + return 0; +} +#else // SHARED_LIB +// Empty: all we need is an ASan shared library constructor. +#endif // SHARED_LIB + +// CHECK-HELP: Available flags for {{.*}}Sanitizer: +// CHECK-NO-HELP-NOT: Available flags for {{.*}}Sanitizer: +// CHECK-FOUND-NOT: Failed to read options +// CHECK-MISSING: Failed to read options |