[RFC] iw: add clang-based fuzzer for scan IEs
diff mbox series

Message ID 20200211114502.4250-1-markus.theil@tu-ilmenau.de
State RFC
Delegated to: Johannes Berg
Headers show
Series
  • [RFC] iw: add clang-based fuzzer for scan IEs
Related show

Commit Message

Markus Theil Feb. 11, 2020, 11:45 a.m. UTC
This patch is not ready for inclusion into the repo, but only useful for
testing purposes.

Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>
---
 Makefile    | 24 ++++++++++++++++++++----
 fuzz.sh     |  5 +++++
 fuzz_scan.c |  6 ++++++
 iw.c        |  4 ++++
 4 files changed, 35 insertions(+), 4 deletions(-)
 create mode 100755 fuzz.sh
 create mode 100644 fuzz_scan.c

Comments

Julian Calaby Feb. 11, 2020, 1:47 p.m. UTC | #1
Hi Markus,

On Tue, Feb 11, 2020 at 11:42 PM Markus Theil
<markus.theil@tu-ilmenau.de> wrote:
>
> This patch is not ready for inclusion into the repo, but only useful for
> testing purposes.
>
> Signed-off-by: Markus Theil <markus.theil@tu-ilmenau.de>

A couple of minor comments:

> ---
>  Makefile    | 24 ++++++++++++++++++++----
>  fuzz.sh     |  5 +++++
>  fuzz_scan.c |  6 ++++++
>  iw.c        |  4 ++++
>  4 files changed, 35 insertions(+), 4 deletions(-)
>  create mode 100755 fuzz.sh
>  create mode 100644 fuzz_scan.c
>
> diff --git a/Makefile b/Makefile
> index 90f2251..4ba2daf 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -16,9 +16,9 @@ CFLAGS_EVAL := $(call cc-option,-Wstringop-overflow=4)
>  CFLAGS ?= -O2 -g
>  CFLAGS += -Wall -Wextra -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common \
>           -Werror-implicit-function-declaration -Wsign-compare -Wno-unused-parameter \
> -         $(CFLAGS_EVAL)
> +         $(CFLAGS_EVAL) $(EXTRA_CFLAGS)
>
> -_OBJS := $(sort $(patsubst %.c,%.o,$(wildcard *.c)))
> +_OBJS := $(filter-out iw.o fuzz_scan.o, $(sort $(patsubst %.c,%.o,$(wildcard *.c))))
>  VERSION_OBJS := $(filter-out version.o, $(_OBJS))
>  OBJS := $(VERSION_OBJS) version.o
>
> @@ -102,12 +102,28 @@ nl80211-commands.inc: nl80211.h
>         @$(NQ) ' CC  ' $@
>         $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
>
> +iw_main.o: iw.c iw.h nl80211.h nl80211-commands.inc
> +       @$(NQ) ' CC  ' $@
> +       $(Q)$(CC) $(CFLAGS) -DIW_MAIN=1 $(CPPFLAGS) -c -o $@ $<
> +
> +iw_no_main.o: iw.c iw.h nl80211.h nl80211-commands.inc
> +       @$(NQ) ' CC  ' $@
> +       $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
> +
>  ifeq ($(IW_ANDROID_BUILD),)
> -iw:    $(OBJS)
> +iw:    $(OBJS) iw_main.o
>         @$(NQ) ' CC  ' iw
> -       $(Q)$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o iw
> +       $(Q)$(CC) $(LDFLAGS) $(OBJS) iw_main.o $(LIBS) -o iw

You can use "$^" to get the full list of prerequisites instead of
spelling it out in both the rule definition and command.

I.e.

$(Q)$(CC) $(LDFLAGS) $^ $(LIBS) -o iw


There's a tool I'm aware of: https://github.com/google/AFL

Which does fuzzing by instrumenting the code under test and iterating
on input data. I'm not sure if it'll get you anything that LLVM's
built-in one won't, but it might be worth a try.

Thanks,
Johannes Berg Feb. 13, 2020, 8:19 p.m. UTC | #2
FWIW, I applied most of your patches, though some I squashed since you
just introduced the bugs in a previous non-applied patch ... :)

Regarding the fuzzing ... how long did you run this?

I adjusted this to afl-clang-fast (afl++, not the original) and it's not
finding much easily...

I guess making it realloc each element into a separate buffer so that
it's checking out-of-bounds for each element separately will help
somewhat, let's see...

