diff --git a/projects/hostap/Dockerfile b/projects/hostap/Dockerfile new file mode 100644 index 000000000..20ae162bd --- /dev/null +++ b/projects/hostap/Dockerfile @@ -0,0 +1,23 @@ +# Copyright 2019 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 +MAINTAINER elver@google.com +RUN apt-get update && apt-get install -y make autoconf automake libtool g++ +RUN git clone --depth 1 git://w1.fi/srv/git/hostap.git hostap +WORKDIR hostap +COPY build.sh $SRC/ +COPY libfuzzer_entry.c $SRC/hostap/tests/ diff --git a/projects/hostap/build.sh b/projects/hostap/build.sh new file mode 100755 index 000000000..b7c72dd18 --- /dev/null +++ b/projects/hostap/build.sh @@ -0,0 +1,162 @@ +#!/bin/bash -eu +# Copyright 2019 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. +# +################################################################################ + +cd 'tests' + +# Make seed corpora +( + # Need clean environment for building test-tls used to create seed corpus. + unset CC + unset CXX + unset CFLAGS + unset CXXFLAGS + unset LDFLAGS + + make clean + make test-tls + + for x in client server; do + ./test-tls $x write "${WORK}/test-tls-${x}.msg" + (cd "$WORK" && zip "${OUT}/test-tls-${x}-read_seed_corpus.zip" test-tls-${x}.msg) + done + + ( + cd p2p-fuzzer + zip "${OUT}/p2p-fuzzer-proberesp_seed_corpus.zip" proberesp*.dat + zip "${OUT}/p2p-fuzzer-action_seed_corpus.zip" go*.dat inv*.dat p2ps*.dat + ) + + (cd eapol-fuzzer && zip "${OUT}/eapol-fuzzer_seed_corpus.zip" *.dat) + (cd ap-mgmt-fuzzer && zip "${OUT}/ap-mgmt-fuzzer_seed_corpus.zip" multi.dat) + (cd wnm-fuzzer && zip "${OUT}/wnm-fuzzer_seed_corpus.zip" *.dat) + + echo '{"a":[[]],"b":1,"c":"q","d":{"e":[{}]}}' > "${WORK}/test.json" + (cd "$WORK" && zip "${OUT}/test-json_seed_corpus.zip" *.json) + + # TODO: test-x509 +) + + +make clean +export LDO=$CXX +export LDFLAGS="$CXXFLAGS $LIB_FUZZING_ENGINE" +export CFLAGS="$CFLAGS -DTEST_LIBFUZZER -DCONFIG_NO_STDOUT_DEBUG" + +# libFuzzer native targets (enabled via TEST_LIBFUZZER) ------------------ + +for target in json x509; do + make test-${target} TEST_FUZZ=y + cp -v "test-${target}" "${OUT}/" +done + +# AFL compatible targets -------------------------------------------------- + +patch_afl_fuzzer() { + ( + printf '#include +char* get_fuzzer_input(const char*, size_t*); +void free_fuzzer_input(void*); +#define os_readfile get_fuzzer_input +#define os_free free_fuzzer_input +' + cat "$1" + ) > "${1}_" + mv "${1}_" "$1" +} + +print_ignore_leaks_options() { + cat < "${OUT}/wnm-fuzzer.options" +) + +# The below Makefiles do not honor OBJS. +recompile_libfuzzer_entry() { + rm -vf "libfuzzer_entry.o" + $CC $CFLAGS -c -o "libfuzzer_entry.o" "libfuzzer_entry.c" +} + +# test-tls variants +( + export LDFLAGS="$LDFLAGS libfuzzer_entry.o" + make clean + + # test-tls uses fopen to open the input file. + sed -i '1i\ +#define fopen fopen_fuzzer_input +' "test-tls.c" + + CFLAGS="$CFLAGS -DEXTRA_ARGS=\"server\",\"read\"," \ + recompile_libfuzzer_entry + make test-tls TEST_FUZZ=y + cp -v "test-tls" "${OUT}/test-tls-server-read" + + CFLAGS="$CFLAGS -DEXTRA_ARGS=\"client\",\"read\"," \ + recompile_libfuzzer_entry + make test-tls TEST_FUZZ=y + cp -v "test-tls" "${OUT}/test-tls-client-read" +) + +( + export LIBS="../libfuzzer_entry.o" + + # eapol-fuzzer + patch_afl_fuzzer "eapol-fuzzer/eapol-fuzzer.c" + make -C "eapol-fuzzer" clean + recompile_libfuzzer_entry + make -C "eapol-fuzzer" + cp -v "eapol-fuzzer/eapol-fuzzer" "${OUT}/" + + # p2p-fuzzer variants + patch_afl_fuzzer "p2p-fuzzer/p2p-fuzzer.c" + make -C "p2p-fuzzer" clean + CFLAGS="$CFLAGS -DEXTRA_ARGS=\"action\"," \ + recompile_libfuzzer_entry + make -C "p2p-fuzzer" + cp -v "p2p-fuzzer/p2p-fuzzer" "${OUT}/p2p-fuzzer-action" + CFLAGS="$CFLAGS -DEXTRA_ARGS=\"proberesp\"," \ + recompile_libfuzzer_entry + make -C "p2p-fuzzer" + cp -v "p2p-fuzzer/p2p-fuzzer" "${OUT}/p2p-fuzzer-proberesp" +) + +# Copy required data. +cp -a "hwsim" "${OUT}/" + diff --git a/projects/hostap/libfuzzer_entry.c b/projects/hostap/libfuzzer_entry.c new file mode 100644 index 000000000..47a6bf8ae --- /dev/null +++ b/projects/hostap/libfuzzer_entry.c @@ -0,0 +1,56 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef EXTRA_ARGS +#define EXTRA_ARGS +#endif + +#define DUMMY_FILE_NAME "/invalid/path/do/not/use" + +static size_t input_size = 0; +static char* input_data = NULL; +static int use_count = 0; + +int fuzzer_main(int argc, char *argv[]); + +char* get_fuzzer_input(const char* fname, size_t *size) { + assert(!strcmp(fname, DUMMY_FILE_NAME)); + *size = input_size; + ++use_count; + return input_data; +} + +void free_fuzzer_input(char* ptr) { + assert(ptr == input_data); +} + +FILE* fopen_fuzzer_input(const char* fname, const char* mode) { + assert(!strcmp(fname, DUMMY_FILE_NAME)); + ++use_count; + return fmemopen(input_data, input_size, mode); +} + +// Entry point for libFuzzer fuzzer, that wraps main of a fuzzer compatible with +// AFL (where input is passed via a file). +// +// TODO: Ideally, should add native libFuzzer entry to project's fuzzer, as this +// approach has noticable performance implications. +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + char* argv[] = {"fuzzer", EXTRA_ARGS DUMMY_FILE_NAME}; + input_size = size; + input_data = (char*) data; + + fuzzer_main(sizeof(argv) / sizeof(char*), argv); + + if (use_count == 0) { + printf("ERROR: input not used!\n"); + } + return 0; +} diff --git a/projects/hostap/project.yaml b/projects/hostap/project.yaml new file mode 100644 index 000000000..c5ea2aa3a --- /dev/null +++ b/projects/hostap/project.yaml @@ -0,0 +1,8 @@ +homepage: "https://w1.fi/cvs.html" +primary_contact: "j@w1.fi" +auto_ccs: + - "elver@google.com" +sanitizers: + - address + - undefined + - memory