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.
This commit is contained in:
Gerald Combs 2021-05-07 12:43:16 -07:00
parent 66cba93e39
commit 2410d8b6eb
2 changed files with 109 additions and 11 deletions

View File

@ -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' ]

View File

@ -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