From 8ebcb6512969af01c658a4909973bd7454505a8d Mon Sep 17 00:00:00 2001 From: mayhem-bot Date: Thu, 2 Jun 2022 20:27:15 -0400 Subject: [PATCH] Mayhem support --- .github/workflows/fuzz_cfg_parser-mayhem.yml | 55 ++++++++++++++ mayhem/Dockerfile | 27 +++++++ mayhem/Dockerfile.dockerignore | 0 mayhem/build.sh | 41 ++++++++++ mayhem/fuzz_cfg_parser.c | 43 +++++++++++ mayhem/fuzz_cfg_parser.mayhemfile | 4 + mayhem/fuzz_hpack_decode.c | 80 ++++++++++++++++++++ 7 files changed, 250 insertions(+) create mode 100644 .github/workflows/fuzz_cfg_parser-mayhem.yml create mode 100644 mayhem/Dockerfile create mode 100644 mayhem/Dockerfile.dockerignore create mode 100755 mayhem/build.sh create mode 100644 mayhem/fuzz_cfg_parser.c create mode 100644 mayhem/fuzz_cfg_parser.mayhemfile create mode 100644 mayhem/fuzz_hpack_decode.c diff --git a/.github/workflows/fuzz_cfg_parser-mayhem.yml b/.github/workflows/fuzz_cfg_parser-mayhem.yml new file mode 100644 index 0000000000..6d737cd34b --- /dev/null +++ b/.github/workflows/fuzz_cfg_parser-mayhem.yml @@ -0,0 +1,55 @@ +name: Mayhem +on: + push: + pull_request: + workflow_dispatch: + workflow_call: +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} +jobs: + build: + name: ${{ matrix.os }} shared=${{ matrix.shared }} ${{ matrix.build_type }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + shared: [false] + build_type: [Release] + include: + - os: ubuntu-latest + triplet: x64-linux + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + file: mayhem/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + - name: Start analysis + uses: forallsecure/mcode-action@v1 + with: + mayhem-token: ${{ secrets.MAYHEM_TOKEN }} + args: --image ${{ steps.meta.outputs.tags }} --cmd /out/fuzz_cfg_parser --target + fuzz_cfg_parser --file mayhem/fuzz_cfg_parser.mayhemfile + sarif-output: sarif + - name: Upload SARIF file(s) + uses: github/codeql-action/upload-sarif@v2 + with: + sarif_file: sarif diff --git a/mayhem/Dockerfile b/mayhem/Dockerfile new file mode 100644 index 0000000000..bf6867d4de --- /dev/null +++ b/mayhem/Dockerfile @@ -0,0 +1,27 @@ +# Copyright 2020 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ +FROM gcr.io/oss-fuzz-base/base-builder +RUN apt-get update && apt-get install -y make +COPY . haproxy +RUN rm -rf haproxy/mayhem + +WORKDIR $SRC + +COPY mayhem/build.sh $SRC +COPY mayhem/fuzz* $SRC/ + +ENV FUZZING_LANGUAGE=c++ SANITIZER=address +RUN compile \ No newline at end of file diff --git a/mayhem/Dockerfile.dockerignore b/mayhem/Dockerfile.dockerignore new file mode 100644 index 0000000000..e69de29bb2 diff --git a/mayhem/build.sh b/mayhem/build.sh new file mode 100755 index 0000000000..b7afc78d56 --- /dev/null +++ b/mayhem/build.sh @@ -0,0 +1,41 @@ +#!/bin/bash -eu +# Copyright 2020 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +export ORIG_CFLAGS=${CFLAGS} +cd haproxy + +# Fix some things in the Makefile where there are no options available +sed 's/CFLAGS = $(ARCH_FLAGS) $(CPU_CFLAGS) $(DEBUG_CFLAGS) $(SPEC_CFLAGS)/CFLAGS = $(ARCH_FLAGS) $(CPU_CFLAGS) $(DEBUG_CFLAGS) $(SPEC_CFLAGS) ${ORIG_CFLAGS}/g' -i Makefile +sed 's/LDFLAGS = $(ARCH_FLAGS) -g/LDFLAGS = $(ARCH_FLAGS) -g ${CXXFLAGS}/g' -i Makefile +make TARGET=generic CC=${CC} LD=${CXX} + +# Make a copy of the main file since it has many global functions we need to declare +# We dont want the main function but we need the rest of the stuff in haproxy.c +cd /src/haproxy +sed 's/int main(int argc/int main2(int argc/g' -i ./src/haproxy.c +sed 's/dladdr(main,/dladdr(main2,/g' -i ./src/tools.c +sed 's/(void*)main/(void*)main2/g' -i ./src/tools.c + + +SETTINGS="-Iinclude -g -DUSE_POLL -DUSE_TPROXY -DCONFIG_HAPROXY_VERSION=\"\" -DCONFIG_HAPROXY_DATE=\"\"" + +$CC $CFLAGS $SETTINGS -c -o ./src/haproxy.o ./src/haproxy.c +ar cr libhaproxy.a ./src/*.o + +for fuzzer in hpack_decode cfg_parser; do + cp $SRC/fuzz_${fuzzer}.c . + $CC $CFLAGS $SETTINGS -c fuzz_${fuzzer}.c -o fuzz_${fuzzer}.o + $CXX -g $CXXFLAGS $LIB_FUZZING_ENGINE fuzz_${fuzzer}.o libhaproxy.a -o $OUT/fuzz_${fuzzer} +done diff --git a/mayhem/fuzz_cfg_parser.c b/mayhem/fuzz_cfg_parser.c new file mode 100644 index 0000000000..28797312bf --- /dev/null +++ b/mayhem/fuzz_cfg_parser.c @@ -0,0 +1,43 @@ +/* +# Copyright 2020 Google Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +################################################################################ +*/ +#include +#include +#include + +int +LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if (size < 50) + return 0; + + char filename[256]; + sprintf(filename, "/tmp/libfuzzer.%d", getpid()); + + FILE *fp = fopen(filename, "wb"); + if (!fp) + return 0; + fwrite(data, size, 1, fp); + fclose(fp); + + // Fuzz the cfg parser + readcfgfile(filename); + + unlink(filename); + + return 0; +} diff --git a/mayhem/fuzz_cfg_parser.mayhemfile b/mayhem/fuzz_cfg_parser.mayhemfile new file mode 100644 index 0000000000..15a7704042 --- /dev/null +++ b/mayhem/fuzz_cfg_parser.mayhemfile @@ -0,0 +1,4 @@ +project: PROJECT +target: fuzz_cfg_parser +cmds: +- cmd: /out/fuzz_cfg_parser diff --git a/mayhem/fuzz_hpack_decode.c b/mayhem/fuzz_hpack_decode.c new file mode 100644 index 0000000000..80ba8c3e70 --- /dev/null +++ b/mayhem/fuzz_hpack_decode.c @@ -0,0 +1,80 @@ +/* + * # Copyright 2020 Google Inc. + * # + * # Licensed under the Apache License, Version 2.0 (the "License"); + * # you may not use this file except in compliance with the License. + * # You may obtain a copy of the License at + * # + * # http://www.apache.org/licenses/LICENSE-2.0 + * # + * # Unless required by applicable law or agreed to in writing, software + * # distributed under the License is distributed on an "AS IS" BASIS, + * # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * # See the License for the specific language governing permissions and + * # limitations under the License. + * # + * ################################################################################ + * */ +#define HPACK_STANDALONE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAX_RQ_SIZE 65536 +#define MAX_HDR_NUM 1000 + +char hex[MAX_RQ_SIZE*3+3]; // enough for "[ XX]* \0" +uint8_t buf[MAX_RQ_SIZE]; + +char trash_buf[MAX_RQ_SIZE]; +char tmp_buf[MAX_RQ_SIZE]; + +struct buffer tmp = { .area = tmp_buf, .data = 0, .size = sizeof(tmp_buf) }; + +/* Empty function we dont need - we just need a callback */ +void debug_hexdump(FILE *out, const char *pfx, const char *buf, + unsigned int baseaddr, int len) +{ } + +// These must be included here +#include "../src/hpack-huff.c" +#include "../src/hpack-tbl.c" +#include "../src/hpack-dec.c" + + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size){ + char *new_str = (char *)malloc(size+1); + struct hpack_dht *dht; + struct pool_head pool; + int dht_size = 4096; + if (new_str == NULL){ + return 0; + } + memcpy(new_str, data, size); + new_str[size] = '\0'; + struct http_hdr list[MAX_HDR_NUM]; + + pool.size = dht_size; + pool_head_hpack_tbl = &pool; + dht = hpack_dht_alloc(); + + if (dht != NULL) + { + hpack_decode_frame(dht, new_str, size, list,sizeof(list)/sizeof(list[0]), &tmp); + if (dht != NULL) + { + free(dht); + } + } + free(new_str); + return 0; +}