1#!/bin/bash
2
3# Due to the complexity to android buile environment this script is created for
4# development purpose to build, run and debug the fuzzers. It's not needed or
5# required for official build and fuzzing.
6
7function init() {
8  if [ -z "$ANDROID_BUILD_TOP" ];
9  then
10    echo "Did you forget lunch?"
11    exit 1
12  fi
13  source $ANDROID_BUILD_TOP/build/envsetup.sh
14
15  PROJ=$(basename $PWD)
16  FUZZER_NAME=nfc_${PROJ}_fuzzer
17  FUZZ_DIR=data/fuzz/$(get_build_var TARGET_ARCH)/$FUZZER_NAME
18  FUZZ_OPTIONS="$FUZZ_OPTIONS -close_fd_mask=3 -max_len=512 -artifact_prefix=/$FUZZ_DIR/crashes/"
19}
20
21function run_once() {
22  if [ "$1" == "-c" ];
23  then
24    adb shell rm -rf /$FUZZ_DIR/corpus /$FUZZ_DIR/crashes /$FUZZ_DIR/gcov
25    adb shell mkdir -p /$FUZZ_DIR/corpus /$FUZZ_DIR/crashes /$FUZZ_DIR/gcov
26    adb push ./corpus/* /$FUZZ_DIR/corpus/  >/dev/null 2>&1
27    rm -rf ./logs ./coverage
28
29    shift
30  fi
31
32  adb logcat -c
33  if [ -z "$1" ];
34  then
35    PAYLOAD=/$FUZZ_DIR/corpus
36    echo "Fuzzing with corpus from $PAYLOAD..."
37  else
38    PAYLOAD=$1
39    echo "Verifying payload $PAYLOAD..."
40  fi
41
42  adb shell mkdir -p /$FUZZ_DIR/corpus /$FUZZ_DIR/crashes /$FUZZ_DIR/gcov
43  adb shell LD_LIBRARY_PATH=/system/lib64/vndk-29 GCOV_PREFIX=/$FUZZ_DIR/gcov GCOV_PREFIX_STRIP=3 /$FUZZ_DIR/$FUZZER_NAME $FUZZ_OPTIONS $PAYLOAD
44
45  echo "==========================================================================================="
46  adb logcat -d| $ANDROID_BUILD_TOP/external/compiler-rt/lib/asan/scripts/symbolize.py
47}
48
49function run_fuzz() {
50  if [ "$1" == "-c" ];
51  then
52    adb shell rm -rf /$FUZZ_DIR/corpus /$FUZZ_DIR/crashes /$FUZZ_DIR/gcov
53    adb shell mkdir -p /$FUZZ_DIR/corpus /$FUZZ_DIR/crashes /$FUZZ_DIR/gcov
54    adb push ./corpus/* /$FUZZ_DIR/corpus/  >/dev/null 2>&1
55    rm -rf ./logs ./coverage
56  fi
57
58  mkdir -p ./logs/ERROR ./logs/UNKNOWN ./coverage
59  while true
60  do
61    echo "Running ..."
62    TS=`date +"%m-%d-%Y-%H-%M-%S"`
63    run_once >./logs/fuzz.log 2>&1
64
65    echo "Fuzzer crashed, looking for crash input ..."
66    CRASH=$(grep -aoP "Test unit written to \K\S+" ./logs/fuzz.log)
67    if [ -z "$CRASH" ];
68    then
69      echo "Error, crash not found!"
70      mv ./logs/fuzz.log ./logs/ERROR/run_$TS.log
71      continue
72    fi
73
74    echo "Verifying crash ..."
75    run_once $CRASH >./logs/verify.log 2>&1
76    SIG=$(grep -m 1 -aoP "#?? \S+ in \K\S+ system/nfc/src\S+:\S+" ./logs/verify.log)
77    if [ -z "$SIG" ];
78    then
79      SIG='UNKNOWN'
80      cat ./logs/verify.log>>./logs/fuzz.log
81    else
82      cp ./logs/verify.log ./logs/fuzz.log
83    fi
84
85    SIG_DIR=$(echo $SIG | tr " /:" '#@#')
86    if [ ! -d "./logs/$SIG_DIR" ];
87    then
88      echo "New crash category found: $SIG"
89      mkdir -p ./logs/$SIG_DIR
90    else
91      echo "Known crash: $SIG"
92    fi
93
94    mv ./logs/fuzz.log ./logs/$SIG_DIR/run_$TS.log
95    adb pull $CRASH ./logs/$SIG_DIR/crash_$TS.bin >/dev/null 2>&1
96    adb rm $CRASH >/dev/null 2>&1
97  done
98}
99
100function build() {
101  pushd $ANDROID_BUILD_TOP
102  SANITIZE_HOST="address" \
103    SANITIZE_TARGET="hwaddress fuzzer" \
104    NATIVE_COVERAGE="true" \
105    NATIVE_COVERAGE_PATHS="system/nfc/src" \
106    make -j $FUZZER_NAME
107  popd
108  adb shell mkdir -p /$FUZZ_DIR
109  adb push $OUT/symbols/$FUZZ_DIR/$FUZZER_NAME /$FUZZ_DIR/
110}
111
112function run() {
113  if [ "$1" == "--once" ];
114  then
115    shift
116    run_once $@
117  else
118    echo "fuzzing..."
119    run_fuzz $@
120  fi
121}
122
123function debug() {
124  if [ -z "$1" ];
125  then
126    echo "Which payload?"
127    exit
128  fi
129
130  FUZZ_PAYLOAD=$1
131
132  adb forward tcp:5039 tcp:5039
133  adb shell LD_LIBRARY_PATH=/system/lib64/vndk-29 gdbserver64 remote:5039 /$FUZZ_DIR/$FUZZER_NAME $FUZZ_OPTIONS $FUZZ_PAYLOAD 2>&1 >/dev/null&
134  sleep 5
135  $ANDROID_BUILD_TOP/prebuilts/gdb/linux-x86/bin/gdb --directory=$ANDROID_BUILD_TOP -ex "target remote:5039"
136}
137
138function get_cov() {
139  mkdir -p ./coverage && adb pull /$FUZZ_DIR/gcov/0/out/soong ./coverage
140  unzip -o $OUT/coverage/$FUZZ_DIR/$FUZZER_NAME.zip -d ./coverage
141  lcov --directory ./coverage --base-directory $ANDROID_BUILD_TOP --gcov-tool $(pwd)/../llvm-gcov --capture -o ./coverage/cov.info
142  TS=`date +"%m-%d-%Y-%H-%M-%S"`
143  genhtml ./coverage/cov.info -o ./coverage/report_$TS
144  xdg-open ./coverage/report_$TS/index.html
145}
146
147function fuzz() {
148  init
149  action=$1
150  shift
151
152  case "$action" in
153    run)
154      run $@
155      ;;
156    build)
157      build $@
158      ;;
159    debug)
160      debug $@
161      ;;
162    gcov)
163      get_cov $@
164      ;;
165    *)
166      echo "Usage: $0 {run|build|debug|gcov}"
167      exit 1
168  esac
169}
170
171if [ "$0" == "${BASH_SOURCE[0]}" ];
172then
173  fuzz $@
174fi
175
176