Mmap interceptor new option, Write Exec runtime detector

Summary:
Following-up the refactoring of mmap interceptors, adding a new common
option to detect PROT_WRITE|PROT_EXEC pages request.

Patch by David CARLIER

Reviewers: vitalybuka, vsk

Reviewed By: vitalybuka

Subscribers: krytarowski, #sanitizers

Differential Revision: https://reviews.llvm.org/D44194

llvm-svn: 328151
This commit is contained in:
Vitaly Buka 2018-03-21 21:25:07 +00:00
parent 1442a5dd3a
commit 8980449bb6
5 changed files with 50 additions and 0 deletions

View File

@ -378,6 +378,8 @@ void ReportErrorSummary(const char *error_type, const AddressInfo &info,
void ReportErrorSummary(const char *error_type, const StackTrace *trace,
const char *alt_tool_name = nullptr);
void ReportMmapWriteExec();
// Math
#if SANITIZER_WINDOWS && !defined(__clang__) && !defined(__GNUC__)
extern "C" {

View File

@ -6887,6 +6887,8 @@ INTERCEPTOR(SIZE_T, strlcat, char *dst, char *src, SIZE_T size) {
INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
OFF_T off) {
void *ctx;
if (common_flags()->detect_write_exec)
ReportMmapWriteExec();
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
COMMON_INTERCEPTOR_ENTER(ctx, mmap, addr, sz, prot, flags, fd, off);
@ -6901,6 +6903,8 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T sz, int prot, int flags, int fd,
INTERCEPTOR(void *, mmap64, void *addr, SIZE_T sz, int prot, int flags, int fd,
OFF64_T off) {
void *ctx;
if (common_flags()->detect_write_exec)
ReportMmapWriteExec();
if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED)
return (void *)internal_mmap(addr, sz, prot, flags, fd, off);
COMMON_INTERCEPTOR_ENTER(ctx, mmap64, addr, sz, prot, flags, fd, off);

View File

@ -81,6 +81,32 @@ void ReportErrorSummary(const char *error_type, const StackTrace *stack,
#endif
}
void ReportMmapWriteExec() {
#if !SANITIZER_GO && !SANITIZER_ANDROID
ScopedErrorReportLock l;
SanitizerCommonDecorator d;
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
BufferedStackTrace *stack = stack_buffer.data();
stack->Reset();
uptr top = 0;
uptr bottom = 0;
GET_CALLER_PC_BP_SP;
(void)sp;
bool fast = common_flags()->fast_unwind_on_fatal;
if (fast)
GetThreadStackTopAndBottom(false, &top, &bottom);
stack->Unwind(kStackTraceMax, pc, bp, nullptr, top, bottom, fast);
Printf("%s", d.Warning());
Report("WARNING: %s: writable-executable page usage\n", SanitizerToolName);
Printf("%s", d.Default());
stack->Print();
ReportErrorSummary("w-and-x-usage", stack);
#endif
}
static void (*SoftRssLimitExceededCallback)(bool exceeded);
void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded)) {
CHECK_EQ(SoftRssLimitExceededCallback, nullptr);

View File

@ -240,3 +240,6 @@ COMMON_FLAG(bool, dump_instruction_bytes, false,
COMMON_FLAG(bool, dump_registers, true,
"If true, dump values of CPU registers when SEGV happens. Only "
"available on OS X for now.")
COMMON_FLAG(bool, detect_write_exec, false,
"If true, triggers warning when writable-executable pages requests "
"are being made")

View File

@ -0,0 +1,15 @@
// RUN: %clangxx %s -o %t
// RUN: %env_tool_opts=detect_write_exec=1 %run %t 2>&1 | FileCheck %s
// ubsan and lsan do not install mmap interceptors
// UNSUPPORTED: ubsan, lsan
// TODO: Fix option on Android, it hangs there for unknown reasons.
// XFAIL: android
#include <sys/mman.h>
int main(int argc, char **argv) {
char *p = (char *)mmap(0, 1024, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// CHECK: WARNING: {{.*}}Sanitizer: writable-executable page usage
}