[compiler-rt] 70cbc6d - [libFuzzer] Fix stack overflow detection

Matt Morehouse via llvm-commits llvm-commits at lists.llvm.org
Fri May 7 08:18:42 PDT 2021


Author: Sebastian Poeplau
Date: 2021-05-07T08:18:28-07:00
New Revision: 70cbc6dbef7048d3b1aa89a676d96c6ba075b41b

URL: https://github.com/llvm/llvm-project/commit/70cbc6dbef7048d3b1aa89a676d96c6ba075b41b
DIFF: https://github.com/llvm/llvm-project/commit/70cbc6dbef7048d3b1aa89a676d96c6ba075b41b.diff

LOG: [libFuzzer] Fix stack overflow detection

Address sanitizer can detect stack exhaustion via its SEGV handler, which is
executed on a separate stack using the sigaltstack mechanism. When libFuzzer is
used with address sanitizer, it installs its own signal handlers which defer to
those put in place by the sanitizer before performing additional actions. In the
particular case of a stack overflow, the current setup fails because libFuzzer
doesn't preserve the flag for executing the signal handler on a separate stack:
when we run out of stack space, the operating system can't run the SEGV handler,
so address sanitizer never reports the issue. See the included test for an
example.

This commit fixes the issue by making libFuzzer preserve the SA_ONSTACK flag
when installing its signal handlers; the dedicated signal-handler stack set up
by the sanitizer runtime appears to be large enough to support the additional
frames from the fuzzer.

Reviewed By: morehouse

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

Added: 
    compiler-rt/test/fuzzer/StackOverflowTest.cpp
    compiler-rt/test/fuzzer/stack-overflow-with-asan.test

Modified: 
    compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
index afb733409ab51..0446d732a9ec8 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilPosix.cpp
@@ -77,10 +77,13 @@ static void SetSigaction(int signum,
       return;
   }
 
-  sigact = {};
-  sigact.sa_flags = SA_SIGINFO;
-  sigact.sa_sigaction = callback;
-  if (sigaction(signum, &sigact, 0)) {
+  struct sigaction new_sigact = {};
+  // Address sanitizer needs SA_ONSTACK (causing the signal handler to run on a
+  // dedicated stack) in order to be able to detect stack overflows; keep the
+  // flag if it's set.
+  new_sigact.sa_flags = SA_SIGINFO | (sigact.sa_flags & SA_ONSTACK);
+  new_sigact.sa_sigaction = callback;
+  if (sigaction(signum, &new_sigact, nullptr)) {
     Printf("libFuzzer: sigaction failed with %d\n", errno);
     exit(1);
   }

diff  --git a/compiler-rt/test/fuzzer/StackOverflowTest.cpp b/compiler-rt/test/fuzzer/StackOverflowTest.cpp
new file mode 100644
index 0000000000000..c8d8984957b25
--- /dev/null
+++ b/compiler-rt/test/fuzzer/StackOverflowTest.cpp
@@ -0,0 +1,26 @@
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+// Stack overflow test for a fuzzer. The fuzzer must find the string "Hi" and
+// cause a stack overflow.
+#include <cstddef>
+#include <cstdint>
+
+volatile int x;
+volatile int y = 1;
+
+int infinite_recursion(char *p) {
+  char *buf = nullptr;
+
+  if (y)
+    infinite_recursion(buf);
+
+  x = 1;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+  if (Size >= 2 && Data[0] == 'H' && Data[1] == 'i')
+    infinite_recursion(nullptr);
+  return 0;
+}

diff  --git a/compiler-rt/test/fuzzer/stack-overflow-with-asan.test b/compiler-rt/test/fuzzer/stack-overflow-with-asan.test
new file mode 100644
index 0000000000000..76be70b580e1b
--- /dev/null
+++ b/compiler-rt/test/fuzzer/stack-overflow-with-asan.test
@@ -0,0 +1,3 @@
+CHECK: SUMMARY: AddressSanitizer: stack-overflow
+RUN: %cpp_compiler %S/StackOverflowTest.cpp -o %t-StackOverflowTest
+RUN: not %run %t-StackOverflowTest 2>&1 | FileCheck %s


        


More information about the llvm-commits mailing list