aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerald Combs <gerald@zing.org>2021-05-07 12:43:16 -0700
committerGerald Combs <gerald@zing.org>2021-05-07 14:09:10 -0700
commit2410d8b6eb02793dbf675bea4aad61a6acffac1c (patch)
tree76cb5144e73cbfcb1a239a44ac09d522eb19daa9
parent66cba93e39f0dcae341087938e983568783fa2ae (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.yml88
-rwxr-xr-xtools/fuzz-test.sh32
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