Skip to content

Commit

Permalink
[MSan] Introduce __msan_unpoison_param().
Browse files Browse the repository at this point in the history
Summary:
This allows libFuzzer to unpoison parameter shadow before calling
LLVMFuzzerTestOneInput to eliminate the false positives described
in google/oss-fuzz#2369.

Reviewers: eugenis

Reviewed By: eugenis

Subscribers: llvm-commits, metzman, kcc

Tags: #llvm

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

llvm-svn: 360379
  • Loading branch information
morehouse authored and MrSidims committed May 24, 2019
1 parent 3ee58fa commit 8a9ce34
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 0 deletions.
3 changes: 3 additions & 0 deletions compiler-rt/include/sanitizer/msan_interface.h
Expand Up @@ -42,6 +42,9 @@ extern "C" {
contents). */
void __msan_unpoison_string(const volatile char *a);

/* Make first n parameters of the next function call fully initialized. */
void __msan_unpoison_param(size_t n);

/* Make memory region fully uninitialized (without changing its contents).
This is a legacy interface that does not update origin information. Use
__msan_allocated_memory() instead. */
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/msan/msan_interceptors.cc
Expand Up @@ -1543,6 +1543,8 @@ void __msan_poison_stack(void *a, uptr size) {
SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
}

void __msan_unpoison_param(uptr n) { UnpoisonParam(n); }

void __msan_clear_and_unpoison(void *a, uptr size) {
REAL(memset)(a, 0, size);
SetShadow(a, size, 0);
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/msan/msan_interface_internal.h
Expand Up @@ -69,6 +69,8 @@ void __msan_unpoison(const void *a, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE
void __msan_unpoison_string(const char *s);
SANITIZER_INTERFACE_ATTRIBUTE
void __msan_unpoison_param(uptr n);
SANITIZER_INTERFACE_ATTRIBUTE
void __msan_clear_and_unpoison(void *a, uptr size);
SANITIZER_INTERFACE_ATTRIBUTE
void* __msan_memcpy(void *dst, const void *src, uptr size);
Expand Down
51 changes: 51 additions & 0 deletions compiler-rt/test/msan/unpoison_param.cc
@@ -0,0 +1,51 @@
// Tests that __msan_unpoison_param() works as specified. To prevent MSan
// instrumentation from modifying parameter shadow before each call to foo(), we
// compile main() without MSan.

// RUN: %clangxx_msan -fno-sanitize=memory -c %s -o %t-main.o
// RUN: %clangxx_msan %t-main.o %s -o %t
// RUN: %run %t

#include <assert.h>
#include <sanitizer/msan_interface.h>

#if __has_feature(memory_sanitizer)

__attribute__((noinline)) int bar(int a, int b) {
volatile int zero = 0;
return zero;
}

int foo(int a, int b, int unpoisoned_params) {
if (unpoisoned_params == 0) {
assert(__msan_test_shadow(&a, sizeof(a)) == 0);
assert(__msan_test_shadow(&b, sizeof(b)) == 0);
} else if (unpoisoned_params == 1) {
assert(__msan_test_shadow(&a, sizeof(a)) == -1);
assert(__msan_test_shadow(&b, sizeof(b)) == 0);
} else if (unpoisoned_params == 2) {
assert(__msan_test_shadow(&a, sizeof(a)) == -1);
assert(__msan_test_shadow(&b, sizeof(b)) == -1);
}

// Poisons parameter shadow in TLS so that the next call from uninstrumented
// main has params 1 and 2 poisoned no matter what.
int x, y;
return bar(x, y);
}

#else

int foo(int, int, int);

int main() {
foo(0, 0, 2); // Poison parameters for next call.
foo(0, 0, 0); // Check that both params are poisoned.
__msan_unpoison_param(1);
foo(0, 0, 1); // Check that only first param is unpoisoned.
__msan_unpoison_param(2);
foo(0, 0, 2); // Check that first and second params are unpoisoned.
return 0;
}

#endif

0 comments on commit 8a9ce34

Please sign in to comment.