[ASan] Restrict the set of flags overriden at activation.

Summary:
Change the way ASan flag parsing is performed at activation: instead
of overwriting all ASan and common flags from the activation string,
ASan will now only override a handful of whitelisted flags.
This is a first step towards making runtime flags immutable after
initialization. I plan to re-factor the activation stragegy to
the following one:

  - Parse commandline flags. Override the defaults from compile
    definition, env var, etc. Flags are immutable at this point.
  - Initiailize the runtime from commandline flags.
  - If ASan needs to be started deactivated, stash the runtime
    state in "asan_deactivated_flags" and deactivate the runtime.
  - When ASan is activated, override "asan_deactivated_flags" with
    activation flags, and use it to re-activate the runtime.

Test Plan: regression test suite

Reviewers: eugenis, kcc

Subscribers: llvm-commits

Differential Revision: http://reviews.llvm.org/D6709

llvm-svn: 224601
This commit is contained in:
Alexey Samsonov 2014-12-19 19:16:07 +00:00
parent 583e9d29ad
commit 1b64854574
1 changed files with 50 additions and 26 deletions

View File

@ -29,6 +29,46 @@ static struct AsanDeactivatedFlags {
bool poison_heap;
bool alloc_dealloc_mismatch;
bool allocator_may_return_null;
void CopyFrom(const Flags *f, const CommonFlags *cf) {
quarantine_size = f->quarantine_size;
max_redzone = f->max_redzone;
malloc_context_size = cf->malloc_context_size;
poison_heap = f->poison_heap;
alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
allocator_may_return_null = cf->allocator_may_return_null;
}
void OverrideFromActivationFlags() {
Flags f;
CommonFlags cf;
// Copy the current activation flags.
f.quarantine_size = quarantine_size;
f.max_redzone = max_redzone;
cf.malloc_context_size = malloc_context_size;
f.poison_heap = poison_heap;
f.alloc_dealloc_mismatch = alloc_dealloc_mismatch;
cf.allocator_may_return_null = allocator_may_return_null;
// Check if activation flags need to be overriden.
// FIXME: Add diagnostic to check that activation flags string doesn't
// contain any other flags.
char buf[100];
GetExtraActivationFlags(buf, sizeof(buf));
ParseCommonFlagsFromString(&cf, buf);
ParseFlagsFromString(&f, buf);
CopyFrom(&f, &cf);
}
void Print() {
Report("quarantine_size %d, max_redzone %d, poison_heap %d, "
"malloc_context_size %d, alloc_dealloc_mismatch %d, "
"allocator_may_return_null %d\n",
quarantine_size, max_redzone, poison_heap, malloc_context_size,
alloc_dealloc_mismatch, allocator_may_return_null);
}
} asan_deactivated_flags;
static bool asan_is_deactivated;
@ -36,16 +76,11 @@ static bool asan_is_deactivated;
void AsanStartDeactivated() {
VReport(1, "Deactivating ASan\n");
// Save flag values.
asan_deactivated_flags.quarantine_size = flags()->quarantine_size;
asan_deactivated_flags.max_redzone = flags()->max_redzone;
asan_deactivated_flags.poison_heap = flags()->poison_heap;
asan_deactivated_flags.malloc_context_size =
common_flags()->malloc_context_size;
asan_deactivated_flags.alloc_dealloc_mismatch =
flags()->alloc_dealloc_mismatch;
asan_deactivated_flags.allocator_may_return_null =
common_flags()->allocator_may_return_null;
asan_deactivated_flags.CopyFrom(flags(), common_flags());
// FIXME: Don't overwrite commandline flags. Instead, make the flags store
// the original values calculated during flag parsing, and re-initialize
// the necessary runtime objects.
flags()->quarantine_size = 0;
flags()->max_redzone = 16;
flags()->poison_heap = false;
@ -60,35 +95,24 @@ void AsanActivate() {
if (!asan_is_deactivated) return;
VReport(1, "Activating ASan\n");
asan_deactivated_flags.OverrideFromActivationFlags();
// Restore flag values.
// FIXME: this is not atomic, and there may be other threads alive.
flags()->max_redzone = asan_deactivated_flags.max_redzone;
flags()->alloc_dealloc_mismatch =
asan_deactivated_flags.alloc_dealloc_mismatch;
// FIXME: Avoid modifying global common_flags() and flags() and restrict the
// set of supported flags that can be provided in activation.
char buf[100];
GetExtraActivationFlags(buf, sizeof(buf));
ParseCommonFlagsFromString(common_flags(), buf);
ParseFlagsFromString(flags(), buf);
if (buf[0] != '\0')
VReport(1, "Extra activation flags: %s\n", buf);
SetCanPoisonMemory(asan_deactivated_flags.poison_heap);
SetMallocContextSize(asan_deactivated_flags.malloc_context_size);
ReInitializeAllocator(asan_deactivated_flags.allocator_may_return_null,
asan_deactivated_flags.quarantine_size);
asan_is_deactivated = false;
VReport(1, "quarantine_size %d, max_redzone %d, poison_heap %d, "
"malloc_context_size %d, alloc_dealloc_mismatch %d, "
"allocator_may_return_null %d\n",
asan_deactivated_flags.quarantine_size, flags()->max_redzone,
asan_deactivated_flags.poison_heap,
asan_deactivated_flags.malloc_context_size,
flags()->alloc_dealloc_mismatch,
asan_deactivated_flags.allocator_may_return_null);
if (common_flags()->verbosity) {
Report("Activated with flags:\n");
asan_deactivated_flags.Print();
}
}
} // namespace __asan