johannes
Markus Theil Feb. 13, 2020, 9:42 p.m. UTC | #3
On 2/13/20 9:19 PM, Johannes Berg wrote:
> FWIW, I applied most of your patches, though some I squashed since you
> just introduced the bugs in a previous non-applied patch ... :)
;)
> Regarding the fuzzing ... how long did you run this?
The first bugs were found nearly instantly, the last ones after several 
minutes (<= 20).
> I adjusted this to afl-clang-fast (afl++, not the original) and it's not
> finding much easily...
>
> I guess making it realloc each element into a separate buffer so that
> it's checking out-of-bounds for each element separately will help
> somewhat, let's see...
>
> johannes
>
>

Patch
diff mbox series

diff --git a/Makefile b/Makefile
index 90f2251..4ba2daf 100644
--- a/Makefile
+++ b/Makefile
@@ -16,9 +16,9 @@  CFLAGS_EVAL := $(call cc-option,-Wstringop-overflow=4)
 CFLAGS ?= -O2 -g
 CFLAGS += -Wall -Wextra -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common \
 	  -Werror-implicit-function-declaration -Wsign-compare -Wno-unused-parameter \
-	  $(CFLAGS_EVAL)
+	  $(CFLAGS_EVAL) $(EXTRA_CFLAGS)
 
-_OBJS := $(sort $(patsubst %.c,%.o,$(wildcard *.c)))
+_OBJS := $(filter-out iw.o fuzz_scan.o, $(sort $(patsubst %.c,%.o,$(wildcard *.c))))
 VERSION_OBJS := $(filter-out version.o, $(_OBJS))
 OBJS := $(VERSION_OBJS) version.o
 
@@ -102,12 +102,28 @@  nl80211-commands.inc: nl80211.h
 	@$(NQ) ' CC  ' $@
 	$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
 
+iw_main.o: iw.c iw.h nl80211.h nl80211-commands.inc
+	@$(NQ) ' CC  ' $@
+	$(Q)$(CC) $(CFLAGS) -DIW_MAIN=1 $(CPPFLAGS) -c -o $@ $<
+
+iw_no_main.o: iw.c iw.h nl80211.h nl80211-commands.inc
+	@$(NQ) ' CC  ' $@
+	$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
 ifeq ($(IW_ANDROID_BUILD),)
-iw:	$(OBJS)
+iw:	$(OBJS) iw_main.o
 	@$(NQ) ' CC  ' iw
-	$(Q)$(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o iw
+	$(Q)$(CC) $(LDFLAGS) $(OBJS) iw_main.o $(LIBS) -o iw
 endif
 
+fuzz_scan.o: fuzz_scan.c iw.h
+	@$(NQ) ' CC  ' $@
+	$(Q)$(CC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $<
+
+fuzz_scan: fuzz_scan.o $(OBJS) iw_no_main.o
+	@$(NQ) ' CC  ' fuzz_scan
+	$(Q)$(CC) $(LDFLAGS) $(OBJS) iw_no_main.o fuzz_scan.o $(LIBS) -o fuzz_scan
+
 check:
 	$(Q)$(MAKE) all CC="REAL_CC=$(CC) CHECK=\"sparse -Wall\" cgcc"
 
diff --git a/fuzz.sh b/fuzz.sh
new file mode 100755
index 0000000..b98fecb
--- /dev/null
+++ b/fuzz.sh
@@ -0,0 +1,5 @@ 
+#!/bin/bash
+
+make V=1 CC=clang EXTRA_CFLAGS="-fsanitize=address,undefined,fuzzer" LDFLAGS="-fsanitize=fuzzer,address,undefined" fuzz_scan
+mkdir -p fuzz_corpus
+./fuzz_scan fuzz_corpus/ -max_len=512 -timeout=5 > /dev/null
diff --git a/fuzz_scan.c b/fuzz_scan.c
new file mode 100644
index 0000000..ed9da4f
--- /dev/null
+++ b/fuzz_scan.c
@@ -0,0 +1,6 @@ 
+#include "iw.h"
+
+int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+	print_ies((unsigned char *)data, size, size % 2, PRINT_SCAN);
+	return 0;
+}
\ No newline at end of file
diff --git a/iw.c b/iw.c
index da71617..1563543 100644
--- a/iw.c
+++ b/iw.c
@@ -562,6 +562,8 @@  int handle_cmd(struct nl80211_state *state, enum id_input idby,
 static struct cmd sizer1 __attribute__((section("__sizer"))) = {};
 static struct cmd sizer2 __attribute__((section("__sizer"))) = {};
 
+#ifdef IW_MAIN
+
 int main(int argc, char **argv)
 {
 	struct nl80211_state nlstate;
@@ -638,3 +640,5 @@  int main(int argc, char **argv)
 
 	return err;
 }
+
+#endif
\ No newline at end of file