Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 43 additions & 4 deletions test/fuzz/oss-fuzz/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,51 @@ cd "$SRC/tcpreplay"
./configure --disable-local-libopts
make -j"$(nproc)"

# The Dockerfile installs libpcap-dev so this build (and tcpreplay's own
# normal build) can find pcap.h/link against something - but the fuzz targets
# link against a *separately built* libpcap.a below, not that system package.
#
# Debian/Ubuntu's libpcap is built with D-Bus, Bluetooth and USB sniffing
# support enabled, each pulling in its own shared library (libdbus-1,
# libsystemd, and libsystemd's own dependency on libcap in turn). All of that
# is dynamically linked into libpcap.so, so the *build* step here links fine
# - the base-builder image has every one of those .so files. OSS-Fuzz's
# separate runner image, where the built binaries actually execute, does not:
# it installs only libcap2 (see infra/base-images/base-runner/install_deps.sh
# upstream), not libdbus-1 or libsystemd. The result was every target dying
# at startup with "error while loading shared libraries: libpcap.so.0.8:
# cannot open shared object file" - a build that reported success but
# produced nothing that could actually run.
#
# Linking the *system* libpcap.a statically doesn't fix this - it just moves
# the missing .so from libpcap itself to whatever libpcap.a still pulls in
# (dbus, systemd, and transitively libcap's cap_* symbols, none of which are
# needed for reading pcap files). None of that is needed to fuzz the pcap
# read path, so it's built out entirely: a self-contained libpcap.a with the
# capture backends that need those disabled, leaving nothing for a fuzz
# target to depend on beyond libc/libstdc++/libm - which the runner image, or
# any Linux system, always has.
cd "$SRC/libpcap"
mkdir -p build
cd build
cmake -DBUILD_SHARED_LIBS=OFF -DDISABLE_DBUS=ON -DDISABLE_BLUETOOTH=ON \
-DDISABLE_LINUX_USBMON=ON -DDISABLE_RDMA=ON ..
make -j"$(nproc)" pcap_static
LIBPCAP_A="$SRC/libpcap/build/libpcap.a"
cd "$SRC/tcpreplay"

# libdnet is optional, and fragroute is the only target that needs it - Debian/
# Ubuntu (including this image) package it as libdumbnet, not libdnet, so the
# link flag has to come from wherever ./configure already worked that out
# rather than being guessed here. test/fuzz/Makefile has it after configure
# runs above, whether or not fragroute itself is actually available.
# runs above, whether or not fragroute itself is actually available. Statically
# linked for the same reason as libpcap above; libdumbnet has no equivalent
# transitive dependency problem, so the system copy is fine to use as-is.
FRAGROUTE_LIB=""
FRAGROUTE_LIBNET=""
if [ -f src/fragroute/libfragroute.a ]; then
FRAGROUTE_LIB="src/fragroute/libfragroute.a"
FRAGROUTE_LIBNET=$(sed -n 's/^LDNETLIB = //p' test/fuzz/Makefile)
FRAGROUTE_LIBNET="-Wl,-Bstatic $(sed -n 's/^LDNETLIB = //p' test/fuzz/Makefile) -Wl,-Bdynamic"
fi

for target in fuzz_services fuzz_pcap fuzz_fragroute; do
Expand All @@ -52,9 +87,13 @@ for target in fuzz_services fuzz_pcap fuzz_fragroute; do
continue
fi

libs="src/common/libcommon.a -lpcap"
# Link order matters for static archives: they only resolve symbols for
# things listed *after* them, so each library has to come before whatever
# it depends on - libfragroute needs libcommon and libdumbnet, libcommon
# needs libpcap.
libs="src/common/libcommon.a $LIBPCAP_A"
if [ "$target" = "fuzz_fragroute" ]; then
libs="$FRAGROUTE_LIB $libs $FRAGROUTE_LIBNET"
libs="$FRAGROUTE_LIB src/common/libcommon.a $LIBPCAP_A $FRAGROUTE_LIBNET"
fi

$CC $CFLAGS -DHAVE_CONFIG_H -I. -Isrc -Itest/fuzz -c "test/fuzz/${target}.c" -o "$WORK/${target}.o"
Expand Down
Loading