[llvm-dev] Some feedback on Libfuzzer

Greg Stark via llvm-dev llvm-dev at lists.llvm.org
Sat Sep 12 11:48:47 PDT 2015


Sorry, I forgot to check in on this thread. I've made a lot of
progress on my side. I've worked around most of my issues, though
better interfaces to avoid workarounds would be great.

My main problem is the timeouts. Postgres uses ALRM and in fact I want
to specifically invoke that logic to detect cases where it's not
working (I.e. where we don't check for signals for too long). So what
I really want is something independent. I'm actually thinking of
implementing a side process that sends some other signal like SIGQUIT
or SIGFPE periodically.

What I did instead right now is replaced the setitimer with
setrlimit(RLIMIT_CPU) and set the AlarmHandler on SIGXCPU which Linux
fires once a second. That happens to be exactly what I want.

void SetTimer(int Seconds) {
int Res;
struct rlimit limit = {1, RLIM_INFINITY};
Res = setrlimit(RLIMIT_CPU, &limit);
assert(Res == 0);

struct sigaction sigact;
memset(&sigact, 0, sizeof(sigact));
sigact.sa_sigaction = AlarmHandler;
Res = sigaction(SIGXCPU, &sigact, 0);
assert(Res == 0);
}


On 8 Sep 2015 19:12, "Kostya Serebryany" <kcc at google.com> wrote:
>
>
>
> On Sat, Sep 5, 2015 at 11:50 AM, Greg Stark <stark at mit.edu> wrote:
>>
>> However I think this isn't the whole story here. There are many
>> different kinds of errors and not all are unrecoverable memory
>> failures. I may just get an internal error from my own code that I
>> know should never happen but doesn't represent major corruption. I
>> would like a way for the callback to return an error condition to the
>> fuzzer driver to have the test case set aside as a crash or perhaps as
>> a separate category (or perhaps to allow it to specify the name of the
>> category).
>
>
> For that you don't need libFuzzer support, right?
> You can intercept your specific type of bug in the target function.

That's exactly what I'm doing. I'm catching internal errors now and
call abort() so the fuzzer logs that test case as a crash.

What I'm doing now is (man I wish gmail was more useful for code):

diff --git a/FuzzerLoop.cpp b/FuzzerLoop.cpp
index dd81616..aa53046 100644
--- a/FuzzerLoop.cpp
+++ b/FuzzerLoop.cpp
@@ -77,6 +77,28 @@ void Fuzzer::AlarmCallback() {
   }
 }

+void Fuzzer::StaticErrorCallback(const char *errorname) {
+  assert(F);
+  F->ErrorCallback(errorname);
+}
+
+#include <string.h>
+void Fuzzer::ErrorCallback(const char *ErrorName) {
+ char prefix[80];
+ assert(strnlen(ErrorName, 80) < 80);
+ if (!ErrorName) {
+ strcpy(prefix, "error-");
+ } else {
+ sprintf(prefix, "%s-", ErrorName);
+ }
+
+    Printf("ERROR: Fuzzer Function reports an internal error\n");
+    if (CurrentUnit.size() <= kMaxUnitSizeToPrint)
+ Print(CurrentUnit, "\n");
+    PrintUnitInASCIIOrTokens(CurrentUnit, "\n");
+    WriteUnitToFileWithPrefix(CurrentUnit, prefix);
+}

So now my test function can call StaticErrorCallback("myerror") and
the driver will log that test in a file named myerror-<hash> and
return control to me. I can then return normally and the fuzzer will
continue. (Sorry for the C string.h)

It may be that I should just not use the Libfuzzer driver at all. Just
use the various functions from Libfuzzer for generating and keeping
track of cases but keep the main loop under my code.

>> I have yet to really experiment with the sanitizers so I don't know if
>> asan is really doing anything for me given Postgres's internal memory
>> management.
>
> That might be an interesting separate topic to discuss.

Fwiw I found it easy to hook ASAN_POISON macros using the existing
valgrind support so that's all good now.

> If you have custom memory management, msan will be as tricky to use as asan.
> Also, try ubsan for other kinds of bugs.

I think msan might be possible to hook with the same macros but I
can't get a working binary out of it. I get

configure:4042: ./conftest
FATAL: Code 0x5634731ac3f0 is out of application range. Non-PIE build?
FATAL: MemorySanitizer can not mmap the shadow memory.
FATAL: Make sure to compile with -fPIE and to link with -pie.
FATAL: Disabling ASLR is known to cause this error.
FATAL: If running under GDB, try 'set disable-randomization off'.

I get that even if I put -fPIE in CFLAGS.


More information about the llvm-dev mailing list