[asan] Respect personality in kernel area detector, patch by Yuri Gribov

llvm-svn: 208760
This commit is contained in:
Kostya Serebryany 2014-05-14 08:13:11 +00:00
parent 5ace2cd512
commit 7534a60753
5 changed files with 45 additions and 15 deletions

View File

@ -556,6 +556,12 @@ static void AsanInitInternal() {
SanitizerToolName = "AddressSanitizer";
CHECK(!asan_init_is_running && "ASan init calls itself!");
asan_init_is_running = true;
// Initialize flags. This must be done early, because most of the
// initialization steps look at flags().
const char *options = GetEnv("ASAN_OPTIONS");
InitializeFlags(flags(), options);
InitializeHighMemEnd();
// Make sure we are not statically linked.
@ -566,11 +572,6 @@ static void AsanInitInternal() {
SetCheckFailedCallback(AsanCheckFailed);
SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
// Initialize flags. This must be done early, because most of the
// initialization steps look at flags().
const char *options = GetEnv("ASAN_OPTIONS");
InitializeFlags(flags(), options);
if (!flags()->start_deactivated)
ParseExtraActivationFlags();

View File

@ -55,6 +55,7 @@ void SetCommonFlagsDefaults(CommonFlags *f) {
f->legacy_pthread_cond = false;
f->intercept_tls_get_addr = false;
f->coverage = false;
f->full_address_space = false;
}
void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
@ -126,6 +127,9 @@ void ParseCommonFlagsFromString(CommonFlags *f, const char *str) {
ParseFlag(str, &f->coverage, "coverage",
"If set, coverage information will be dumped at program shutdown (if the "
"coverage instrumentation was enabled at compile time).");
ParseFlag(str, &f->full_address_space, "full_address_space",
"Sanitize complete address space; "
"by default kernel area on 32-bit platforms will not be sanitized");
// Do a sanity check for certain flags.
if (f->malloc_context_size < 1)

View File

@ -54,6 +54,7 @@ struct CommonFlags {
bool help;
uptr mmap_limit_mb;
bool coverage;
bool full_address_space;
};
inline CommonFlags *common_flags() {

View File

@ -24,6 +24,7 @@
#if SANITIZER_LINUX
#include <sys/utsname.h>
#include <sys/personality.h>
#endif
namespace __sanitizer {
@ -34,16 +35,36 @@ uptr GetMmapGranularity() {
}
#if SANITIZER_WORDSIZE == 32
// Take care of unusable kernel area in top gigabyte
static uptr GetKernelStartAddress() {
#if 0 // SANITIZER_LINUX
// FIXME: this code is too naive. We have a situation where the machine is a
// true x8_64, but under schroot uname returns i686.
// 64-bit Linux provides 32-bit apps with full address space
// Take care of unusable kernel area in top gigabyte.
static uptr GetKernelAreaSize() {
#if SANITIZER_LINUX
const uptr gbyte = 1UL << 30;
// Firstly check if there are writable segments
// mapped to top gigabyte (e.g. stack).
MemoryMappingLayout proc_maps(/*cache_enabled*/true);
uptr end, prot;
while (proc_maps.Next(/*start*/0, &end,
/*offset*/0, /*filename*/0,
/*filename_size*/0, &prot)) {
if ((end >= 3 * gbyte)
&& (prot & MemoryMappingLayout::kProtectionWrite) != 0)
return 0;
}
// Even if nothing is mapped, top Gb may still be accessible
// if we are running on 64-bit kernel.
// Uname may report misleading results if personality type
// is modified (e.g. under schroot) so check this as well.
struct utsname uname_info;
return 0 == uname(&uname_info) && !internal_strstr(uname_info.machine, "64")
? 1ULL << 30
: 0;
int pers = personality(0xffffffffUL);
if (!(pers & PER_MASK)
&& uname(&uname_info) == 0
&& internal_strstr(uname_info.machine, "64"))
return 0;
// Top gigabyte is reserved for kernel.
return gbyte;
#else
return 0;
#endif // SANITIZER_LINUX
@ -66,7 +87,8 @@ uptr GetMaxVirtualAddress() {
# endif
#else // SANITIZER_WORDSIZE == 32
uptr res = (1ULL << 32) - 1; // 0xffffffff;
res -= GetKernelStartAddress();
if (!common_flags()->full_address_space)
res -= GetKernelAreaSize();
CHECK_LT(reinterpret_cast<uptr>(&res), res);
return res;
#endif // SANITIZER_WORDSIZE

View File

@ -2,6 +2,8 @@
//
// RUN: %clangxx_asan %s -o %t
// RUN: ASAN_OPTIONS=verbosity=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
// RUN: ASAN_OPTIONS=verbosity=1:full_address_space=0 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-%kernel_bits
// RUN: ASAN_OPTIONS=verbosity=1:full_address_space=1 %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-kernel-64-bits
//
// CHECK-kernel-32-bits: || `[0x38000000, 0xbfffffff]` || HighMem ||
// CHECK-kernel-32-bits: || `[0x27000000, 0x37ffffff]` || HighShadow ||