[compiler-rt] r360379 - [MSan] Introduce __msan_unpoison_param().

Matt Morehouse via llvm-commits llvm-commits at lists.llvm.org
Thu May 9 14:50:57 PDT 2019


Author: morehouse
Date: Thu May  9 14:50:57 2019
New Revision: 360379

URL: http://llvm.org/viewvc/llvm-project?rev=360379&view=rev
Log:
[MSan] Introduce __msan_unpoison_param().

Summary:
This allows libFuzzer to unpoison parameter shadow before calling
LLVMFuzzerTestOneInput to eliminate the false positives described
in https://github.com/google/oss-fuzz/issues/2369.

Reviewers: eugenis

Reviewed By: eugenis

Subscribers: llvm-commits, metzman, kcc

Tags: #llvm

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

Added:
    compiler-rt/trunk/test/msan/unpoison_param.cc
Modified:
    compiler-rt/trunk/include/sanitizer/msan_interface.h
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    compiler-rt/trunk/lib/msan/msan_interface_internal.h

Modified: compiler-rt/trunk/include/sanitizer/msan_interface.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/include/sanitizer/msan_interface.h?rev=360379&r1=360378&r2=360379&view=diff
==============================================================================
--- compiler-rt/trunk/include/sanitizer/msan_interface.h (original)
+++ compiler-rt/trunk/include/sanitizer/msan_interface.h Thu May  9 14:50:57 2019
@@ -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. */

Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=360379&r1=360378&r2=360379&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Thu May  9 14:50:57 2019
@@ -1543,6 +1543,8 @@ void __msan_poison_stack(void *a, uptr s
   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);

Modified: compiler-rt/trunk/lib/msan/msan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interface_internal.h?rev=360379&r1=360378&r2=360379&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/msan/msan_interface_internal.h Thu May  9 14:50:57 2019
@@ -69,6 +69,8 @@ void __msan_unpoison(const void *a, uptr
 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);

Added: compiler-rt/trunk/test/msan/unpoison_param.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/unpoison_param.cc?rev=360379&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/unpoison_param.cc (added)
+++ compiler-rt/trunk/test/msan/unpoison_param.cc Thu May  9 14:50:57 2019
@@ -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




More information about the llvm-commits mailing list