-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add AFL-based fuzzing setup for network modules #13157
Conversation
5e07da3
to
a405eb9
Compare
Hello, thank you for your contribution nmeum, I'm pretty happy to see that I'm not sure if this is the best place to ask, so I'm sorry for any potential inconvenience. If an issue would be more appropriate I will open one. Would there be any interest in integrating LLVM's LibFuzzer [1] fuzzing tests into RIOT too? I have been working on a paper about fuzzing, and have recently The advantage of LibFuzzer is that it is quicker to set up and fuzz |
@jvijtiuk if you already have something, go right ahead and make a PR. If not, I recommend an issue as a feature request, and "claiming" it, to prevent other people don't start working on it, while you do your work. In general I think having multiple tools doing the same thing is a good thing, as they might put the focus on different things. |
@benpicco Should I address your comments right away or is there more to come? I just want to avoid spending time on documenting something which doesn't end up being merged in the end. Is there a general interest in having a fuzzing setup? I don't mind if there isn't but this hasn't really received much attention which makes me think that there is not much interest in having something like this integrated into upstream RIOT. |
There is definitely interest in fuzzing! Fuzzing is definitely a feature we want - as you have proven with all the fuzzing based bugs you discovered. Thank you a lot for these! (And I think you generally got pretty swift responses there 😉) It's just that new, larger features take a bit more time to look at, and then sometimes PR are just forgotten. You can always ping maintainers if you feel your PR got swapped out of attention. Now with this I think it's pretty good. It's self contained and provides a valuable feature. |
30b3e0c
to
57f4a61
Compare
This adds a utility module which is used to write applications for fuzzing RIOT network modules. The module provides a dummy network interface which is configured with a static IPv6 addresses for modules which perform operations on the underlying network interface. Besides, it contains a utility function for transforming data received on standard input into a `gnrc_pktsnip_t`.
Since RIOT is an operating system the native binary will never terminate [0]. The termination condition for fuzzing GNRC is that the packet was handled by the network stack and therefore freed. If it is never freed we will deadlock meaning a memory leak was found, afl should be able to detect this through timeouts. This is currently only supported for gnrc_pktbuf_malloc since this is the pktbuf implementation I used for fuzzing. Implementing this in pktbuf.h is not possible. [0]: Except NATIVE_AUTO_EXIT is defined, however, even with that define set RIOT will only terminate when all threads terminated. Unfortunately, gnrc_udp and other network threads will never terminate.
The termination condition implemented in gnrc_pktbuf_malloc does not work when using the sock interface as sock copies packet data to a local buffer and frees the packet afterwards. As such, the fuzzing application would exit before performing any input processing. For this reason, the termination condition in gnrc_pktbuf_malloc is disabled when using sock. Instead, the application terminates if gnrc_sock_recv previously returned the fuzzing packet. The underlying assumption of this implementation is that gnrc_sock_recv is called in a loop.
Rebased and made some adjustments for recent API changes of |
57f4a61
to
5633ddf
Compare
@@ -747,6 +747,11 @@ test-input-hash: | |||
true | |||
endif | |||
|
|||
.PHONY: fuzz | |||
fuzz: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fuzz: | |
fuzz: all-asan |
So make fuzz
will always be enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is theoretically possible, I didn't do this initially because I did not want to enforce usage of the address sanitizer. For instance, to allow instrumentation with other sanitizers (e.g. UBSAN). Besides, some bugs (memory leaks) can also be found without using any sanitizer at all as AFL itself detects a hang in these cases (e.g. #12001).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally got around to testing this - work like a charm.
Just one minor comment: Can we make the fuzz
target depend on all-asan
so the user doesn't accidentally fuzz an old binary?
It would also be nice to add the |
I agree - I think adding the directory to |
Kind of, murdock seems to attempt building the applications now but it seems to fail for some reason (maybe missing makefile targets?):
…
and more similar messages. Any idea how to fix this? |
Maybe this is caused by a lack of |
Don't think so, seems to me the CI sets |
There are also some |
Yepp, murdock is unable to get the supported boards for your application:
|
I don't understand Github anymore... in case you missed it: solution is proposed here #13157 (comment) |
This adds a new subdirectory called `fuzzing/` which will contain applications for fuzzing various RIOT network modules in the future. This subdirectory is heavily inspired by the `examples/` subdirectory. The fuzzing applications use AFL as a fuzzer. Each application contains Makefiles, source code, and an input corpus used by AFL to generate input for fuzzing.
This should ensure that fuzzing applications are build by the CI.
086d486
to
24d71f9
Compare
Thank you very much, pushed an updated version. While at it, I also improved the documentation a bit. Let's see how this goes... :) |
Whoo that seems to have worked \o/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good and Murdock is happy.
Then let's merge this :-) |
Contribution description
This pull requests proposes a simple framework for fuzzing RIOT network
applications. Inspired by the
examples/
subdirectory it adds anadditional directory called
fuzzing/
with applications for fuzzingcertain network modules. The fuzzing setup is based on Michal
Zalewski's AFL fuzzer.
AFL generates random network packets from an input corpus and writes the
generated data to standard input. As such, each application in
fuzzing/
reads from standard input, converts the data to a
gnrc_pktsnip_t
, andpasses it to the network module under test using RIOT's message passing
mechanism.
The fuzzing applications are terminated as soon as the RIOT network
module under test finished processing the input data (fuzzing packet).
This is achieved differently for applications using GNRC directly and
applications using the sock interface. For the former, RIOT is
terminated using
exit(3)
as soon as the generated fuzzingpacket is passed to
gnrc_pktbuf_release
. For the latter, it isassumed that
gnrc_sock_recv
is called in a loop, if it iscalled again and the previously returned packet equals the
fuzzing packet, RIOT is terminated using
exit(3)
.I have written fuzzing applications for different modules and discovered
various bugs using these fuzzing applications (see related issues
below). This PR only contains a fuzzing applications for
gnrc_tcp
.Additional applications have been omitted for now to ease code review.
If desired, I will submit those separately later.
Needless to say, the fuzzing setup only works on
native
currently.Besides, it only sends a single packet and does not fuzz any sending
functions, only receiving functions. I don't think that this setup is
perfect as is, but is definitely usable in the sense that it finds
existing bugs. In my opinion, it is definitely superior to testing
network applications with hardcoded "malcious" packets as done currently
(e.g. #12369), if at all.
Testing procedure
Usage instructions are provided in
fuzzing/README.md
. The best way totest the
gnrc_tcp
fuzzing application and the fuzzing setup ingeneral is reverting some of the fixes listed below and checking whether
the fuzzing setup finds the underlying bugs again.
For instance:
At some point AFL will find a crash, keep in mind that this might take
a while though.
Issues/PRs references
The following lists issues found using the proposed fuzzing setup.
gnrc_tftp
gnrc_tcp
asymcute
emcute
dtls-sock
@miri64 you were involved in most issues listed above. Do you have any
though on the changes proposed here?