We recently added fuzz testing to Ethereal's automated build system. I tried out the script we're using on tcpdump and it turned up a bug in util.c. Attached are:
- A patch for util.c:print_unknown_data() that makes sure a negative length isn't passed to hex_print(). - A capture file that triggers the bug in the current daily build. - The fuzz testing script that created the capture. It is based on "fuzz-test.sh" from the Ethereal distribution and requires a recent version of editcap.
--- ../tcpdump-2005.06.09.orig/util.c 2005-05-06 03:26:45.000000000 -0500 +++ util.c 2005-06-12 14:04:13.520867529 -0500 @@ -244,6 +244,8 @@ { if (snapend - cp < len) len = snapend - cp; + if (len < 0) + return(0); /* XXX - Should we print an error here? */ hex_print(ident,cp,len); return(1); /* everything is ok */ }
#!/bin/bash # # $Id$ # Fuzz testing script for tcpdump # # By Gerald Combs <[EMAIL PROTECTED]> and Ulf Lamping <[EMAIL PROTECTED]> # # This script uses Ethereal's Editcap utility to add random errors # ("fuzz") to a set of capture files specified on the command line. # It runs tcpdump on each fuzzed file and checks for errors. The # files are processed repeatedly until an error is found. # Tweak the following to your liking. Editcap must support "-E". # This feature is present in Ethereal 0.10.11 and later. TCPDUMP=./tcpdump EDITCAP=editcap CAPINFOS=capinfos # This needs to point to a 'date' that supports %s. DATE=/bin/date # Where our temp files are saved (editcap.out and stderr.out) # Cygwin user may wish to use "TMP_DIR=./". TMP_DIR=/tmp # These may be set to your liking # Stop the child process, if it's running longer than x seconds MAX_CPU_TIME=900 # Stop the child process, if it's using more than y * 1024 bytes MAX_VMEM=500000 # Insert z times an error into the capture file (0.02 seems to be a # good value to find errors) ERR_PROB=0.02 # set some limits to the child processes, e.g. stop it if it's running # longer then MAX_CPU_TIME seconds # (ulimit is not supported well on cygwin and probably other platforms, # e.g. cygwin shows some warnings) ulimit -S -t $MAX_CPU_TIME -v $MAX_VMEM ### usually you won't have to change anything below this line ### # Tcpdump arguments (you won't have to change these) # vvv Maximum verbosity # n Disable network object name resolution # r Read packet data from the following infile TCPDUMP_ARGS="-vvv -nr" # Make sure we have a valid test set FOUND=0 for CF in "$@" ; do "$CAPINFOS" "$CF" > /dev/null 2>&1 && FOUND=1 if [ $FOUND -eq 1 ] ; then break ; fi done if [ $FOUND -eq 0 ] ; then cat <<FIN Error: No valid capture files found. Usage: `basename $0` capture file 1 [capture file 2]... FIN exit 1 fi echo "Running $TCPDUMP with args: $TCPDUMP_ARGS" echo "" # Iterate over our capture files. PASS=0 while [ 1 ] ; do PASS=`expr $PASS + 1` echo "Pass $PASS:" for CF in "$@" ; do echo -n " $CF: " "$CAPINFOS" "$CF" > /dev/null 2>&1 if [ $? -ne 0 ] ; then echo "Not a valid capture file" continue fi DISSECTOR_BUG=0 "$EDITCAP" -E $ERR_PROB "$CF" $TMP_DIR/editcap.out > /dev/null 2>&1 if [ $? -ne 0 ] ; then "$EDITCAP" -E $ERR_PROB -T ether "$CF" $TMP_DIR/editcap.out > /dev/null 2>&1 if [ $? -ne 0 ] ; then echo "Invalid format for editcap" continue fi fi "$TCPDUMP" $TCPDUMP_ARGS $TMP_DIR/editcap.out \ > /dev/null 2> $TMP_DIR/stderr.out RETVAL=$? grep -i "dissector bug" $TMP_DIR/stderr.out \ > /dev/null 2>&1 && DISSECTOR_BUG=1 # XXX - Tcpdump had trouble reading some files that editcap generated. # We need to handle this better than checking for a return value > 1. if [ $RETVAL -gt 1 -o $DISSECTOR_BUG -ne 0 ] ; then SECS=`$DATE +%s` echo " ERROR" echo -e "Processing failed. Capture info follows:\n" mv $TMP_DIR/editcap.out $TMP_DIR/editcap.$SECS.pcap echo " Output file: $TMP_DIR/editcap.$SECS.pcap" if [ $DISSECTOR_BUG -ne 0 ] ; then echo -e "stderr follows:\n" cat $TMP_DIR/stderr.out fi exit 1 fi echo " OK" done done
- This is the tcpdump-workers list. Visit https://lists.sandelman.ca/ to unsubscribe.