forked from OSchip/llvm-project
[DFSan] Handle mmap() calls before interceptors are installed.
InitializeInterceptors() calls dlsym(), which calls calloc(). Depending on the allocator implementation, calloc() may invoke mmap(), which results in a segfault since REAL(mmap) is still being resolved. We fix this by doing a direct syscall if interceptors haven't been fully resolved yet. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D86168
This commit is contained in:
parent
e2645488ca
commit
4deda57106
|
@ -11,16 +11,29 @@
|
|||
// Interceptors for standard library functions.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "dfsan/dfsan.h"
|
||||
#include "interception/interception.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
|
||||
using namespace __sanitizer;
|
||||
|
||||
static bool interceptors_initialized;
|
||||
|
||||
INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
|
||||
int fd, OFF_T offset) {
|
||||
void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
|
||||
if (res != (void*)-1)
|
||||
void *res;
|
||||
|
||||
// interceptors_initialized is set to true during preinit_array, when we're
|
||||
// single-threaded. So we don't need to worry about accessing it atomically.
|
||||
if (!interceptors_initialized)
|
||||
res = (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
|
||||
else
|
||||
res = REAL(mmap)(addr, length, prot, flags, fd, offset);
|
||||
|
||||
if (res != (void *)-1)
|
||||
dfsan_set_label(0, res, RoundUpTo(length, GetPageSize()));
|
||||
return res;
|
||||
}
|
||||
|
@ -28,18 +41,18 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
|
|||
INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
|
||||
int fd, OFF64_T offset) {
|
||||
void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
|
||||
if (res != (void*)-1)
|
||||
if (res != (void *)-1)
|
||||
dfsan_set_label(0, res, RoundUpTo(length, GetPageSize()));
|
||||
return res;
|
||||
}
|
||||
|
||||
namespace __dfsan {
|
||||
void InitializeInterceptors() {
|
||||
static int inited = 0;
|
||||
CHECK_EQ(inited, 0);
|
||||
CHECK(!interceptors_initialized);
|
||||
|
||||
INTERCEPT_FUNCTION(mmap);
|
||||
INTERCEPT_FUNCTION(mmap64);
|
||||
inited = 1;
|
||||
|
||||
interceptors_initialized = true;
|
||||
}
|
||||
} // namespace __dfsan
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
// RUN: %clang_dfsan -fno-sanitize=dataflow -DCALLOC -c %s -o %t-calloc.o
|
||||
// RUN: %clang_dfsan %s %t-calloc.o -o %t
|
||||
// RUN: %run %t
|
||||
//
|
||||
// Tests that calling mmap() during during dfsan initialization works.
|
||||
|
||||
#include <assert.h>
|
||||
#include <sanitizer/dfsan_interface.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef CALLOC
|
||||
|
||||
// dfsan_init() installs interceptors via dlysm(), which calls calloc().
|
||||
// Calling mmap() from here should work even if interceptors haven't been fully
|
||||
// set up yet.
|
||||
void *calloc(size_t Num, size_t Size) {
|
||||
size_t PageSize = getpagesize();
|
||||
Size = Size * Num;
|
||||
Size = (Size + PageSize - 1) & ~(PageSize - 1); // Round up to PageSize.
|
||||
void *Ret = mmap(NULL, Size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
assert(Ret != MAP_FAILED);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
int main() { return 0; }
|
||||
|
||||
#endif // CALLOC
|
Loading…
Reference in New Issue