From 965fc94e4910da14d13a2f10d997cc720b3f6127 Mon Sep 17 00:00:00 2001 From: Arjun Date: Sat, 25 May 2024 17:52:02 +0530 Subject: fuzzing: add fuzzing infrastructure in build system Signed-off-by: Arjun Reviewed-by: Andrew Clayton Signed-off-by: Andrew Clayton --- fuzzing/build-fuzz.sh | 20 ++++++++++++++++++++ fuzzing/oss-fuzz.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 fuzzing/build-fuzz.sh create mode 100644 fuzzing/oss-fuzz.sh (limited to 'fuzzing') diff --git a/fuzzing/build-fuzz.sh b/fuzzing/build-fuzz.sh new file mode 100644 index 00000000..04f080d9 --- /dev/null +++ b/fuzzing/build-fuzz.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash + +export CC=clang +export CXX=clang++ +export CFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address,undefined -fsanitize=fuzzer-no-link" +export CXXFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address,undefined -fsanitize=fuzzer-no-link" +export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" + +./configure --no-regex --no-pcre2 --fuzz=$LIB_FUZZING_ENGINE +make fuzz -j$(nproc) + +mkdir -p build/fuzz_basic_seed +mkdir -p build/fuzz_http_controller_seed +mkdir -p build/fuzz_http_h1p_seed +mkdir -p build/fuzz_http_h1p_peer_seed +mkdir -p build/fuzz_json_seed + +echo "" +echo "Run: ./build/\${fuzzer} build/\${fuzzer}_seed src/fuzz/\${fuzzer}_seed_corpus" +echo "" diff --git a/fuzzing/oss-fuzz.sh b/fuzzing/oss-fuzz.sh new file mode 100644 index 00000000..1fe5ecda --- /dev/null +++ b/fuzzing/oss-fuzz.sh @@ -0,0 +1,29 @@ +#!/bin/bash -eu + +# Build unit +./configure --no-regex --no-pcre2 --fuzz="$LIB_FUZZING_ENGINE" +make fuzz -j"$(nproc)" + +# Copy all fuzzers. +cp build/fuzz_* $OUT/ + +# cd into fuzzing dir +pushd fuzzing/ +cp fuzz_http.dict $OUT/fuzz_http_controller.dict +cp fuzz_http.dict $OUT/fuzz_http_h1p.dict +cp fuzz_http.dict $OUT/fuzz_http_h1p_peer.dict + +# Create temporary directories. +cp -r fuzz_http_seed_corpus/ fuzz_http_controller_seed_corpus/ +cp -r fuzz_http_seed_corpus/ fuzz_http_h1p_seed_corpus/ +cp -r fuzz_http_seed_corpus/ fuzz_http_h1p_peer_seed_corpus/ + +zip -r $OUT/fuzz_basic_seed_corpus.zip fuzz_basic_seed_corpus/ +zip -r $OUT/fuzz_http_controller_seed_corpus.zip fuzz_http_controller_seed_corpus/ +zip -r $OUT/fuzz_http_h1p_seed_corpus.zip fuzz_http_h1p_seed_corpus/ +zip -r $OUT/fuzz_http_h1p_peer_seed_corpus.zip fuzz_http_h1p_peer_seed_corpus/ +zip -r $OUT/fuzz_json_seed_corpus.zip fuzz_json_seed_corpus/ + +# Delete temporary directories. +rm -r fuzz_http_controller_seed_corpus/ fuzz_http_h1p_seed_corpus/ fuzz_http_h1p_peer_seed_corpus/ +popd -- cgit From a93d878e5c3a6c3476e77d021ae59dc937e3066c Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 12 Jun 2024 10:34:09 +0530 Subject: fuzzing: add fuzzing targets Signed-off-by: Arjun Reviewed-by: Andrew Clayton Signed-off-by: Andrew Clayton --- fuzzing/nxt_basic_fuzz.c | 91 ++++++++++++++++++++++++++++++++++++++ fuzzing/nxt_http_controller_fuzz.c | 87 ++++++++++++++++++++++++++++++++++++ fuzzing/nxt_http_h1p_fuzz.c | 85 +++++++++++++++++++++++++++++++++++ fuzzing/nxt_http_h1p_peer_fuzz.c | 86 +++++++++++++++++++++++++++++++++++ fuzzing/nxt_json_fuzz.c | 76 +++++++++++++++++++++++++++++++ 5 files changed, 425 insertions(+) create mode 100644 fuzzing/nxt_basic_fuzz.c create mode 100644 fuzzing/nxt_http_controller_fuzz.c create mode 100644 fuzzing/nxt_http_h1p_fuzz.c create mode 100644 fuzzing/nxt_http_h1p_peer_fuzz.c create mode 100644 fuzzing/nxt_json_fuzz.c (limited to 'fuzzing') diff --git a/fuzzing/nxt_basic_fuzz.c b/fuzzing/nxt_basic_fuzz.c new file mode 100644 index 00000000..df3a1b6a --- /dev/null +++ b/fuzzing/nxt_basic_fuzz.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include + + +#define KMININPUTLENGTH 2 +#define KMAXINPUTLENGTH 128 + + +extern int LLVMFuzzerInitialize(int *argc, char ***argv); +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + +void nxt_base64_fuzz(const u_char *data, size_t size); +void nxt_term_fuzz(const u_char *data, size_t size); +void nxt_time_fuzz(const u_char *data, size_t size); +void nxt_utf8_fuzz(const u_char *data, size_t size); + + +extern char **environ; + + +int +LLVMFuzzerInitialize(int *argc, char ***argv) +{ + if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) { + return NXT_ERROR; + } + + return 0; +} + + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { + return 0; + } + + nxt_base64_fuzz(data, size); + nxt_term_fuzz(data, size); + nxt_time_fuzz(data, size); + nxt_utf8_fuzz(data, size); + + return 0; +} + + +void +nxt_base64_fuzz(const u_char *data, size_t size) +{ + u_char buf[256]; + ssize_t ret; + + /* + * Validate base64 data before decoding. + */ + ret = nxt_base64_decode(NULL, (u_char *)data, size); + if (ret == NXT_ERROR) { + return; + } + + nxt_base64_decode(buf, (u_char *)data, size); +} + + +void +nxt_term_fuzz(const u_char *data, size_t size) +{ + nxt_term_parse(data, size, 0); + nxt_term_parse(data, size, 1); +} + + +void +nxt_time_fuzz(const u_char *data, size_t size) +{ + nxt_time_parse(data, size); +} + + +void +nxt_utf8_fuzz(const u_char *data, size_t size) +{ + const u_char *in; + + in = data; + nxt_utf8_decode(&in, data + size); +} diff --git a/fuzzing/nxt_http_controller_fuzz.c b/fuzzing/nxt_http_controller_fuzz.c new file mode 100644 index 00000000..b7c6c272 --- /dev/null +++ b/fuzzing/nxt_http_controller_fuzz.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include + +/* DO NOT TRY THIS AT HOME! */ +#include "nxt_controller.c" + + +#define KMININPUTLENGTH 2 +#define KMAXINPUTLENGTH 1024 + + +extern int LLVMFuzzerInitialize(int *argc, char ***argv); +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + + +extern char **environ; + + +int +LLVMFuzzerInitialize(int *argc, char ***argv) +{ + nxt_int_t ret; + + if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) { + return NXT_ERROR; + } + + ret = nxt_http_fields_hash(&nxt_controller_fields_hash, + nxt_controller_request_fields, + nxt_nitems(nxt_controller_request_fields)); + if (ret != NXT_OK) { + return NXT_ERROR; + } + + return 0; +} + + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + nxt_mp_t *mp; + nxt_buf_mem_t buf; + nxt_controller_request_t *r_controller; + nxt_http_request_parse_t rp; + + if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { + return 0; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return 0; + } + + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + if (nxt_http_parse_request_init(&rp, mp) != NXT_OK) { + goto failed; + } + + buf.start = (u_char *)data; + buf.end = (u_char *)data + size; + buf.pos = buf.start; + buf.free = buf.end; + + if (nxt_http_parse_request(&rp, &buf) != NXT_DONE) { + goto failed; + } + + r_controller = nxt_mp_zget(mp, sizeof(nxt_controller_request_t)); + + if (r_controller == NULL) { + goto failed; + } + + nxt_http_fields_process(rp.fields, &nxt_controller_fields_hash, + r_controller); + +failed: + + nxt_mp_destroy(mp); + + return 0; +} diff --git a/fuzzing/nxt_http_h1p_fuzz.c b/fuzzing/nxt_http_h1p_fuzz.c new file mode 100644 index 00000000..471e87a4 --- /dev/null +++ b/fuzzing/nxt_http_h1p_fuzz.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include + +/* DO NOT TRY THIS AT HOME! */ +#include "nxt_h1proto.c" + + +#define KMININPUTLENGTH 2 +#define KMAXINPUTLENGTH 1024 + + +extern int LLVMFuzzerInitialize(int *argc, char ***argv); +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + + +extern char **environ; + + +int +LLVMFuzzerInitialize(int *argc, char ***argv) +{ + nxt_int_t ret; + + if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) { + return NXT_ERROR; + } + + ret = nxt_http_fields_hash(&nxt_h1p_fields_hash, + nxt_h1p_fields, nxt_nitems(nxt_h1p_fields)); + if (ret != NXT_OK) { + return NXT_ERROR; + } + + return 0; +} + + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + nxt_mp_t *mp; + nxt_buf_mem_t buf; + nxt_http_request_t *r_h1p; + nxt_http_request_parse_t rp; + + if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { + return 0; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return 0; + } + + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + if (nxt_http_parse_request_init(&rp, mp) != NXT_OK) { + goto failed; + } + + buf.start = (u_char *)data; + buf.end = (u_char *)data + size; + buf.pos = buf.start; + buf.free = buf.end; + + if (nxt_http_parse_request(&rp, &buf) != NXT_DONE) { + goto failed; + } + + r_h1p = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); + + if (r_h1p == NULL) { + goto failed; + } + + nxt_http_fields_process(rp.fields, &nxt_h1p_fields_hash, r_h1p); + +failed: + + nxt_mp_destroy(mp); + + return 0; +} diff --git a/fuzzing/nxt_http_h1p_peer_fuzz.c b/fuzzing/nxt_http_h1p_peer_fuzz.c new file mode 100644 index 00000000..7b722248 --- /dev/null +++ b/fuzzing/nxt_http_h1p_peer_fuzz.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include + +/* DO NOT TRY THIS AT HOME! */ +#include "nxt_h1proto.c" + + +#define KMININPUTLENGTH 2 +#define KMAXINPUTLENGTH 1024 + + +extern int LLVMFuzzerInitialize(int *argc, char ***argv); +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + + +extern char **environ; + + +int +LLVMFuzzerInitialize(int *argc, char ***argv) +{ + nxt_int_t ret; + + if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) { + return NXT_ERROR; + } + + ret = nxt_http_fields_hash(&nxt_h1p_peer_fields_hash, + nxt_h1p_peer_fields, + nxt_nitems(nxt_h1p_peer_fields)); + if (ret != NXT_OK) { + return NXT_ERROR; + } + + return 0; +} + + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + nxt_mp_t *mp; + nxt_buf_mem_t buf; + nxt_http_request_t *r_h1p_peer; + nxt_http_request_parse_t rp; + + if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { + return 0; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return 0; + } + + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + if (nxt_http_parse_request_init(&rp, mp) != NXT_OK) { + goto failed; + } + + buf.start = (u_char *)data; + buf.end = (u_char *)data + size; + buf.pos = buf.start; + buf.free = buf.end; + + if (nxt_http_parse_request(&rp, &buf) != NXT_DONE) { + goto failed; + } + + r_h1p_peer = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); + + if (r_h1p_peer == NULL) { + goto failed; + } + + nxt_http_fields_process(rp.fields, &nxt_h1p_peer_fields_hash, r_h1p_peer); + +failed: + + nxt_mp_destroy(mp); + + return 0; +} diff --git a/fuzzing/nxt_json_fuzz.c b/fuzzing/nxt_json_fuzz.c new file mode 100644 index 00000000..532babb1 --- /dev/null +++ b/fuzzing/nxt_json_fuzz.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) NGINX, Inc. + */ + +#include +#include + + +#define KMININPUTLENGTH 2 +#define KMAXINPUTLENGTH 1024 + + +extern int LLVMFuzzerInitialize(int *argc, char ***argv); +extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); + + +extern char **environ; + + +int +LLVMFuzzerInitialize(int *argc, char ***argv) +{ + if (nxt_lib_start("fuzzing", NULL, &environ) != NXT_OK) { + return NXT_ERROR; + } + + return 0; +} + + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + nxt_mp_t *mp; + nxt_str_t input; + nxt_conf_value_t *conf; + nxt_conf_validation_t vldt; + + if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { + return 0; + } + + mp = nxt_mp_create(1024, 128, 256, 32); + if (mp == NULL) { + return 0; + } + + input.start = (u_char *)data; + input.length = size; + + conf = nxt_conf_json_parse_str(mp, &input); + if (conf == NULL) { + goto failed; + } + + nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); + + vldt.pool = nxt_mp_create(1024, 128, 256, 32); + if (vldt.pool == NULL) { + goto failed; + } + + vldt.conf = conf; + vldt.conf_pool = mp; + vldt.ver = NXT_VERNUM; + + nxt_conf_validate(&vldt); + + nxt_mp_destroy(vldt.pool); + +failed: + + nxt_mp_destroy(mp); + + return 0; +} -- cgit From 665353dcb4a9d018f124127151b320632c177f26 Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 12 Jun 2024 10:36:39 +0530 Subject: fuzzing: add a fuzzing seed corpus and dictionary Signed-off-by: Arjun Reviewed-by: Andrew Clayton Signed-off-by: Andrew Clayton --- fuzzing/fuzz_basic_seed_corpus/base64_0.bin | Bin 0 -> 12 bytes fuzzing/fuzz_basic_seed_corpus/term_0.bin | Bin 0 -> 26 bytes fuzzing/fuzz_basic_seed_corpus/term_1.bin | Bin 0 -> 26 bytes fuzzing/fuzz_basic_seed_corpus/utf8_0.bin | Bin 0 -> 26 bytes fuzzing/fuzz_http.dict | 38 +++++++++++++++++++++ .../fuzz_http_seed_corpus/nxt_http_test_bench.bin | 16 +++++++++ .../fuzz_http_seed_corpus/nxt_http_test_run_0.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_1.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_10.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_11.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_12.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_13.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_14.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_15.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_16.bin | 4 +++ .../fuzz_http_seed_corpus/nxt_http_test_run_17.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_18.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_19.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_2.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_20.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_21.bin | 4 +++ .../fuzz_http_seed_corpus/nxt_http_test_run_22.bin | 3 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_23.bin | 5 +++ .../fuzz_http_seed_corpus/nxt_http_test_run_24.bin | 5 +++ .../fuzz_http_seed_corpus/nxt_http_test_run_3.bin | 1 + .../fuzz_http_seed_corpus/nxt_http_test_run_4.bin | 1 + .../fuzz_http_seed_corpus/nxt_http_test_run_5.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_6.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_7.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_8.bin | 2 ++ .../fuzz_http_seed_corpus/nxt_http_test_run_9.bin | 2 ++ fuzzing/fuzz_json_seed_corpus/json_0.bin | 1 + fuzzing/fuzz_json_seed_corpus/json_1.bin | 1 + fuzzing/fuzz_json_seed_corpus/json_2.bin | 1 + fuzzing/fuzz_json_seed_corpus/json_3.bin | 1 + fuzzing/fuzz_json_seed_corpus/json_4.bin | 1 + 36 files changed, 127 insertions(+) create mode 100644 fuzzing/fuzz_basic_seed_corpus/base64_0.bin create mode 100644 fuzzing/fuzz_basic_seed_corpus/term_0.bin create mode 100644 fuzzing/fuzz_basic_seed_corpus/term_1.bin create mode 100644 fuzzing/fuzz_basic_seed_corpus/utf8_0.bin create mode 100644 fuzzing/fuzz_http.dict create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin create mode 100644 fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin create mode 100644 fuzzing/fuzz_json_seed_corpus/json_0.bin create mode 100644 fuzzing/fuzz_json_seed_corpus/json_1.bin create mode 100644 fuzzing/fuzz_json_seed_corpus/json_2.bin create mode 100644 fuzzing/fuzz_json_seed_corpus/json_3.bin create mode 100644 fuzzing/fuzz_json_seed_corpus/json_4.bin (limited to 'fuzzing') diff --git a/fuzzing/fuzz_basic_seed_corpus/base64_0.bin b/fuzzing/fuzz_basic_seed_corpus/base64_0.bin new file mode 100644 index 00000000..71501405 Binary files /dev/null and b/fuzzing/fuzz_basic_seed_corpus/base64_0.bin differ diff --git a/fuzzing/fuzz_basic_seed_corpus/term_0.bin b/fuzzing/fuzz_basic_seed_corpus/term_0.bin new file mode 100644 index 00000000..c7fff416 Binary files /dev/null and b/fuzzing/fuzz_basic_seed_corpus/term_0.bin differ diff --git a/fuzzing/fuzz_basic_seed_corpus/term_1.bin b/fuzzing/fuzz_basic_seed_corpus/term_1.bin new file mode 100644 index 00000000..bd03def0 Binary files /dev/null and b/fuzzing/fuzz_basic_seed_corpus/term_1.bin differ diff --git a/fuzzing/fuzz_basic_seed_corpus/utf8_0.bin b/fuzzing/fuzz_basic_seed_corpus/utf8_0.bin new file mode 100644 index 00000000..d395758e Binary files /dev/null and b/fuzzing/fuzz_basic_seed_corpus/utf8_0.bin differ diff --git a/fuzzing/fuzz_http.dict b/fuzzing/fuzz_http.dict new file mode 100644 index 00000000..0a198414 --- /dev/null +++ b/fuzzing/fuzz_http.dict @@ -0,0 +1,38 @@ +"Accept-Encoding" +"Accept-Language" +"Accept" +"Authorization" +"Cache-Control" +"Connection" +"Content-Length" +"Content-Range" +"Content-Type" +"Cookie" +"Date" +"Expect" +"Host" +"If-Match" +"If-Modified-Since" +"If-None-Match" +"If-Range" +"If-Unmodified-Since" +"Keep-Alive" +"Origin" +"Pragma" +"Range" +"Referer" +"Sec-WebSocket-Key" +"Sec-WebSocket-Version" +"Server" +"TE" +"Transfer-Encoding" +"Upgrade-Insecure-Requests" +"Upgrade" +"User-Agent" +"Via" +"X-Forwarded-For" +"X-Forwarded-Host" +"X-Forwarded-Proto" +"X-Http-Method-Override" +"X-Real-IP" +"X-Request-ID" diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin new file mode 100644 index 00000000..64e2f7e8 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_bench.bin @@ -0,0 +1,16 @@ +POST /path/to/very/interesting/article/on.this.site?arg1=value&arg2=value2&very_big_arg=even_bigger_value HTTP/1.1 +Host: www.example.com +User-Agent: Mozilla/5.0 (X11; Gentoo Linux x86_64; rv:42.0) Firefox/42.0 +Accept: text/html,application/json,application/xml;q=0.9,*/*;q=0.8 +Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 +Accept-Encoding: gzip, deflate, br +If-Modified-Since: Wed, 31 Dec 1986 16:00:00 GMT +Referer: https://example.org/path/to/not-interesting/article.html +Cookie: name=value; name2=value2; some_big_cookie=Olr+/9hoA0og/dAcHH1p8sEFAHAAAAAElFTkSuQmCC +Connection: keep-alive +Content-Length: 0 +Upgrade-Insecure-Requests: 1 +Pragma: no-cache +Cache-Control: no-cache +X-Forwarded-For: 192.0.2.0, 198.51.100.0, 203.0.113.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin new file mode 100644 index 00000000..00ff084d --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_0.bin @@ -0,0 +1,2 @@ +XXX-METHOD /d.ir/fi+le.ext?key=val HTTP/1.2 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin new file mode 100644 index 00000000..2f6c6149 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_1.bin @@ -0,0 +1,2 @@ +GEt / HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin new file mode 100644 index 00000000..03337016 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_10.bin @@ -0,0 +1,2 @@ +GET /na %20me.ext?args HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin new file mode 100644 index 00000000..bac5bc27 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_11.bin @@ -0,0 +1,2 @@ +GET / HTTP/1.0 HTTP/1.1 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin new file mode 100644 index 00000000..75bd72e2 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_12.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Host:example.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin new file mode 100644 index 00000000..2216ec8d --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_13.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Host: + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin new file mode 100644 index 00000000..12435096 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_14.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +:Host: example.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin new file mode 100644 index 00000000..88bb36f4 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_15.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Ho_st: example.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin new file mode 100644 index 00000000..ce7453c2 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_16.bin @@ -0,0 +1,4 @@ +GET / HTTP/1.1 +Ho +st: example.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin new file mode 100644 index 00000000..5016e0df --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_17.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Host: exa mple.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin new file mode 100644 index 00000000..d2409a88 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_18.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Host: example.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin new file mode 100644 index 00000000..40e39921 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_19.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +!#$%&'*+.^_`|~: allowed + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin new file mode 100644 index 00000000..cfc0d81a --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_2.bin @@ -0,0 +1,3 @@ +GET / + HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin new file mode 100644 index 00000000..b1deb571 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_20.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Host: xn--e1afmkfd.xn--80akhbyknj4f + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin new file mode 100644 index 00000000..89565fd8 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_21.bin @@ -0,0 +1,4 @@ +GET / HTTP/1.1 +Host: exa +mple.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin new file mode 100644 index 00000000..3e0f8f6a --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_22.bin @@ -0,0 +1,3 @@ +GET / HTTP/1.1 +Host: exa mple.com + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin new file mode 100644 index 00000000..da0661e5 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_23.bin @@ -0,0 +1,5 @@ +GET / HTTP/1.1 +X-Unknown-Header: value +X-Good-Header: value +!#$%&'*+.^_`|~: skipped + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin new file mode 100644 index 00000000..6b5232e3 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_24.bin @@ -0,0 +1,5 @@ +GET / HTTP/1.1 +X-Good-Header: value +X-Unknown-Header: value +X-Bad-Header: value + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin new file mode 100644 index 00000000..20afdfb4 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_3.bin @@ -0,0 +1 @@ +GET / HTTP/1.0 diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin new file mode 100644 index 00000000..22b52346 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_4.bin @@ -0,0 +1 @@ +GET / HTTP/2.0 diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin new file mode 100644 index 00000000..2da59689 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_5.bin @@ -0,0 +1,2 @@ +GET /. HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin new file mode 100644 index 00000000..9cf4c094 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_6.bin @@ -0,0 +1,2 @@ +GET /# HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin new file mode 100644 index 00000000..d02576e0 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_7.bin @@ -0,0 +1,2 @@ +GET /?# HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin new file mode 100644 index 00000000..fa246dc4 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_8.bin @@ -0,0 +1,2 @@ +GET // HTTP/1.0 + diff --git a/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin new file mode 100644 index 00000000..2668f283 --- /dev/null +++ b/fuzzing/fuzz_http_seed_corpus/nxt_http_test_run_9.bin @@ -0,0 +1,2 @@ +GET /%20 HTTP/1.0 + diff --git a/fuzzing/fuzz_json_seed_corpus/json_0.bin b/fuzzing/fuzz_json_seed_corpus/json_0.bin new file mode 100644 index 00000000..450e2283 --- /dev/null +++ b/fuzzing/fuzz_json_seed_corpus/json_0.bin @@ -0,0 +1 @@ +[{"container": 1000, "host": 0, "size": 1},{"container": 10000, "host": 10000, "size": 1}, {"container": 60000, "host": 60000, "size": 1}] \ No newline at end of file diff --git a/fuzzing/fuzz_json_seed_corpus/json_1.bin b/fuzzing/fuzz_json_seed_corpus/json_1.bin new file mode 100644 index 00000000..0637a088 --- /dev/null +++ b/fuzzing/fuzz_json_seed_corpus/json_1.bin @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/fuzzing/fuzz_json_seed_corpus/json_2.bin b/fuzzing/fuzz_json_seed_corpus/json_2.bin new file mode 100644 index 00000000..5c1201b8 --- /dev/null +++ b/fuzzing/fuzz_json_seed_corpus/json_2.bin @@ -0,0 +1 @@ +[{"container": 0, "host": 0, "size": 1}] \ No newline at end of file diff --git a/fuzzing/fuzz_json_seed_corpus/json_3.bin b/fuzzing/fuzz_json_seed_corpus/json_3.bin new file mode 100644 index 00000000..e040c9b7 --- /dev/null +++ b/fuzzing/fuzz_json_seed_corpus/json_3.bin @@ -0,0 +1 @@ +[{"container": 1000, "host": 0, "size": 1}] \ No newline at end of file diff --git a/fuzzing/fuzz_json_seed_corpus/json_4.bin b/fuzzing/fuzz_json_seed_corpus/json_4.bin new file mode 100644 index 00000000..30a2bc50 --- /dev/null +++ b/fuzzing/fuzz_json_seed_corpus/json_4.bin @@ -0,0 +1 @@ +[{"container": 0, "host": 1000, "size": 1}, {"container": 1000, "host": 2000, "size": 1}] \ No newline at end of file -- cgit From 5b65134c804667625f9423c20dfdd118ce984bd7 Mon Sep 17 00:00:00 2001 From: Arjun Date: Thu, 13 Jun 2024 08:33:32 +0530 Subject: fuzzing: add a basic README Signed-off-by: Arjun Reviewed-by: Andrew Clayton [ Some small edits - Andrew ] Signed-off-by: Andrew Clayton --- fuzzing/README.md | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 fuzzing/README.md (limited to 'fuzzing') diff --git a/fuzzing/README.md b/fuzzing/README.md new file mode 100644 index 00000000..b1509327 --- /dev/null +++ b/fuzzing/README.md @@ -0,0 +1,68 @@ +# Fuzzing unit + +These tests are generally advised to run only on GNU/Linux. + +## Build fuzzers using libFuzzer. + +Running `sh fuzzing/build-fuzz.sh` can build all the fuzzers with standard +`ASan` and `UBSan`. + +### More comprehensive How-to Guide. + +#### Export flags that are to be used by Unit for fuzzing. + +Note that in `CFLAGS` and `CXXFLAGS`, any type of sanitizers can be added. + +- [AddressSanitizer](https://clang.llvm.org/docs/AddressSanitizer.html), + [ThreadSanitizer](https://clang.llvm.org/docs/ThreadSanitizer.html), + [MemorySanitizer](https://clang.llvm.org/docs/MemorySanitizer.html), + [UndefinedBehaviorSanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html), + [LeakSanitizer](https://clang.llvm.org/docs/LeakSanitizer.html). + +```shell +$ export CC=clang +$ export CXX=clang++ +$ export CFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=fuzzer-no-link" +$ export CXXFLAGS="-g -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=fuzzer-no-link" +$ export LIB_FUZZING_ENGINE="-fsanitize=fuzzer" +``` + +#### Build Unit for Fuzzing. + +```shell +$ ./configure --no-regex --no-pcre2 --fuzz=$LIB_FUZZING_ENGINE +$ make fuzz -j$(nproc) +``` + +#### Running fuzzers. + +```shell +$ mkdir -p build/fuzz_basic_seed +$ mkdir -p build/fuzz_http_controller_seed +$ mkdir -p build/fuzz_http_h1p_seed +$ mkdir -p build/fuzz_http_h1p_peer_seed +$ mkdir -p build/fuzz_json_seed + +$ ./build/fuzz_basic build/fuzz_basic_seed src/fuzz/fuzz_basic_seed_corpus +$ ./build/fuzz_http_controller build/fuzz_http_controller_seed src/fuzz/fuzz_http_controller_seed_corpus +$ ./build/fuzz_http_h1p build/fuzz_http_h1p_seed src/fuzz/fuzz_http_h1p_seed_corpus +$ ./build/fuzz_http_h1p_peer build/fuzz_http_h1p_peer_seed src/fuzz/fuzz_http_h1p_peer_seed_corpus +$ ./build/fuzz_json build/fuzz_json_seed src/fuzz/fuzz_json_seed_corpus +``` + +Here is more information about [LibFuzzer](https://llvm.org/docs/LibFuzzer.html). + +## Build fuzzers using other fuzzing engines. + +- [Honggfuzz](https://github.com/google/honggfuzz/blob/master/docs/PersistentFuzzing.md). +- [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus/blob/stable/utils/aflpp_driver/README.md). + + +## Requirements. + +You will likely need at least the following packages installed (package names +may vary). + +``` +clang, llvm & compiler-rt +``` -- cgit From 35a572c2813ed2cae6af2282cb361e901a79934d Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Thu, 13 Jun 2024 14:12:47 +0100 Subject: fuzzing: Add a .gitattributes file The various .bin files are in DOS format with trailing ^Ms (CRs) and should be ignored for whitespace issues. Signed-off-by: Andrew Clayton --- fuzzing/.gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 fuzzing/.gitattributes (limited to 'fuzzing') diff --git a/fuzzing/.gitattributes b/fuzzing/.gitattributes new file mode 100644 index 00000000..70e0757b --- /dev/null +++ b/fuzzing/.gitattributes @@ -0,0 +1 @@ +*.bin whitespace=-blank-at-eol,-blank-at-eof -- cgit From fcbaf8f3162e8b589628a8bbe10690a9759f56bb Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 10 Jul 2024 10:35:36 +0530 Subject: fuzzing: fix harness bugs There are multiple false positive bugs in harness due to improper use of the internal API. Fixes: a93d878e ("fuzzing: add fuzzing targets") Signed-off-by: Arjun [ Removed private links - Andrew ] Signed-off-by: Andrew Clayton --- fuzzing/nxt_http_controller_fuzz.c | 8 ++++++++ fuzzing/nxt_http_h1p_fuzz.c | 2 ++ fuzzing/nxt_json_fuzz.c | 19 ++++++++++++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) (limited to 'fuzzing') diff --git a/fuzzing/nxt_http_controller_fuzz.c b/fuzzing/nxt_http_controller_fuzz.c index b7c6c272..eac54d7b 100644 --- a/fuzzing/nxt_http_controller_fuzz.c +++ b/fuzzing/nxt_http_controller_fuzz.c @@ -76,6 +76,14 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + r_controller->conn = nxt_mp_zget(mp, sizeof(nxt_conn_t)); + if (r_controller->conn == NULL) { + goto failed; + } + + nxt_main_log.level = NXT_LOG_ALERT; + r_controller->conn->log = nxt_main_log; + nxt_http_fields_process(rp.fields, &nxt_controller_fields_hash, r_controller); diff --git a/fuzzing/nxt_http_h1p_fuzz.c b/fuzzing/nxt_http_h1p_fuzz.c index 471e87a4..a170463a 100644 --- a/fuzzing/nxt_http_h1p_fuzz.c +++ b/fuzzing/nxt_http_h1p_fuzz.c @@ -75,6 +75,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + r_h1p->mem_pool = mp; + nxt_http_fields_process(rp.fields, &nxt_h1p_fields_hash, r_h1p); failed: diff --git a/fuzzing/nxt_json_fuzz.c b/fuzzing/nxt_json_fuzz.c index 532babb1..cfeb395d 100644 --- a/fuzzing/nxt_json_fuzz.c +++ b/fuzzing/nxt_json_fuzz.c @@ -4,7 +4,7 @@ #include #include - +#include #define KMININPUTLENGTH 2 #define KMAXINPUTLENGTH 1024 @@ -33,6 +33,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { nxt_mp_t *mp; nxt_str_t input; + nxt_thread_t *thr; + nxt_runtime_t *rt; nxt_conf_value_t *conf; nxt_conf_validation_t vldt; @@ -40,11 +42,21 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } + thr = nxt_thread(); + mp = nxt_mp_create(1024, 128, 256, 32); if (mp == NULL) { return 0; } + rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t)); + if (rt == NULL) { + goto failed; + } + + thr->runtime = rt; + rt->mem_pool = mp; + input.start = (u_char *)data; input.length = size; @@ -64,6 +76,11 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) vldt.conf_pool = mp; vldt.ver = NXT_VERNUM; + rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); + if (rt->languages == NULL) { + goto failed; + } + nxt_conf_validate(&vldt); nxt_mp_destroy(vldt.pool); -- cgit From 61c13ade39473b1b4849ab0ae10ab4ceff324ba5 Mon Sep 17 00:00:00 2001 From: Arjun Date: Sat, 13 Jul 2024 09:42:42 +0530 Subject: fuzzing: update directory path in README and build-fuzz.sh Fixes: 965fc94e ("fuzzing: add fuzzing infrastructure in build system") Fixes: 5b65134c ("fuzzing: add a basic README") Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/README.md | 10 +++++----- fuzzing/build-fuzz.sh | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'fuzzing') diff --git a/fuzzing/README.md b/fuzzing/README.md index b1509327..9c70c801 100644 --- a/fuzzing/README.md +++ b/fuzzing/README.md @@ -43,11 +43,11 @@ $ mkdir -p build/fuzz_http_h1p_seed $ mkdir -p build/fuzz_http_h1p_peer_seed $ mkdir -p build/fuzz_json_seed -$ ./build/fuzz_basic build/fuzz_basic_seed src/fuzz/fuzz_basic_seed_corpus -$ ./build/fuzz_http_controller build/fuzz_http_controller_seed src/fuzz/fuzz_http_controller_seed_corpus -$ ./build/fuzz_http_h1p build/fuzz_http_h1p_seed src/fuzz/fuzz_http_h1p_seed_corpus -$ ./build/fuzz_http_h1p_peer build/fuzz_http_h1p_peer_seed src/fuzz/fuzz_http_h1p_peer_seed_corpus -$ ./build/fuzz_json build/fuzz_json_seed src/fuzz/fuzz_json_seed_corpus +$ ./build/fuzz_basic build/fuzz_basic_seed fuzzing/fuzz_basic_seed_corpus +$ ./build/fuzz_http_controller build/fuzz_http_controller_seed fuzzing/fuzz_http_seed_corpus +$ ./build/fuzz_http_h1p build/fuzz_http_h1p_seed fuzzing/fuzz_http_seed_corpus +$ ./build/fuzz_http_h1p_peer build/fuzz_http_h1p_peer_seed fuzzing/fuzz_http_seed_corpus +$ ./build/fuzz_json build/fuzz_json_seed fuzzing/fuzz_json_seed_corpus ``` Here is more information about [LibFuzzer](https://llvm.org/docs/LibFuzzer.html). diff --git a/fuzzing/build-fuzz.sh b/fuzzing/build-fuzz.sh index 04f080d9..62f7a676 100644 --- a/fuzzing/build-fuzz.sh +++ b/fuzzing/build-fuzz.sh @@ -16,5 +16,5 @@ mkdir -p build/fuzz_http_h1p_peer_seed mkdir -p build/fuzz_json_seed echo "" -echo "Run: ./build/\${fuzzer} build/\${fuzzer}_seed src/fuzz/\${fuzzer}_seed_corpus" +echo "Run: ./build/\${fuzzer} build/\${fuzzer}_seed fuzzing/\${fuzzer}_seed_corpus" echo "" -- cgit From e56c4edefa3726ffe86f66fde3cba9e9365bfd61 Mon Sep 17 00:00:00 2001 From: Arjun Date: Fri, 2 Aug 2024 18:21:12 +0530 Subject: fuzzing: code cleanup Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/nxt_http_controller_fuzz.c | 31 +++++++++++++++++-------------- fuzzing/nxt_http_h1p_fuzz.c | 23 +++++++++++++---------- fuzzing/nxt_http_h1p_peer_fuzz.c | 19 +++++++++++-------- fuzzing/nxt_json_fuzz.c | 19 +++++++++---------- 4 files changed, 50 insertions(+), 42 deletions(-) (limited to 'fuzzing') diff --git a/fuzzing/nxt_http_controller_fuzz.c b/fuzzing/nxt_http_controller_fuzz.c index eac54d7b..25527ae1 100644 --- a/fuzzing/nxt_http_controller_fuzz.c +++ b/fuzzing/nxt_http_controller_fuzz.c @@ -43,8 +43,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { nxt_mp_t *mp; + nxt_int_t rc; nxt_buf_mem_t buf; - nxt_controller_request_t *r_controller; + nxt_controller_request_t *req; nxt_http_request_parse_t rp; if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { @@ -56,8 +57,13 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } - nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - if (nxt_http_parse_request_init(&rp, mp) != NXT_OK) { + req = nxt_mp_zget(mp, sizeof(nxt_controller_request_t)); + if (req == NULL) { + goto failed; + } + + req->conn = nxt_mp_zget(mp, sizeof(nxt_conn_t)); + if (req->conn == NULL) { goto failed; } @@ -66,26 +72,23 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) buf.pos = buf.start; buf.free = buf.end; - if (nxt_http_parse_request(&rp, &buf) != NXT_DONE) { - goto failed; - } + nxt_main_log.level = NXT_LOG_ALERT; + req->conn->log = nxt_main_log; - r_controller = nxt_mp_zget(mp, sizeof(nxt_controller_request_t)); + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - if (r_controller == NULL) { + rc = nxt_http_parse_request_init(&rp, mp); + if (rc != NXT_OK) { goto failed; } - r_controller->conn = nxt_mp_zget(mp, sizeof(nxt_conn_t)); - if (r_controller->conn == NULL) { + rc = nxt_http_parse_request(&rp, &buf); + if (rc != NXT_DONE) { goto failed; } - nxt_main_log.level = NXT_LOG_ALERT; - r_controller->conn->log = nxt_main_log; - nxt_http_fields_process(rp.fields, &nxt_controller_fields_hash, - r_controller); + req); failed: diff --git a/fuzzing/nxt_http_h1p_fuzz.c b/fuzzing/nxt_http_h1p_fuzz.c index a170463a..6b54431c 100644 --- a/fuzzing/nxt_http_h1p_fuzz.c +++ b/fuzzing/nxt_http_h1p_fuzz.c @@ -42,8 +42,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { nxt_mp_t *mp; + nxt_int_t rc; nxt_buf_mem_t buf; - nxt_http_request_t *r_h1p; + nxt_http_request_t *req; nxt_http_request_parse_t rp; if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { @@ -55,8 +56,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } - nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - if (nxt_http_parse_request_init(&rp, mp) != NXT_OK) { + req = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); + if (req == NULL) { goto failed; } @@ -65,19 +66,21 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) buf.pos = buf.start; buf.free = buf.end; - if (nxt_http_parse_request(&rp, &buf) != NXT_DONE) { - goto failed; - } + req->mem_pool = mp; - r_h1p = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - if (r_h1p == NULL) { + rc = nxt_http_parse_request_init(&rp, mp); + if (rc != NXT_OK) { goto failed; } - r_h1p->mem_pool = mp; + rc = nxt_http_parse_request(&rp, &buf); + if (rc != NXT_DONE) { + goto failed; + } - nxt_http_fields_process(rp.fields, &nxt_h1p_fields_hash, r_h1p); + nxt_http_fields_process(rp.fields, &nxt_h1p_fields_hash, req); failed: diff --git a/fuzzing/nxt_http_h1p_peer_fuzz.c b/fuzzing/nxt_http_h1p_peer_fuzz.c index 7b722248..54876658 100644 --- a/fuzzing/nxt_http_h1p_peer_fuzz.c +++ b/fuzzing/nxt_http_h1p_peer_fuzz.c @@ -43,8 +43,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { nxt_mp_t *mp; + nxt_int_t rc; nxt_buf_mem_t buf; - nxt_http_request_t *r_h1p_peer; + nxt_http_request_t *req; nxt_http_request_parse_t rp; if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { @@ -56,8 +57,8 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) return 0; } - nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); - if (nxt_http_parse_request_init(&rp, mp) != NXT_OK) { + req = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); + if (req == NULL) { goto failed; } @@ -66,17 +67,19 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) buf.pos = buf.start; buf.free = buf.end; - if (nxt_http_parse_request(&rp, &buf) != NXT_DONE) { + nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); + + rc = nxt_http_parse_request_init(&rp, mp); + if (rc != NXT_OK) { goto failed; } - r_h1p_peer = nxt_mp_zget(mp, sizeof(nxt_http_request_t)); - - if (r_h1p_peer == NULL) { + rc = nxt_http_parse_request(&rp, &buf); + if (rc != NXT_DONE) { goto failed; } - nxt_http_fields_process(rp.fields, &nxt_h1p_peer_fields_hash, r_h1p_peer); + nxt_http_fields_process(rp.fields, &nxt_h1p_peer_fields_hash, req); failed: diff --git a/fuzzing/nxt_json_fuzz.c b/fuzzing/nxt_json_fuzz.c index cfeb395d..3a9201d8 100644 --- a/fuzzing/nxt_json_fuzz.c +++ b/fuzzing/nxt_json_fuzz.c @@ -54,19 +54,24 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } - thr->runtime = rt; - rt->mem_pool = mp; + rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); + if (rt->languages == NULL) { + goto failed; + } input.start = (u_char *)data; input.length = size; + thr->runtime = rt; + rt->mem_pool = mp; + + nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); + conf = nxt_conf_json_parse_str(mp, &input); if (conf == NULL) { goto failed; } - nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); - vldt.pool = nxt_mp_create(1024, 128, 256, 32); if (vldt.pool == NULL) { goto failed; @@ -76,13 +81,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) vldt.conf_pool = mp; vldt.ver = NXT_VERNUM; - rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); - if (rt->languages == NULL) { - goto failed; - } - nxt_conf_validate(&vldt); - nxt_mp_destroy(vldt.pool); failed: -- cgit From 900d25c39624980a5416b9d7d6218312ddbbac07 Mon Sep 17 00:00:00 2001 From: Arjun Date: Fri, 2 Aug 2024 16:51:15 +0100 Subject: fuzzing: fixed harness bug False positive bug in harness due to improper use of the internal API. Fixes: a93d878 ("fuzzing: add fuzzing targets") Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/nxt_http_h1p_fuzz.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'fuzzing') diff --git a/fuzzing/nxt_http_h1p_fuzz.c b/fuzzing/nxt_http_h1p_fuzz.c index 6b54431c..b8893ad6 100644 --- a/fuzzing/nxt_http_h1p_fuzz.c +++ b/fuzzing/nxt_http_h1p_fuzz.c @@ -61,12 +61,28 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + req->proto.h1 = nxt_mp_zget(mp, sizeof(nxt_h1proto_t)); + if (req->proto.h1 == NULL) { + goto failed; + } + + req->conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_joint_t)); + if (req->conf == NULL) { + goto failed; + } + + req->conf->socket_conf = nxt_mp_zget(mp, sizeof(nxt_socket_conf_t)); + if (req->conf->socket_conf == NULL) { + goto failed; + } + buf.start = (u_char *)data; buf.end = (u_char *)data + size; buf.pos = buf.start; buf.free = buf.end; req->mem_pool = mp; + req->conf->socket_conf->max_body_size = 8 * 1024 * 1024; nxt_memzero(&rp, sizeof(nxt_http_request_parse_t)); -- cgit From bc49274db06a9795d090bbbd22c074888a9ef583 Mon Sep 17 00:00:00 2001 From: Arjun Date: Fri, 2 Aug 2024 16:58:32 +0100 Subject: fuzzing: updated JSON target Added 'nxt_conf_json_length' check for extra coverage. Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/nxt_json_fuzz.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'fuzzing') diff --git a/fuzzing/nxt_json_fuzz.c b/fuzzing/nxt_json_fuzz.c index 3a9201d8..fa222988 100644 --- a/fuzzing/nxt_json_fuzz.c +++ b/fuzzing/nxt_json_fuzz.c @@ -31,12 +31,13 @@ LLVMFuzzerInitialize(int *argc, char ***argv) int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { - nxt_mp_t *mp; - nxt_str_t input; - nxt_thread_t *thr; - nxt_runtime_t *rt; - nxt_conf_value_t *conf; - nxt_conf_validation_t vldt; + nxt_mp_t *mp; + nxt_str_t input; + nxt_thread_t *thr; + nxt_runtime_t *rt; + nxt_conf_value_t *conf; + nxt_conf_validation_t vldt; + nxt_conf_json_pretty_t pretty; if (size < KMININPUTLENGTH || size > KMAXINPUTLENGTH) { return 0; @@ -65,6 +66,7 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) thr->runtime = rt; rt->mem_pool = mp; + nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); nxt_memzero(&vldt, sizeof(nxt_conf_validation_t)); conf = nxt_conf_json_parse_str(mp, &input); @@ -72,6 +74,9 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + nxt_conf_json_length(conf, NULL); + nxt_conf_json_length(conf, &pretty); + vldt.pool = nxt_mp_create(1024, 128, 256, 32); if (vldt.pool == NULL) { goto failed; -- cgit From 3667c3e2d257566c8e3dfb68fac7f09190db8db4 Mon Sep 17 00:00:00 2001 From: Arjun Date: Fri, 26 Jul 2024 17:57:19 +0530 Subject: fuzzing: added new basic targets Added fuzzing targets: 1. djb hash 2. murmur hash2 3. parse 4. sha1 5. uri decode, uri encode 6. utf8 casecmp 7. websocket base64 encode 8. websocket frame Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/nxt_basic_fuzz.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 146 insertions(+), 1 deletion(-) (limited to 'fuzzing') diff --git a/fuzzing/nxt_basic_fuzz.c b/fuzzing/nxt_basic_fuzz.c index df3a1b6a..5f71a909 100644 --- a/fuzzing/nxt_basic_fuzz.c +++ b/fuzzing/nxt_basic_fuzz.c @@ -3,9 +3,15 @@ */ #include +#include +#include +#include +/* DO NOT TRY THIS AT HOME! */ +#include -#define KMININPUTLENGTH 2 + +#define KMININPUTLENGTH 4 #define KMAXINPUTLENGTH 128 @@ -13,9 +19,17 @@ extern int LLVMFuzzerInitialize(int *argc, char ***argv); extern int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size); void nxt_base64_fuzz(const u_char *data, size_t size); +void nxt_djb_hash_fuzz(const u_char *data, size_t size); +void nxt_murmur_hash2_fuzz(const u_char *data, size_t size); +void nxt_parse_fuzz(const u_char *data, size_t size); +void nxt_sha1_fuzz(const u_char *data, size_t size); +void nxt_sha1_update_fuzz(const u_char *data, size_t size); void nxt_term_fuzz(const u_char *data, size_t size); void nxt_time_fuzz(const u_char *data, size_t size); +void nxt_uri_fuzz(const u_char *data, size_t size); void nxt_utf8_fuzz(const u_char *data, size_t size); +void nxt_websocket_base64_fuzz(const u_char *data, size_t size); +void nxt_websocket_frame_fuzz(const u_char *data, size_t size); extern char **environ; @@ -40,9 +54,17 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) } nxt_base64_fuzz(data, size); + nxt_djb_hash_fuzz(data, size); + nxt_murmur_hash2_fuzz(data, size); + nxt_parse_fuzz(data, size); + nxt_sha1_fuzz(data, size); + nxt_sha1_update_fuzz(data, size); nxt_term_fuzz(data, size); nxt_time_fuzz(data, size); + nxt_uri_fuzz(data, size); nxt_utf8_fuzz(data, size); + nxt_websocket_base64_fuzz(data, size); + nxt_websocket_frame_fuzz(data, size); return 0; } @@ -66,6 +88,64 @@ nxt_base64_fuzz(const u_char *data, size_t size) } +void +nxt_djb_hash_fuzz(const u_char *data, size_t size) +{ + nxt_djb_hash(data, size); + nxt_djb_hash_lowcase(data, size); +} + + +void +nxt_murmur_hash2_fuzz(const u_char *data, size_t size) +{ + nxt_murmur_hash2(data, size); + nxt_murmur_hash2_uint32(data); +} + + +void +nxt_parse_fuzz(const u_char *data, size_t size) +{ + nxt_str_t input; + + input.start = (u_char *)data; + input.length = size; + + nxt_int_parse(data, size); + nxt_size_t_parse(data, size); + nxt_size_parse(data, size); + nxt_off_t_parse(data, size); + nxt_str_int_parse(&input); + nxt_number_parse(&data, data + size); +} + + +void +nxt_sha1_fuzz(const u_char *data, size_t size) +{ + u_char bin_accept[20]; + nxt_sha1_t ctx; + + nxt_sha1_init(&ctx); + nxt_sha1_update(&ctx, data, size); + nxt_sha1_final(bin_accept, &ctx); +} + + +void +nxt_sha1_update_fuzz(const u_char *data, size_t size) +{ + u_char bin_accept[20]; + nxt_sha1_t ctx; + + nxt_sha1_init(&ctx); + nxt_sha1_update(&ctx, data, size); + nxt_sha1_update(&ctx, data, size); + nxt_sha1_final(bin_accept, &ctx); +} + + void nxt_term_fuzz(const u_char *data, size_t size) { @@ -81,6 +161,27 @@ nxt_time_fuzz(const u_char *data, size_t size) } +void +nxt_uri_fuzz(const u_char *data, size_t size) +{ + u_char *dst; + + dst = nxt_zalloc(size * 3); + if (dst == NULL) { + return; + } + + nxt_decode_uri(dst, (u_char *)data, size); + nxt_decode_uri_plus(dst, (u_char *)data, size); + + nxt_memzero(dst, size * 3); + nxt_encode_uri(NULL, (u_char *)data, size); + nxt_encode_uri(dst, (u_char *)data, size); + + nxt_free(dst); +} + + void nxt_utf8_fuzz(const u_char *data, size_t size) { @@ -88,4 +189,48 @@ nxt_utf8_fuzz(const u_char *data, size_t size) in = data; nxt_utf8_decode(&in, data + size); + + nxt_utf8_casecmp((const u_char *)"ABC АБВ ΑΒΓ", + data, + nxt_length("ABC АБВ ΑΒΓ"), + size); +} + + +void +nxt_websocket_base64_fuzz(const u_char *data, size_t size) +{ + u_char *out; + + out = nxt_zalloc(size * 2); + if (out == NULL) { + return; + } + + nxt_websocket_base64_encode(out, data, size); + + nxt_free(out); +} + + +void +nxt_websocket_frame_fuzz(const u_char *data, size_t size) +{ + u_char *input; + + /* + * Resolve overwrites-const-input by using a copy of the data. + */ + input = nxt_malloc(size); + if (input == NULL) { + return; + } + + nxt_memcpy(input, data, size); + + nxt_websocket_frame_init(input, 0); + nxt_websocket_frame_header_size(input); + nxt_websocket_frame_payload_len(input); + + nxt_free(input); } -- cgit From 719207693ef42953e50b1422c59fafc497320d41 Mon Sep 17 00:00:00 2001 From: Arjun Date: Wed, 7 Aug 2024 15:08:46 +0530 Subject: fuzzing: fixed harness bug False positive bug in harness due to improper use of the internal API. Fixes: a93d878 ("fuzzing: add fuzzing targets") Signed-off-by: Arjun Signed-off-by: Andrew Clayton --- fuzzing/nxt_http_h1p_peer_fuzz.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'fuzzing') diff --git a/fuzzing/nxt_http_h1p_peer_fuzz.c b/fuzzing/nxt_http_h1p_peer_fuzz.c index 54876658..43786d0c 100644 --- a/fuzzing/nxt_http_h1p_peer_fuzz.c +++ b/fuzzing/nxt_http_h1p_peer_fuzz.c @@ -62,6 +62,16 @@ LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) goto failed; } + req->peer = nxt_mp_zalloc(mp, sizeof(nxt_http_peer_t)); + if (req->peer == NULL) { + goto failed; + } + + req->peer->proto.h1 = nxt_mp_zalloc(mp, sizeof(nxt_h1proto_t)); + if (req->peer->proto.h1 == NULL) { + goto failed; + } + buf.start = (u_char *)data; buf.end = (u_char *)data + size; buf.pos = buf.start; -- cgit