diff options
author | Gerald Combs <gerald@zing.org> | 2021-05-07 12:43:16 -0700 |
---|---|---|
committer | Gerald Combs <gerald@zing.org> | 2021-05-07 14:09:10 -0700 |
commit | 2410d8b6eb02793dbf675bea4aad61a6acffac1c (patch) | |
tree | 76cb5144e73cbfcb1a239a44ac09d522eb19daa9 | |
parent | 66cba93e39f0dcae341087938e983568783fa2ae (diff) |
GitLab CI: Add fuzzing to the 3.4 branch.
Backport part of d7bdd77a4c, which adds a -t option to
tools/fuzz-test.sh which lets you specify a maximum fuzz time.
Copy over the current (as of 7c6df3848f) fuzz jobs from the master
branch.
-rw-r--r-- | .gitlab-ci.yml | 88 | ||||
-rwxr-xr-x | tools/fuzz-test.sh | 32 |
2 files changed, 109 insertions, 11 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4fd576a09a..cc01b1c856 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,13 @@ # https://hub.docker.com/r/wireshark/wireshark-opensuse-15.1-dev # https://hub.docker.com/r/wireshark/wireshark-ubuntu-dev +stages: + - build + - test + - fuzz-asan + - fuzz-randpkt + - fuzz-valgrind + variables: # Ensure that checkouts are a) fast and b) have a reachable tag. In a # brighter, more glorious future we might be able to use --shallow-since: @@ -41,6 +48,11 @@ variables: .if-attached-merge-request: - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_PROJECT_URL =~ /.*gitlab.com\/wireshark\/wireshark/' when: always +# Fuzz jobs. Care should be taken when changing this since the scheduler +# often doesn't report errors. +.if-fuzz-schedule: + - if: '$CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "fuzz"' + when: always .build: stage: build @@ -333,3 +345,79 @@ Windows Build: - msbuild "/consoleloggerparameters:PerformanceSummary;NoSummary" /maxcpucount Wireshark.sln - msbuild "/consoleloggerparameters:PerformanceSummary;NoSummary" test-programs.vcxproj - ctest -C RelWithDebInfo --parallel 3 --force-new-ctest-process --verbose + +# Fuzz TShark using ASAN and valgrind. +.fuzz-ubuntu: + extends: .build-ubuntu + rules: !reference [.if-fuzz-schedule] + tags: + - wireshark-ubuntu-fuzz + resource_group: fuzz-master + variables: + CC: "clang-$CLANG_VERSION" + CXX: "clang++-$CLANG_VERSION" + INSTALL_PREFIX: "$CI_PROJECT_DIR/_install" + MIN_PLUGINS: 10 + MAX_PASSES: 15 + before_script: + - mkdir -p ccache + # Signal after_script, which runs in its own shell. + - echo "export FUZZ_PASSED=true" > /tmp/fuzz_result.sh + - mkdir /tmp/fuzz + - mkdir build + - cd build + after_script: + - . /tmp/fuzz_result.sh + - if $FUZZ_PASSED ; then exit 0 ; fi + - echo Fuzzing failed. Generating report. + - FUZZ_CAPTURE=$( ls /tmp/fuzz/fuzz-*.pcap | head -n 1 ) + - FUZZ_ERRORS="/tmp/fuzz/$( basename "$FUZZ_CAPTURE" .pcap ).err" + - printf "\nfuzz-test.sh stderr:\n" >> "$FUZZ_ERRORS" + - cat fuzz-test.err >> "$FUZZ_ERRORS" + - | + if [ -n "$AWS_ACCESS_KEY_ID" ] && [ -n "$AWS_SECRET_ACCESS_KEY" ] && [ -n "$S3_DESTINATION_FUZZ" ] ; then + aws s3 cp "$FUZZ_CAPTURE" "$S3_DESTINATION_FUZZ/" + aws s3 cp "$FUZZ_ERRORS" "$S3_DESTINATION_FUZZ/" + fi + # The cache should be large enough to be useful but it shouldn't take + # too long to restore+save each run. + - ccache --max-size $( du --summarize --block-size=1M "$CI_PROJECT_DIR/build" | awk '{printf ("%dM", $1 * 1.5)}' ) + +ASan Menagerie Fuzz: + extends: .fuzz-ubuntu + stage: fuzz-asan + script: + - MAX_SECONDS=$(( 4 * 60 * 60 )) + - cmake -G Ninja -DBUILD_wireshark=OFF -DCMAKE_BUILD_TYPE=Debug -DENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX .. + - ninja + - ninja install + - cd .. + # /var/menagerie contains captures harvested from wireshark.org's mailing list, wiki, issues, etc. + # We have more captures than we can fuzz in $MAX_SECONDS, so we shuffle them each run. + - ./tools/fuzz-test.sh -a -2 -P $MIN_PLUGINS -b $INSTALL_PREFIX/bin -d /tmp/fuzz -t $MAX_SECONDS $( shuf -e /var/menagerie/*/* ) 2> fuzz-test.err || echo "export FUZZ_PASSED=false" > /tmp/fuzz_result.sh + +ASan randpkt Fuzz: + extends: .fuzz-ubuntu + stage: fuzz-randpkt + script: + # XXX Reuse fuzz-asan? + - cmake -G Ninja -DBUILD_wireshark=OFF -DCMAKE_BUILD_TYPE=Debug -DENABLE_ASAN=ON -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX .. + - ninja + - ninja install + - cd .. + - ./tools/randpkt-test.sh -a -b $INSTALL_PREFIX/bin -d /tmp/fuzz -p $MAX_PASSES 2> fuzz-test.err || echo "export FUZZ_PASSED=false" > /tmp/fuzz_result.sh + needs: [ 'ASan Menagerie Fuzz' ] + +Valgrind Menagerie Fuzz: + extends: .fuzz-ubuntu + stage: fuzz-valgrind + script: + - DEBIAN_FRONTEND=noninteractive apt-get update + - DEBIAN_FRONTEND=noninteractive apt-get --yes install valgrind + - MAX_SECONDS=$(( 3 * 60 * 60 )) + - cmake -G Ninja -DBUILD_wireshark=OFF -DCMAKE_BUILD_TYPE=Debug -DENABLE_ASAN=OFF -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX .. + - ninja + - ninja install + - cd .. + - ./tools/fuzz-test.sh -g -P $MIN_PLUGINS -b $INSTALL_PREFIX/bin -d /tmp/fuzz -t $MAX_SECONDS $( shuf -e /var/menagerie/*/* ) 2> fuzz-test.err || echo "export FUZZ_PASSED=false" > /tmp/fuzz_result.sh + needs: [ 'ASan randpkt Fuzz' ] diff --git a/tools/fuzz-test.sh b/tools/fuzz-test.sh index 0eb4be5a80..cc70f2c39e 100755 --- a/tools/fuzz-test.sh +++ b/tools/fuzz-test.sh @@ -22,8 +22,8 @@ TEST_TYPE="fuzz" # Sanity check to make sure we can find our plugins. Zero or less disables. MIN_PLUGINS=0 -# Did we catch a signal? -DONE=0 +# Did we catch a signal or time out? +DONE=false # Currently running children RUNNER_PIDS= @@ -48,8 +48,12 @@ CHANGE_OFFSET=0 # Only has effect when running under valgrind. MAX_LEAK=$(( 1024 * 100 )) +# Our maximum run time. +START_SECONDS=$SECONDS +MAX_SECONDS=$(( START_SECONDS + 86400 )) + # To do: add options for file names and limits -while getopts "2b:C:d:e:agp:P:o:" OPTCHAR ; do +while getopts "2b:C:d:e:agp:P:o:t:" OPTCHAR ; do case $OPTCHAR in a) ASAN=1 ;; 2) TWO_PASS="-2 " ;; @@ -61,6 +65,7 @@ while getopts "2b:C:d:e:agp:P:o:" OPTCHAR ; do p) MAX_PASSES=$OPTARG ;; P) MIN_PLUGINS=$OPTARG ;; o) CHANGE_OFFSET=$OPTARG ;; + t) MAX_SECONDS=$(( START_SECONDS + OPTARG )) ;; *) printf "Unknown option %s" "$OPTCHAR" esac done @@ -145,7 +150,7 @@ echo "" # Clean up on <ctrl>C, etc trap_all() { - DONE=1 + DONE=true echo 'Caught signal' } @@ -161,14 +166,14 @@ trap trap_abrt ABRT # Iterate over our capture files. PASS=0 -while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && [ $DONE -ne 1 ] ; do +while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && ! $DONE ; do PASS=$(( PASS+1 )) echo "Starting pass $PASS:" RUN=0 for CF in "$@" ; do - if [ $DONE -eq 1 ]; then - break # We caught a signal + if $DONE; then + break # We caught a signal or timed out fi RUN=$(( RUN + 1 )) if [ $(( RUN % 50 )) -eq 0 ] ; then @@ -185,7 +190,7 @@ while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && [ $DONE -ne echo "Not a valid capture file" rm -f "$TMP_DIR/$ERR_FILE" continue - elif [ $RETVAL -ne 0 ] && [ $DONE -ne 1 ] ; then + elif [ $RETVAL -ne 0 ] && ! $DONE ; then # Some other error ws_exit_error fi @@ -208,7 +213,7 @@ while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && [ $DONE -ne RUNNER_PIDS= RUNNER_ERR_FILES= for ARGS in "${RUNNER_ARGS[@]}" ; do - if [ $DONE -eq 1 ]; then + if $DONE; then break # We caught a signal fi echo -n "($ARGS) " @@ -242,6 +247,11 @@ while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && [ $DONE -ne RUNNER_PID=$! RUNNER_PIDS="$RUNNER_PIDS $RUNNER_PID" RUNNER_ERR_FILES="$RUNNER_ERR_FILES $TMP_DIR/$ERR_FILE.$RUNNER_PID" + + if [ $SECONDS -ge $MAX_SECONDS ] ; then + printf "\nStopping after %d seconds.\n" $(( SECONDS - START_SECONDS )) + DONE=true + fi done for RUNNER_PID in $RUNNER_PIDS ; do @@ -254,7 +264,7 @@ while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && [ $DONE -ne #grep -i "dissector bug" $TMP_DIR/$ERR_FILE \ # > /dev/null 2>&1 && DISSECTOR_BUG=1 - if [ $VALGRIND -eq 1 ] && [ $DONE -ne 1 ]; then + if [ $VALGRIND -eq 1 ] && ! $DONE; then VG_ERR_CNT=$( grep "ERROR SUMMARY:" "$TMP_DIR/$ERR_FILE" | cut -f4 -d' ' ) VG_DEF_LEAKED=$( grep "definitely lost:" "$TMP_DIR/$ERR_FILE" | cut -f7 -d' ' | tr -d , ) VG_IND_LEAKED=$( grep "indirectly lost:" "$TMP_DIR/$ERR_FILE" | cut -f7 -d' ' | tr -d , ) @@ -273,7 +283,7 @@ while { [ $PASS -lt "$MAX_PASSES" ] || [ "$MAX_PASSES" -lt 1 ]; } && [ $DONE -ne fi fi - if [ $DONE -ne 1 ] && { [ $RUNNER_RETVAL -ne 0 ] || [ $DISSECTOR_BUG -ne 0 ] || [ $VG_ERR_CNT -ne 0 ]; } ; then + if $DONE && { [ $RUNNER_RETVAL -ne 0 ] || [ $DISSECTOR_BUG -ne 0 ] || [ $VG_ERR_CNT -ne 0 ]; } ; then # shellcheck disable=SC2086 rm -f $RUNNER_ERR_FILES ws_exit_error |