forked from OSchip/llvm-project
[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. llvm-svn: 243473
This commit is contained in:
parent
8eb9c3068c
commit
7eeb02bd09
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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++;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue