1*b13c0e40SEric Biggers#!/bin/bash 2*b13c0e40SEric Biggers# SPDX-License-Identifier: MIT 3*b13c0e40SEric Biggers# Copyright 2020 Google LLC 4*b13c0e40SEric Biggers# 5*b13c0e40SEric Biggers# Use of this source code is governed by an MIT-style 6*b13c0e40SEric Biggers# license that can be found in the LICENSE file or at 7*b13c0e40SEric Biggers# https://opensource.org/licenses/MIT. 8*b13c0e40SEric Biggers# 9*b13c0e40SEric Biggers# 10*b13c0e40SEric Biggers# Test script for fsverity-utils. Runs 'make check' in lots of configurations, 11*b13c0e40SEric Biggers# runs static analysis, and does a few other tests. 12*b13c0e40SEric Biggers# 13*b13c0e40SEric Biggers# Note: for more test coverage, in addition to running this script, also build 14*b13c0e40SEric Biggers# fsverity-utils into a kvm-xfstests test appliance and run 15*b13c0e40SEric Biggers# 'kvm-xfstests -c ext4,f2fs -g verity' 16*b13c0e40SEric Biggers 17*b13c0e40SEric Biggersset -e -u -o pipefail 18*b13c0e40SEric Biggerscd "$(dirname "$0")/.." 19*b13c0e40SEric Biggers 20*b13c0e40SEric Biggerslog() 21*b13c0e40SEric Biggers{ 22*b13c0e40SEric Biggers echo "[$(date)] $*" 1>&2 23*b13c0e40SEric Biggers} 24*b13c0e40SEric Biggers 25*b13c0e40SEric Biggersfail() 26*b13c0e40SEric Biggers{ 27*b13c0e40SEric Biggers echo "FAIL: $*" 1>&2 28*b13c0e40SEric Biggers exit 1 29*b13c0e40SEric Biggers} 30*b13c0e40SEric Biggers 31*b13c0e40SEric BiggersTMPDIR=$(mktemp -d -t libfsverity_test.XXXXXXXXX) 32*b13c0e40SEric Biggerstrap 'rm -r "$TMPDIR"' EXIT 33*b13c0e40SEric Biggers 34*b13c0e40SEric Biggers# Both stdout and stderr go to log file. 35*b13c0e40SEric Biggers# Only stderr goes to terminal. 36*b13c0e40SEric Biggersecho "Starting fsverity-utils tests. See run-tests.log for full output." 37*b13c0e40SEric Biggersrm -f run-tests.log 38*b13c0e40SEric Biggersexec >> run-tests.log 39*b13c0e40SEric Biggersexec 2> >(tee -ia run-tests.log 1>&2) 40*b13c0e40SEric Biggers 41*b13c0e40SEric BiggersMAKE="make -j$(getconf _NPROCESSORS_ONLN)" 42*b13c0e40SEric Biggers 43*b13c0e40SEric BiggersTEST_FUNCS=() 44*b13c0e40SEric Biggers 45*b13c0e40SEric Biggersstatic_linking_test() 46*b13c0e40SEric Biggers{ 47*b13c0e40SEric Biggers log "Build and test with statically linking" 48*b13c0e40SEric Biggers $MAKE CFLAGS="-Werror" 49*b13c0e40SEric Biggers if ldd fsverity | grep libfsverity.so; then 50*b13c0e40SEric Biggers fail "fsverity binary should be statically linked to libfsverity by default" 51*b13c0e40SEric Biggers fi 52*b13c0e40SEric Biggers ./fsverity --version 53*b13c0e40SEric Biggers 54*b13c0e40SEric Biggers log "Check that all global symbols are prefixed with \"libfsverity_\"" 55*b13c0e40SEric Biggers if nm libfsverity.a | grep ' T ' | grep -v " libfsverity_"; then 56*b13c0e40SEric Biggers fail "Some global symbols are not prefixed with \"libfsverity_\"" 57*b13c0e40SEric Biggers fi 58*b13c0e40SEric Biggers} 59*b13c0e40SEric BiggersTEST_FUNCS+=(static_linking_test) 60*b13c0e40SEric Biggers 61*b13c0e40SEric Biggersdynamic_linking_test() 62*b13c0e40SEric Biggers{ 63*b13c0e40SEric Biggers log "Build and test with dynamic linking" 64*b13c0e40SEric Biggers $MAKE CFLAGS="-Werror" USE_SHARED_LIB=1 check 65*b13c0e40SEric Biggers if ! ldd fsverity | grep libfsverity.so; then 66*b13c0e40SEric Biggers fail "fsverity binary should be dynamically linked to libfsverity when USE_SHARED_LIB=1" 67*b13c0e40SEric Biggers fi 68*b13c0e40SEric Biggers 69*b13c0e40SEric Biggers log "Check that all exported symbols are prefixed with \"libfsverity_\"" 70*b13c0e40SEric Biggers if nm libfsverity.so | grep ' T ' | grep -v " libfsverity_"; then 71*b13c0e40SEric Biggers fail "Some exported symbols are not prefixed with \"libfsverity_\"" 72*b13c0e40SEric Biggers fi 73*b13c0e40SEric Biggers} 74*b13c0e40SEric BiggersTEST_FUNCS+=(dynamic_linking_test) 75*b13c0e40SEric Biggers 76*b13c0e40SEric Biggerscplusplus_test() 77*b13c0e40SEric Biggers{ 78*b13c0e40SEric Biggers $MAKE CFLAGS="-Werror" libfsverity.so 79*b13c0e40SEric Biggers log "Test using libfsverity from C++ program" 80*b13c0e40SEric Biggers cat > "$TMPDIR/test.cc" <<EOF 81*b13c0e40SEric Biggers#include <libfsverity.h> 82*b13c0e40SEric Biggers#include <iostream> 83*b13c0e40SEric Biggersint main() 84*b13c0e40SEric Biggers{ 85*b13c0e40SEric Biggers std::cout << libfsverity_get_digest_size(FS_VERITY_HASH_ALG_SHA256) << std::endl; 86*b13c0e40SEric Biggers} 87*b13c0e40SEric BiggersEOF 88*b13c0e40SEric Biggers c++ -Wall -Werror "$TMPDIR/test.cc" -Iinclude -L. -lfsverity -o "$TMPDIR/test" 89*b13c0e40SEric Biggers [ "$(LD_LIBRARY_PATH=. "$TMPDIR/test")" = "32" ] 90*b13c0e40SEric Biggers rm "${TMPDIR:?}"/* 91*b13c0e40SEric Biggers} 92*b13c0e40SEric BiggersTEST_FUNCS+=(cplusplus_test) 93*b13c0e40SEric Biggers 94*b13c0e40SEric Biggersuntracked_files_test() 95*b13c0e40SEric Biggers{ 96*b13c0e40SEric Biggers log "Check that build doesn't produce untracked files" 97*b13c0e40SEric Biggers $MAKE CFLAGS="-Werror" all test_programs 98*b13c0e40SEric Biggers if git status --short | grep -q '^??'; then 99*b13c0e40SEric Biggers git status 100*b13c0e40SEric Biggers fail "Build produced untracked files (check 'git status'). Missing gitignore entry?" 101*b13c0e40SEric Biggers fi 102*b13c0e40SEric Biggers} 103*b13c0e40SEric BiggersTEST_FUNCS+=(untracked_files_test) 104*b13c0e40SEric Biggers 105*b13c0e40SEric Biggersuninstall_test() 106*b13c0e40SEric Biggers{ 107*b13c0e40SEric Biggers log "Test that 'make uninstall' uninstalls all files" 108*b13c0e40SEric Biggers make DESTDIR="$TMPDIR" install 109*b13c0e40SEric Biggers if [ "$(find "$TMPDIR" -type f -o -type l | wc -l)" = 0 ]; then 110*b13c0e40SEric Biggers fail "'make install' didn't install any files" 111*b13c0e40SEric Biggers fi 112*b13c0e40SEric Biggers make DESTDIR="$TMPDIR" uninstall 113*b13c0e40SEric Biggers if [ "$(find "$TMPDIR" -type f -o -type l | wc -l)" != 0 ]; then 114*b13c0e40SEric Biggers fail "'make uninstall' didn't uninstall all files" 115*b13c0e40SEric Biggers fi 116*b13c0e40SEric Biggers rm -r "${TMPDIR:?}"/* 117*b13c0e40SEric Biggers} 118*b13c0e40SEric BiggersTEST_FUNCS+=(uninstall_test) 119*b13c0e40SEric Biggers 120*b13c0e40SEric Biggersdash_test() 121*b13c0e40SEric Biggers{ 122*b13c0e40SEric Biggers log "Build, install, and uninstall with dash" 123*b13c0e40SEric Biggers make clean SHELL=/bin/dash 124*b13c0e40SEric Biggers make DESTDIR="$TMPDIR" SHELL=/bin/dash install 125*b13c0e40SEric Biggers make DESTDIR="$TMPDIR" SHELL=/bin/dash uninstall 126*b13c0e40SEric Biggers} 127*b13c0e40SEric BiggersTEST_FUNCS+=(dash_test) 128*b13c0e40SEric Biggers 129*b13c0e40SEric Biggerslicense_test() 130*b13c0e40SEric Biggers{ 131*b13c0e40SEric Biggers log "Check that all files have license and copyright info" 132*b13c0e40SEric Biggers list="$TMPDIR/filelist" 133*b13c0e40SEric Biggers filter_license_info() { 134*b13c0e40SEric Biggers # files to exclude from license and copyright info checks 135*b13c0e40SEric Biggers grep -E -v '(\.gitignore|LICENSE|.*\.md|testdata|fsverity_uapi\.h|libfsverity\.pc\.in)' 136*b13c0e40SEric Biggers } 137*b13c0e40SEric Biggers git grep -L 'SPDX-License-Identifier: MIT' \ 138*b13c0e40SEric Biggers | filter_license_info > "$list" || true 139*b13c0e40SEric Biggers if [ -s "$list" ]; then 140*b13c0e40SEric Biggers fail "The following files are missing an appropriate SPDX license identifier: $(<"$list")" 141*b13c0e40SEric Biggers fi 142*b13c0e40SEric Biggers # For now some people still prefer a free-form license statement, not just SPDX. 143*b13c0e40SEric Biggers git grep -L 'Use of this source code is governed by an MIT-style' \ 144*b13c0e40SEric Biggers | filter_license_info > "$list" || true 145*b13c0e40SEric Biggers if [ -s "$list" ]; then 146*b13c0e40SEric Biggers fail "The following files are missing an appropriate license statement: $(<"$list")" 147*b13c0e40SEric Biggers fi 148*b13c0e40SEric Biggers git grep -L '\<Copyright\>' | filter_license_info > "$list" || true 149*b13c0e40SEric Biggers if [ -s "$list" ]; then 150*b13c0e40SEric Biggers fail "The following files are missing a copyright statement: $(<"$list")" 151*b13c0e40SEric Biggers fi 152*b13c0e40SEric Biggers rm "$list" 153*b13c0e40SEric Biggers} 154*b13c0e40SEric BiggersTEST_FUNCS+=(license_test) 155*b13c0e40SEric Biggers 156*b13c0e40SEric Biggersgcc_test() 157*b13c0e40SEric Biggers{ 158*b13c0e40SEric Biggers log "Build and test with gcc (-O2)" 159*b13c0e40SEric Biggers $MAKE CC=gcc CFLAGS="-O2 -Werror" check 160*b13c0e40SEric Biggers 161*b13c0e40SEric Biggers log "Build and test with gcc (-O3)" 162*b13c0e40SEric Biggers $MAKE CC=gcc CFLAGS="-O3 -Werror" check 163*b13c0e40SEric Biggers} 164*b13c0e40SEric BiggersTEST_FUNCS+=(gcc_test) 165*b13c0e40SEric Biggers 166*b13c0e40SEric Biggersclang_test() 167*b13c0e40SEric Biggers{ 168*b13c0e40SEric Biggers log "Build and test with clang (-O2)" 169*b13c0e40SEric Biggers $MAKE CC=clang CFLAGS="-O2 -Werror" check 170*b13c0e40SEric Biggers 171*b13c0e40SEric Biggers log "Build and test with clang (-O3)" 172*b13c0e40SEric Biggers $MAKE CC=clang CFLAGS="-O3 -Werror" check 173*b13c0e40SEric Biggers} 174*b13c0e40SEric BiggersTEST_FUNCS+=(clang_test) 175*b13c0e40SEric Biggers 176*b13c0e40SEric Biggers32bit_test() 177*b13c0e40SEric Biggers{ 178*b13c0e40SEric Biggers log "Build and test with gcc (32-bit)" 179*b13c0e40SEric Biggers $MAKE CC=gcc CFLAGS="-O2 -Werror -m32" check 180*b13c0e40SEric Biggers} 181*b13c0e40SEric BiggersTEST_FUNCS+=(32bit_test) 182*b13c0e40SEric Biggers 183*b13c0e40SEric Biggerssanitizers_test() 184*b13c0e40SEric Biggers{ 185*b13c0e40SEric Biggers log "Build and test with clang + UBSAN" 186*b13c0e40SEric Biggers $MAKE CC=clang \ 187*b13c0e40SEric Biggers CFLAGS="-O2 -Werror -fsanitize=undefined -fno-sanitize-recover=undefined" \ 188*b13c0e40SEric Biggers check 189*b13c0e40SEric Biggers 190*b13c0e40SEric Biggers log "Build and test with clang + ASAN" 191*b13c0e40SEric Biggers $MAKE CC=clang \ 192*b13c0e40SEric Biggers CFLAGS="-O2 -Werror -fsanitize=address -fno-sanitize-recover=address" \ 193*b13c0e40SEric Biggers check 194*b13c0e40SEric Biggers 195*b13c0e40SEric Biggers log "Build and test with clang + unsigned integer overflow sanitizer" 196*b13c0e40SEric Biggers $MAKE CC=clang \ 197*b13c0e40SEric Biggers CFLAGS="-O2 -Werror -fsanitize=unsigned-integer-overflow -fno-sanitize-recover=unsigned-integer-overflow" \ 198*b13c0e40SEric Biggers check 199*b13c0e40SEric Biggers 200*b13c0e40SEric Biggers log "Build and test with clang + CFI" 201*b13c0e40SEric Biggers $MAKE CC=clang CFLAGS="-O2 -Werror -fsanitize=cfi -flto -fvisibility=hidden" \ 202*b13c0e40SEric Biggers AR=llvm-ar check 203*b13c0e40SEric Biggers} 204*b13c0e40SEric BiggersTEST_FUNCS+=(sanitizers_test) 205*b13c0e40SEric Biggers 206*b13c0e40SEric Biggersvalgrind_test() 207*b13c0e40SEric Biggers{ 208*b13c0e40SEric Biggers log "Build and test with valgrind" 209*b13c0e40SEric Biggers $MAKE TEST_WRAPPER_PROG="valgrind --quiet --error-exitcode=100 --leak-check=full --errors-for-leak-kinds=all" \ 210*b13c0e40SEric Biggers CFLAGS="-O2 -Werror" check 211*b13c0e40SEric Biggers} 212*b13c0e40SEric BiggersTEST_FUNCS+=(valgrind_test) 213*b13c0e40SEric Biggers 214*b13c0e40SEric Biggersboringssl_test() 215*b13c0e40SEric Biggers{ 216*b13c0e40SEric Biggers log "Build and test using BoringSSL instead of OpenSSL" 217*b13c0e40SEric Biggers log "-> Building BoringSSL" 218*b13c0e40SEric Biggers $MAKE boringssl 219*b13c0e40SEric Biggers log "-> Building fsverity-utils linked to BoringSSL" 220*b13c0e40SEric Biggers $MAKE CFLAGS="-O2 -Werror" LDFLAGS="-Lboringssl/build/crypto" \ 221*b13c0e40SEric Biggers CPPFLAGS="-Iboringssl/include" LDLIBS="-lcrypto -lpthread" check 222*b13c0e40SEric Biggers} 223*b13c0e40SEric BiggersTEST_FUNCS+=(boringssl_test) 224*b13c0e40SEric Biggers 225*b13c0e40SEric Biggersopenssl1_test() 226*b13c0e40SEric Biggers{ 227*b13c0e40SEric Biggers log "Build and test using OpenSSL 1.0" 228*b13c0e40SEric Biggers $MAKE CFLAGS="-O2 -Werror" LDFLAGS="-L/usr/lib/openssl-1.0" \ 229*b13c0e40SEric Biggers CPPFLAGS="-I/usr/include/openssl-1.0" check 230*b13c0e40SEric Biggers} 231*b13c0e40SEric BiggersTEST_FUNCS+=(openssl1_test) 232*b13c0e40SEric Biggers 233*b13c0e40SEric Biggersopenssl3_test() 234*b13c0e40SEric Biggers{ 235*b13c0e40SEric Biggers log "Build and test using OpenSSL 3.0" 236*b13c0e40SEric Biggers OSSL3=$HOME/src/openssl/inst/usr/local 237*b13c0e40SEric Biggers LD_LIBRARY_PATH="$OSSL3/lib64" $MAKE CFLAGS="-O2 -Werror" \ 238*b13c0e40SEric Biggers LDFLAGS="-L$OSSL3/lib64" CPPFLAGS="-I$OSSL3/include" check 239*b13c0e40SEric Biggers} 240*b13c0e40SEric BiggersTEST_FUNCS+=(openssl3_test) 241*b13c0e40SEric Biggers 242*b13c0e40SEric Biggersunsigned_char_test() 243*b13c0e40SEric Biggers{ 244*b13c0e40SEric Biggers log "Build and test using -funsigned-char" 245*b13c0e40SEric Biggers $MAKE CFLAGS="-O2 -Werror -funsigned-char" check 246*b13c0e40SEric Biggers} 247*b13c0e40SEric BiggersTEST_FUNCS+=(unsigned_char_test) 248*b13c0e40SEric Biggers 249*b13c0e40SEric Biggerssigned_char_test() 250*b13c0e40SEric Biggers{ 251*b13c0e40SEric Biggers log "Build and test using -fsigned-char" 252*b13c0e40SEric Biggers $MAKE CFLAGS="-O2 -Werror -fsigned-char" check 253*b13c0e40SEric Biggers} 254*b13c0e40SEric BiggersTEST_FUNCS+=(signed_char_test) 255*b13c0e40SEric Biggers 256*b13c0e40SEric Biggerswindows_build_test() 257*b13c0e40SEric Biggers{ 258*b13c0e40SEric Biggers log "Cross-compile for Windows (32-bit)" 259*b13c0e40SEric Biggers $MAKE CC=i686-w64-mingw32-gcc CFLAGS="-O2 -Werror" 260*b13c0e40SEric Biggers 261*b13c0e40SEric Biggers log "Cross-compile for Windows (64-bit)" 262*b13c0e40SEric Biggers $MAKE CC=x86_64-w64-mingw32-gcc CFLAGS="-O2 -Werror" 263*b13c0e40SEric Biggers} 264*b13c0e40SEric BiggersTEST_FUNCS+=(windows_build_test) 265*b13c0e40SEric Biggers 266*b13c0e40SEric Biggerssparse_test() 267*b13c0e40SEric Biggers{ 268*b13c0e40SEric Biggers log "Run sparse" 269*b13c0e40SEric Biggers ./scripts/run-sparse.sh 270*b13c0e40SEric Biggers} 271*b13c0e40SEric BiggersTEST_FUNCS+=(sparse_test) 272*b13c0e40SEric Biggers 273*b13c0e40SEric Biggersclang_analyzer_test() 274*b13c0e40SEric Biggers{ 275*b13c0e40SEric Biggers log "Run clang static analyzer" 276*b13c0e40SEric Biggers scan-build --status-bugs make CFLAGS="-O2 -Werror" all test_programs 277*b13c0e40SEric Biggers} 278*b13c0e40SEric BiggersTEST_FUNCS+=(clang_analyzer_test) 279*b13c0e40SEric Biggers 280*b13c0e40SEric Biggersshellcheck_test() 281*b13c0e40SEric Biggers{ 282*b13c0e40SEric Biggers log "Run shellcheck" 283*b13c0e40SEric Biggers shellcheck scripts/*.sh 1>&2 284*b13c0e40SEric Biggers} 285*b13c0e40SEric BiggersTEST_FUNCS+=(shellcheck_test) 286*b13c0e40SEric Biggers 287*b13c0e40SEric Biggerstest_exists() 288*b13c0e40SEric Biggers{ 289*b13c0e40SEric Biggers local tst=$1 290*b13c0e40SEric Biggers local func 291*b13c0e40SEric Biggers for func in "${TEST_FUNCS[@]}"; do 292*b13c0e40SEric Biggers if [ "${tst}_test" = "$func" ]; then 293*b13c0e40SEric Biggers return 0 294*b13c0e40SEric Biggers fi 295*b13c0e40SEric Biggers done 296*b13c0e40SEric Biggers return 1 297*b13c0e40SEric Biggers} 298*b13c0e40SEric Biggers 299*b13c0e40SEric Biggersif [[ $# == 0 ]]; then 300*b13c0e40SEric Biggers for func in "${TEST_FUNCS[@]}"; do 301*b13c0e40SEric Biggers eval "$func" 302*b13c0e40SEric Biggers done 303*b13c0e40SEric Biggerselse 304*b13c0e40SEric Biggers for tst; do 305*b13c0e40SEric Biggers if ! test_exists "$tst"; then 306*b13c0e40SEric Biggers echo 1>&2 "Unknown test: $tst" 307*b13c0e40SEric Biggers exit 2 308*b13c0e40SEric Biggers fi 309*b13c0e40SEric Biggers done 310*b13c0e40SEric Biggers for tst; do 311*b13c0e40SEric Biggers eval "${tst}_test" 312*b13c0e40SEric Biggers done 313*b13c0e40SEric Biggersfi 314*b13c0e40SEric Biggers 315*b13c0e40SEric Biggerslog "All tests passed!" 316