From d79676744d77a74b3f8beea802a4aa9bc7ec1f60 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Tue, 16 Mar 2021 21:54:53 -0400 Subject: [PATCH 1/5] libfuzzer library integration tests --- .github/workflows/ci.yml | 13 ++++ src/integration-tests/integration-test.py | 38 ++++++++++ .../libfuzzer-dlopen/Makefile | 18 +++++ src/integration-tests/libfuzzer-dlopen/bad.c | 64 +++++++++++++++++ src/integration-tests/libfuzzer-dlopen/bad.h | 9 +++ src/integration-tests/libfuzzer-dlopen/main.c | 39 +++++++++++ .../libfuzzer-dlopen/seeds/good.txt | 1 + .../libfuzzer-linked-library/Makefile | 22 ++++++ .../libfuzzer-linked-library/Makefile.windows | 23 ++++++ .../libfuzzer-linked-library/bad1.c | 70 +++++++++++++++++++ .../libfuzzer-linked-library/bad1.h | 9 +++ .../libfuzzer-linked-library/bad2.c | 70 +++++++++++++++++++ .../libfuzzer-linked-library/bad2.h | 9 +++ .../libfuzzer-linked-library/main.c | 14 ++++ .../libfuzzer-linked-library/seeds/good.txt | 1 + 15 files changed, 400 insertions(+) create mode 100644 src/integration-tests/libfuzzer-dlopen/Makefile create mode 100644 src/integration-tests/libfuzzer-dlopen/bad.c create mode 100644 src/integration-tests/libfuzzer-dlopen/bad.h create mode 100644 src/integration-tests/libfuzzer-dlopen/main.c create mode 100644 src/integration-tests/libfuzzer-dlopen/seeds/good.txt create mode 100644 src/integration-tests/libfuzzer-linked-library/Makefile create mode 100644 src/integration-tests/libfuzzer-linked-library/Makefile.windows create mode 100644 src/integration-tests/libfuzzer-linked-library/bad1.c create mode 100644 src/integration-tests/libfuzzer-linked-library/bad1.h create mode 100644 src/integration-tests/libfuzzer-linked-library/bad2.c create mode 100644 src/integration-tests/libfuzzer-linked-library/bad2.h create mode 100644 src/integration-tests/libfuzzer-linked-library/main.c create mode 100644 src/integration-tests/libfuzzer-linked-library/seeds/good.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 358f9f3142..0aa7ac8867 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -366,6 +366,14 @@ jobs: (cd libfuzzer-dotnet; make) cp -r libfuzzer-dotnet/my-fuzzer libfuzzer-dotnet/inputs artifacts/linux-libfuzzer-dotnet/ + mkdir -p artifacts/linux-libfuzzer-dlopen + (cd libfuzzer-dlopen; make) + cp -r libfuzzer-dlopen/{fuzz.exe,*.so,seeds} artifacts/linux-libfuzzer-dlopen/ + + mkdir -p artifacts/linux-libfuzzer-linked-library + (cd libfuzzer-linked-library; make) + cp -r libfuzzer-linked-library/{fuzz.exe,*.so,seeds} artifacts/linux-libfuzzer-linked-library/ + mkdir -p artifacts/linux-trivial-crash-asan (cd trivial-crash ; make clean; make CFLAGS='-fsanitize=address -fno-omit-frame-pointer') cp -r trivial-crash/fuzz.exe trivial-crash/seeds artifacts/linux-trivial-crash-asan @@ -417,6 +425,11 @@ jobs: cp fuzz.exe,fuzz.pdb,seeds ../artifacts/windows-trivial-crash -Recurse cd ../ + mkdir artifacts/windows-libfuzzer-linked-library + cd libfuzzer-linked-library + make -F Makefile.windows + cp fuzz.exe,fuzz.pdb,bad1.dll,bad1.pdb,bad2.dll,bad2.pdb,seeds ../artifacts/windows-libfuzzer-linked-library -Recurse + mkdir artifacts/windows-trivial-crash-asan cd trivial-crash make clean diff --git a/src/integration-tests/integration-test.py b/src/integration-tests/integration-test.py index de945e8900..0bed5fbc1b 100755 --- a/src/integration-tests/integration-test.py +++ b/src/integration-tests/integration-test.py @@ -88,6 +88,32 @@ class Integration(BaseModel): }, reboot_after_setup=True, ), + "linux-libfuzzer-dlopen": Integration( + template=TemplateType.libfuzzer, + os=OS.linux, + target_exe="fuzz.exe", + inputs="seeds", + wait_for_files={ + ContainerType.unique_reports: 1, + ContainerType.coverage: 1, + ContainerType.inputs: 2, + }, + reboot_after_setup=True, + use_setup=True, + ), + "linux-libfuzzer-linked-library": Integration( + template=TemplateType.libfuzzer, + os=OS.linux, + target_exe="fuzz.exe", + inputs="seeds", + wait_for_files={ + ContainerType.unique_reports: 1, + ContainerType.coverage: 1, + ContainerType.inputs: 2, + }, + reboot_after_setup=True, + use_setup=True, + ), "linux-libfuzzer-dotnet": Integration( template=TemplateType.libfuzzer_dotnet, os=OS.linux, @@ -140,6 +166,18 @@ class Integration(BaseModel): ContainerType.coverage: 1, }, ), + "windows-libfuzzer-linked-library": Integration( + template=TemplateType.libfuzzer, + os=OS.windows, + target_exe="fuzz.exe", + inputs="seeds", + wait_for_files={ + ContainerType.inputs: 2, + ContainerType.unique_reports: 1, + ContainerType.coverage: 1, + }, + use_setup=True, + ), "windows-trivial-crash": Integration( template=TemplateType.radamsa, os=OS.windows, diff --git a/src/integration-tests/libfuzzer-dlopen/Makefile b/src/integration-tests/libfuzzer-dlopen/Makefile new file mode 100644 index 0000000000..f7284b3e52 --- /dev/null +++ b/src/integration-tests/libfuzzer-dlopen/Makefile @@ -0,0 +1,18 @@ +CC=clang +CFLAGS=-fsanitize=address,fuzzer -fPIC -O0 -ggdb3 + +.PHONY: all clean test + +all: libbad.so fuzz.exe + +fuzz.exe: main.o + $(CC) $(CFLAGS) -o $@ $< + +libbad.so: bad.o + $(CC) -shared -o $@ $< + +test: all + LD_LIBRARY_PATH=. ./fuzz.exe + +clean: + rm -rf fuzz.exe *.o *.so crash-* diff --git a/src/integration-tests/libfuzzer-dlopen/bad.c b/src/integration-tests/libfuzzer-dlopen/bad.c new file mode 100644 index 0000000000..3cf7449734 --- /dev/null +++ b/src/integration-tests/libfuzzer-dlopen/bad.c @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +int func(const uint8_t *data, size_t len) { + int cnt = 0; + + if (len < 4) { + return 0; + } + + if (data[0] == 'x') { cnt++; } + if (data[1] == 'y') { cnt++; } + if (data[2] == 'z') { cnt++; } + + if (cnt >= 3) { + switch (data[3]) { + case '0': { + // segv + int *p = NULL; *p = 123; + break; + } + case '1': { + // stack-buffer-underflow + int* p = &cnt - 32; for (int i = 0; i < 32; i++) { *(p + i) = 0; } + break; + } + case '2': { + // stack-buffer-overflow + int* p = &cnt + 32; for (int i = 0; i < 32; i++) { *(p - i) = 0; } + break; + } + case '3': { + // bad-free + int *p = &cnt; free(p); + break; + } + case '4': { + // double-free + int* p = malloc(sizeof(int)); free(p); free(p); + break; + } + case '5': { + // heap-use-after-free + int* p = malloc(sizeof(int)); free(p); *p = 123; + break; + } + case '6': { + // heap-buffer-overflow + int* p = malloc(8 * sizeof(int)); for (int i = 0; i < 32; i++) { *(p + i) = 0; } + break; + } + case '7': { + // fpe + int x = 0; int y = 123 / x; + break; + } + } + } + + return 0; +} diff --git a/src/integration-tests/libfuzzer-dlopen/bad.h b/src/integration-tests/libfuzzer-dlopen/bad.h new file mode 100644 index 0000000000..1fcd630cbd --- /dev/null +++ b/src/integration-tests/libfuzzer-dlopen/bad.h @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifndef BAD_H +#define BAD_H + +int func(const uint8_t *data, size_t len); + +#endif diff --git a/src/integration-tests/libfuzzer-dlopen/main.c b/src/integration-tests/libfuzzer-dlopen/main.c new file mode 100644 index 0000000000..48b8bdc3f1 --- /dev/null +++ b/src/integration-tests/libfuzzer-dlopen/main.c @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include + +int (*fuzz_func)(const uint8_t *data, size_t size); + +int LLVMFuzzerInitialize(int *argc, char ***argv) +{ + printf("initilize\n"); + void *handle; + int (*b)(void); + char *error; + + handle = dlopen("libbad.so", RTLD_LAZY); + if (!handle) + { + printf("can't open %s", dlerror()); + return 1; + } + fuzz_func = (int (*)(const uint8_t *data, size_t size))dlsym(handle, "func"); + error = dlerror(); + if (error != NULL) + { + printf("%s\n", error); + exit(EXIT_FAILURE); + } + return 0; +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + assert(fuzz_func != NULL); + return fuzz_func(data, size); +} diff --git a/src/integration-tests/libfuzzer-dlopen/seeds/good.txt b/src/integration-tests/libfuzzer-dlopen/seeds/good.txt new file mode 100644 index 0000000000..12799ccbe7 --- /dev/null +++ b/src/integration-tests/libfuzzer-dlopen/seeds/good.txt @@ -0,0 +1 @@ +good diff --git a/src/integration-tests/libfuzzer-linked-library/Makefile b/src/integration-tests/libfuzzer-linked-library/Makefile new file mode 100644 index 0000000000..515d7f0b23 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/Makefile @@ -0,0 +1,22 @@ +CC=clang + +.PHONY: all clean test + +all: fuzz.exe + +CFLAGS=-fsanitize=address,fuzzer -fPIC -O0 -ggdb3 + +fuzz.exe: main.o libbad1.so libbad2.so + $(CC) $(CFLAGS) -o $@ $< -lbad1 -lbad2 -L. + +libbad1.so: bad1.o + $(CC) -fsanitize=address -shared -o $@ $< + +libbad2.so: bad2.o + $(CC) -fsanitize=address -shared -o $@ $< + +test: all + LD_LIBRARY_PATH=. ./fuzz.exe + +clean: + rm -rf fuzz.exe *.o *.so *.dll crash-* *.lib *.exp *.pdb diff --git a/src/integration-tests/libfuzzer-linked-library/Makefile.windows b/src/integration-tests/libfuzzer-linked-library/Makefile.windows new file mode 100644 index 0000000000..f2983b85e2 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/Makefile.windows @@ -0,0 +1,23 @@ +CC=clang + +.PHONY: all clean test + +all: fuzz.exe + +CFLAGS=-g3 -fsanitize=address + +fuzz.exe: main.o bad1.dll bad2.dll + $(CC) -fsanitize=fuzzer,address main.o -o fuzz.exe -L. -lbad1 -lbad2 + +bad1.dll: bad1.o + $(CC) $(CFLAGS) -shared -o bad1.dll bad1.o + +bad2.dll: bad2.o + $(CC) $(CFLAGS) -shared -o bad2.dll bad2.o + + +test: all + LD_LIBRARY_PATH=. ./fuzz.exe + +clean: + rm -f *.dll *.exe *.exp *.pdb *.o *.lib diff --git a/src/integration-tests/libfuzzer-linked-library/bad1.c b/src/integration-tests/libfuzzer-linked-library/bad1.c new file mode 100644 index 0000000000..5563a62be6 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/bad1.c @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +#if defined(_WIN32) + #define LIBRARY_API __declspec(dllexport) +#else + #define LIBRARY_API +#endif + +int LIBRARY_API func1(const uint8_t *data, size_t len) { + int cnt = 0; + + if (len < 4) { + return 0; + } + + if (data[0] == 'x') { cnt++; } + if (data[1] == 'y') { cnt++; } + if (data[2] == 'z') { cnt++; } + + if (cnt >= 3) { + switch (data[3]) { + case '0': { + // segv + int *p = NULL; *p = 123; + break; + } + case '1': { + // stack-buffer-underflow + int* p = &cnt - 32; for (int i = 0; i < 32; i++) { *(p + i) = 0; } + break; + } + case '2': { + // stack-buffer-overflow + int* p = &cnt + 32; for (int i = 0; i < 32; i++) { *(p - i) = 0; } + break; + } + case '3': { + // bad-free + int *p = &cnt; free(p); + break; + } + case '4': { + // double-free + int* p = malloc(sizeof(int)); free(p); free(p); + break; + } + case '5': { + // heap-use-after-free + int* p = malloc(sizeof(int)); free(p); *p = 123; + break; + } + case '6': { + // heap-buffer-overflow + int* p = malloc(8 * sizeof(int)); for (int i = 0; i < 32; i++) { *(p + i) = 0; } + break; + } + case '7': { + // fpe + int x = 0; int y = 123 / x; + break; + } + } + } + + return 0; +} diff --git a/src/integration-tests/libfuzzer-linked-library/bad1.h b/src/integration-tests/libfuzzer-linked-library/bad1.h new file mode 100644 index 0000000000..a18736708c --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/bad1.h @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifndef BAD1_H +#define BAD1_H + +int func1(const uint8_t *data, size_t len); + +#endif diff --git a/src/integration-tests/libfuzzer-linked-library/bad2.c b/src/integration-tests/libfuzzer-linked-library/bad2.c new file mode 100644 index 0000000000..d863ffb265 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/bad2.c @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +#if defined(_WIN32) + #define LIBRARY_API __declspec(dllexport) +#else + #define LIBRARY_API +#endif + +int LIBRARY_API func2(const uint8_t *data, size_t len) { + int cnt = 0; + + if (len < 4) { + return 0; + } + + if (data[0] == 'a') { cnt++; } + if (data[1] == 'b') { cnt++; } + if (data[2] == 'c') { cnt++; } + + if (cnt >= 3) { + switch (data[3]) { + case '0': { + // segv + int *p = NULL; *p = 123; + break; + } + case '1': { + // stack-buffer-underflow + int* p = &cnt - 32; for (int i = 0; i < 32; i++) { *(p + i) = 0; } + break; + } + case '2': { + // stack-buffer-overflow + int* p = &cnt + 32; for (int i = 0; i < 32; i++) { *(p - i) = 0; } + break; + } + case '3': { + // bad-free + int *p = &cnt; free(p); + break; + } + case '4': { + // double-free + int* p = malloc(sizeof(int)); free(p); free(p); + break; + } + case '5': { + // heap-use-after-free + int* p = malloc(sizeof(int)); free(p); *p = 123; + break; + } + case '6': { + // heap-buffer-overflow + int* p = malloc(8 * sizeof(int)); for (int i = 0; i < 32; i++) { *(p + i) = 0; } + break; + } + case '7': { + // fpe + int x = 0; int y = 123 / x; + break; + } + } + } + + return 0; +} diff --git a/src/integration-tests/libfuzzer-linked-library/bad2.h b/src/integration-tests/libfuzzer-linked-library/bad2.h new file mode 100644 index 0000000000..2ded409026 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/bad2.h @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#ifndef BAD2_H +#define BAD2_H + +int func2(const uint8_t *data, size_t len); + +#endif diff --git a/src/integration-tests/libfuzzer-linked-library/main.c b/src/integration-tests/libfuzzer-linked-library/main.c new file mode 100644 index 0000000000..81f3634a41 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/main.c @@ -0,0 +1,14 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +#include "bad1.h" +#include "bad2.h" + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + func1(data, size); + func2(data, size); + return 0; +} diff --git a/src/integration-tests/libfuzzer-linked-library/seeds/good.txt b/src/integration-tests/libfuzzer-linked-library/seeds/good.txt new file mode 100644 index 0000000000..12799ccbe7 --- /dev/null +++ b/src/integration-tests/libfuzzer-linked-library/seeds/good.txt @@ -0,0 +1 @@ +good From d8ca03babb13e0b7d21b6f973a940d2e48693a30 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Tue, 16 Mar 2021 22:02:58 -0400 Subject: [PATCH 2/5] fix typo --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aa7ac8867..1cc4845260 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -427,7 +427,7 @@ jobs: mkdir artifacts/windows-libfuzzer-linked-library cd libfuzzer-linked-library - make -F Makefile.windows + make -f Makefile.windows cp fuzz.exe,fuzz.pdb,bad1.dll,bad1.pdb,bad2.dll,bad2.pdb,seeds ../artifacts/windows-libfuzzer-linked-library -Recurse mkdir artifacts/windows-trivial-crash-asan From b7cf9a03d2a40b9cc4a0c474dca9c5e8839dda6e Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Tue, 16 Mar 2021 22:13:50 -0400 Subject: [PATCH 3/5] add cd --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cc4845260..e07cc2f151 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -429,6 +429,7 @@ jobs: cd libfuzzer-linked-library make -f Makefile.windows cp fuzz.exe,fuzz.pdb,bad1.dll,bad1.pdb,bad2.dll,bad2.pdb,seeds ../artifacts/windows-libfuzzer-linked-library -Recurse + cd ../ mkdir artifacts/windows-trivial-crash-asan cd trivial-crash From 55528ce5b87a233e0b456bf4fa4ffd54d170b0b0 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Wed, 17 Mar 2021 10:49:50 -0400 Subject: [PATCH 4/5] fix windows builds --- .../libfuzzer-linked-library/Makefile.windows | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/integration-tests/libfuzzer-linked-library/Makefile.windows b/src/integration-tests/libfuzzer-linked-library/Makefile.windows index f2983b85e2..620fb6edfc 100644 --- a/src/integration-tests/libfuzzer-linked-library/Makefile.windows +++ b/src/integration-tests/libfuzzer-linked-library/Makefile.windows @@ -4,10 +4,10 @@ CC=clang all: fuzz.exe -CFLAGS=-g3 -fsanitize=address +CFLAGS=-g3 -fsanitize=address,fuzzer fuzz.exe: main.o bad1.dll bad2.dll - $(CC) -fsanitize=fuzzer,address main.o -o fuzz.exe -L. -lbad1 -lbad2 + $(CC) $(CFLAGS) main.o -o fuzz.exe -L. -lbad1 -lbad2 bad1.dll: bad1.o $(CC) $(CFLAGS) -shared -o bad1.dll bad1.o From dc2dc8ac4aaa71352435cdb1191fbd2b83e5f776 Mon Sep 17 00:00:00 2001 From: bmc-msft <41130664+bmc-msft@users.noreply.github.com> Date: Wed, 17 Mar 2021 12:42:53 -0400 Subject: [PATCH 5/5] Update src/integration-tests/libfuzzer-dlopen/main.c Co-authored-by: Joe Ranweiler --- src/integration-tests/libfuzzer-dlopen/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/integration-tests/libfuzzer-dlopen/main.c b/src/integration-tests/libfuzzer-dlopen/main.c index 48b8bdc3f1..26e8ab1cad 100644 --- a/src/integration-tests/libfuzzer-dlopen/main.c +++ b/src/integration-tests/libfuzzer-dlopen/main.c @@ -11,7 +11,7 @@ int (*fuzz_func)(const uint8_t *data, size_t size); int LLVMFuzzerInitialize(int *argc, char ***argv) { - printf("initilize\n"); + printf("initialize\n"); void *handle; int (*b)(void); char *error;