[EXAMPLE] How to add a source3 fuzz target

Douglas Bagnall douglas.bagnall at catalyst.net.nz
Sun Jan 12 10:00:06 UTC 2020


Maybe you are a Samba developer who has noticed some activity around
automated fuzzing, but you haven't really got your head around how to
add a fuzz target in your subdomain. This message is meant to show you
how easy it is. So easy, in fact, that you might prefer to skip to the
attached patch.

My process for finding this target was:

1. `git grep parse_ -- source3`.

2. look for a function that looks like it
   a. does a bit of work,
   b. probably deals with untrusted data,
   c. is not enmeshed in a whole lot of state.

So already with point 1, you know that YOU can do better.

For point 2, I saw this parse_packet() was filling out nested
structures using a tree of function calls (that's 2a), has a networky
sounding name (2b), and there is no context pointer involved (2c). (If
there was a context pointer, that would be OK if we could create the
context afresh every time, or if it wasn't really modified).

With the target selected, you make a file in lib/fuzzing with a
function called LLVMFuzzerTestOneInput(). That is libfuzzer's entry
point. LLVMFuzzerTestOneInput() essentially takes a datablob and
returns 0 (always 0 -- you report errors with abort()). This is
sort of enough to fuzz nmblib's parse_packet:

  int LLVMFuzzerTestOneInput(uint8_t *input, size_t len)
  {
          struct packet_struct *p = NULL;
          struct in_addr ip = {
                  0x0100007f /* 127.0.0.1 */
          };

          p = parse_packet((char *)input,
                           len,
                           NMB_PACKET,
                           ip,
                           1234);
          return 0;
  }

but that's a bit useless. It [hopefully] tells us that parse_packet()
doesn't crash, but it doesn't warn us if it is returning deadly
structures. So we add in a round trip using build_packet() and a test
to ensure p->packet.nmb.question.question_name.name exists, which I
think something somewhere assumes is true. Anybody who knew anything
about nmb packets could add more checks, which they would do by
straight out doing the thing that might crash, not by making careful
assertions.

To compile it we add a stanza to wscript_build using the standard mix
of copy, paste, trial, error, and guesswork. Then you need to compile
it differently. What I use is a wrapper around libfuzzer and compilers
called Honggfuzz. The steps to get it are something like:

$  git clone git at github.com:google/honggfuzz.git
$  cd honggfuzz
$  make

then back in samba, you need a fancy configure line:

$  rm -r bin
$  buildtools/bin/waf -C \
                --without-gettext \
                --enable-debug \
                --enable-developer \
                --enable-libfuzzer \
                CC=$PATH_TO_HONGGFUZZ/hfuzz_cc/hfuzz-clang \
                configure \
                LINK_CC=$PATH_TO_HONGGFUZZ/hfuzz_cc/hfuzz-clang \
                --disable-warnings-as-errors  \
                --abi-check-disable
$  make -j

Maybe not all of those options are necessary, but at some point they
were each for something. I think at least you'll need
'--enable-libfuzzer CC=...'.

Then run it:

$  mkdir nmb_parse_seeds
$  $PATH_TO_HONGGFUZZ/honggfuzz  -V -T -F 50000 \
          -i nmb_parse_seeds \
          -- bin/fuzz_nmblib_parse_packet

This will create fuzz packets based on the the examples in
./nmb_parse_seeds, of which there are initially none. It will mutate
and add to these (initially mutating the empty string), trying to find
packets that lead to new code pathways. While it doing this it shows
you how it's going on a console dashboard. If a packet causes a crash
or abort (or with -T, a timeout), it saves that packet in a weirdly
named file and writes a report in (by default) HONGGFUZZ_REPORT.TXT.

To replay a packet in gdb or valgrind, you just do this:

$  gdb --args ./bin/fuzz_nmblib_parse_packet $the_file_name

and the problem should become apparent.

Needless to say, I have found no crashes with this particular patch,
and I suspect it is not actually a very good target. But perhaps it is
an excellent target and we just happen to have very good code!

The main point is that you should consider adding targets; now that we
have made fuzzing Samba easy, we want to ensure that *we* are the ones
doing it.

cheers,
Douglas
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-fuzz-add-nmblib-parse_packet-target.patch
Type: text/x-patch
Size: 3102 bytes
Desc: not available
URL: <http://lists.samba.org/pipermail/samba-technical/attachments/20200112/7750eca2/0001-fuzz-add-nmblib-parse_packet-target.bin>


More information about the samba-technical mailing list