forked from osmocom/wireshark
fuzzshark: integrate oss-fuzz targets in CMake
The current fuzzshark target built by CMake is not usable for fuzzing. Address this by adding a new ENABLE_FUZZER option that enables mandatory instrumentation and libFuzzer linking options for the fuzzshark binary. Create more CMake targets for specific fuzzing targets such as fuzzshark_ip and fuzzshark_ip_proto-udp. These targets are not built by default, either build individual targets or use the all-fuzzers target. Now these binaries are not specific to oss-fuzz, so move them to a new directory (perhaps the corpora can be added here in the future). oss-fuzz build.sh is simplified and reuses the CMake targets. When OSS_FUZZ is set, it will force static linking with external libraries and limit parallel linker jobs (maybe not necessary for Google's oss-fuzz builders, but my 8G/6c VM ran out of memory). Change-Id: If3ba8f60ea1f5c3bd2131223050a81f9acbce05d Reviewed-on: https://code.wireshark.org/review/30228 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
parent
eda196951b
commit
7e88bb5e53
|
@ -268,6 +268,36 @@ if(APPLE AND EXISTS /usr/local/opt/qt5)
|
|||
set (QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5)
|
||||
endif()
|
||||
|
||||
set(OSS_FUZZ OFF CACHE BOOL "Whether building for oss-fuzz")
|
||||
mark_as_advanced(OSS_FUZZ)
|
||||
if(OSS_FUZZ)
|
||||
if(ENABLE_FUZZER)
|
||||
# In oss-fuzz mode, the fuzzing engine can be afl or libFuzzer.
|
||||
message(FATAL_ERROR "Cannot force libFuzzer when using oss-fuzz")
|
||||
endif()
|
||||
# Must not depend on external dependencies so statically link all libs.
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Linking can consume a lot of memory, especially when built with ASAN and
|
||||
# static libraries (like oss-fuzz) or Debug mode. With Ninja, the number of
|
||||
# parallel linker processes is constrained by job parallelism (-j), but this can
|
||||
# be reduced further by setting "job pools" to a lower number.
|
||||
#
|
||||
if(CMAKE_MAKE_PROGRAM MATCHES "ninja" AND OSS_FUZZ)
|
||||
# Assume oss-fuzz linker jobs do not require more than 1.2G per task
|
||||
set(per_job_memory_mb 1200)
|
||||
cmake_host_system_information(RESULT total_memory_mb QUERY TOTAL_PHYSICAL_MEMORY)
|
||||
math(EXPR parallel_link_jobs "${total_memory_mb} / ${per_job_memory_mb}")
|
||||
if(parallel_link_jobs LESS 1)
|
||||
set(parallel_link_jobs 1)
|
||||
endif()
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${parallel_link_jobs})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
message(STATUS "Ninja job pool size: ${parallel_link_jobs}")
|
||||
endif()
|
||||
|
||||
# Always enable position-independent code when compiling, even for
|
||||
# executables, so you can build position-independent executables.
|
||||
# -pie is added below for non-MSVC.
|
||||
|
@ -732,6 +762,21 @@ if(ENABLE_UBSAN)
|
|||
set(CMAKE_CXX_FLAGS "-fsanitize=undefined ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(ENABLE_FUZZER)
|
||||
# Available since Clang >= 6
|
||||
# Will enable coverage flags which can be used by the fuzzshark target.
|
||||
cmake_push_check_state()
|
||||
set(CMAKE_REQUIRED_LIBRARIES "-fsanitize=fuzzer-no-link")
|
||||
check_c_compiler_flag(-fsanitize=fuzzer C__fsanitize_fuzzer_no_link_VALID)
|
||||
check_cxx_compiler_flag(-fsanitize=fuzzer CXX__fsanitize_fuzzer_no_link_VALID)
|
||||
cmake_pop_check_state()
|
||||
if(NOT C__fsanitize_fuzzer_no_link_VALID OR NOT CXX__fsanitize_fuzzer_no_link_VALID)
|
||||
message(FATAL_ERROR "ENABLE_FUZZER was requested, but not supported!")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "-fsanitize=fuzzer-no-link ${CMAKE_C_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "-fsanitize=fuzzer-no-link ${CMAKE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
set(WERROR_COMMON_FLAGS "")
|
||||
if(NOT DISABLE_WERROR AND NOT ENABLE_EXTRA_COMPILER_WARNINGS)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "MSVC")
|
||||
|
@ -2351,20 +2396,8 @@ if(BUILD_randpkt)
|
|||
install(TARGETS randpkt RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
if(BUILD_fuzzshark)
|
||||
set(fuzzshark_LIBS
|
||||
wiretap
|
||||
${LIBEPAN_LIBS}
|
||||
)
|
||||
set(fuzzshark_FILES
|
||||
tools/oss-fuzzshark/fuzzshark.c
|
||||
tools/oss-fuzzshark/StandaloneFuzzTargetMain.c
|
||||
version_info.c
|
||||
)
|
||||
add_executable(fuzzshark ${fuzzshark_FILES})
|
||||
add_dependencies(fuzzshark version)
|
||||
set_extra_executable_properties(fuzzshark "Executables")
|
||||
target_link_libraries(fuzzshark ${fuzzshark_LIBS})
|
||||
if(BUILD_fuzzshark OR ENABLE_FUZZER OR OSS_FUZZ)
|
||||
add_subdirectory(fuzz)
|
||||
endif()
|
||||
|
||||
if(BUILD_text2pcap)
|
||||
|
|
|
@ -45,6 +45,7 @@ option(ENABLE_CODE_ANALYSIS "Enable the compiler's static analyzer if possible"
|
|||
option(ENABLE_ASAN "Enable AddressSanitizer (ASAN) for debugging (degrades performance)" OFF)
|
||||
option(ENABLE_TSAN "Enable ThreadSanitizer (TSan) for debugging" OFF)
|
||||
option(ENABLE_UBSAN "Enable UndefinedBehaviorSanitizer (UBSan) for debugging" OFF)
|
||||
option(ENABLE_FUZZER "Enable libFuzzer instrumentation for use with fuzzshark" OFF)
|
||||
option(ENABLE_CHECKHF_CONFLICT "Enable hf conflict check for debugging (start-up may be slower)" OFF)
|
||||
option(ENABLE_CCACHE "Speed up compiling and linking using ccache if possible" OFF)
|
||||
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
# CMakeLists.txt
|
||||
#
|
||||
# Wireshark - Network traffic analyzer
|
||||
# By Gerald Combs <gerald@wireshark.org>
|
||||
# Copyright 1998 Gerald Combs
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#
|
||||
|
||||
# List of dissectors compiled below, which should be turned off.
|
||||
# This is done to avoid single fuzzer (like IP) to call UDP protocols, which can go back to IP, and so on..
|
||||
# While doing so might find some bugs, but it's likely to be the problem for too big corpus in oss-fuzzer
|
||||
# (see: https://github.com/google/oss-fuzz/issues/1087).
|
||||
# + udplite - it's sharing most of code with UDP.
|
||||
set(FUZZ_DISABLED_DISSECTORS ip udp udplite ospf bgp dhcp json)
|
||||
|
||||
set(FUZZ_DISSECTORS ip)
|
||||
set(FUZZ_IP_PROTO_DISSECTORS udp ospf)
|
||||
|
||||
set(FUZZ_TCP_PORT_DISSECTORS bgp)
|
||||
# list(APPEND FUZZ_TCP_PORT_DISSECTORS bzr) # disabled, cause of known problem.
|
||||
# list(APPEND FUZZ_TCP_PORT_DISSECTORS echo) # disabled, too simple.
|
||||
|
||||
set(FUZZ_UDP_PORT_DISSECTORS dns dhcp)
|
||||
# list(FUZZ_UDP_PORT_DISSECTORS bfd) # disabled, too simple.
|
||||
|
||||
set(FUZZ_MEDIA_TYPE_DISSECTORS json)
|
||||
|
||||
set(fuzzshark_LIBS
|
||||
wiretap
|
||||
${LIBEPAN_LIBS}
|
||||
)
|
||||
if(OSS_FUZZ)
|
||||
if("$ENV{LIB_FUZZING_ENGINE}" STREQUAL "")
|
||||
message(FATAL_ERROR "LIB_FUZZING_ENGINE is not set!")
|
||||
endif()
|
||||
list(APPEND fuzzshark_LIBS $ENV{LIB_FUZZING_ENGINE})
|
||||
endif()
|
||||
set(fuzzshark_FILES
|
||||
fuzzshark.c
|
||||
${CMAKE_SOURCE_DIR}/version_info.c
|
||||
)
|
||||
set(FUZZ_LINK_FLAGS "${WS_LINK_FLAGS}")
|
||||
if(ENABLE_FUZZER)
|
||||
set(FUZZ_LINK_FLAGS "${FUZZ_LINK_FLAGS} -fsanitize=fuzzer")
|
||||
endif()
|
||||
if(OSS_FUZZ)
|
||||
# libFuzzingEngine.a is not position independent, so cannot use -pie.
|
||||
set(FUZZ_LINK_FLAGS "${FUZZ_LINK_FLAGS} -no-pie")
|
||||
endif()
|
||||
|
||||
# Convert the list of disabled dissectors from a;b;c -> "a", "b", "c"
|
||||
# for use in fuzzshark.c (macro)
|
||||
string(REGEX REPLACE "([^;]+)" "\"\\1\"" FUZZ_DISABLED_DISSECTORS_MACRO "${FUZZ_DISABLED_DISSECTORS}")
|
||||
string(REPLACE ";" ", " FUZZ_DISABLED_DISSECTORS_MACRO "${FUZZ_DISABLED_DISSECTORS_MACRO}")
|
||||
|
||||
# Targets that are build via all-fuzzers:
|
||||
# - fuzzshark: a non-specific fuzz target, configurable through env vars (requires BUILD_fuzzshark)
|
||||
# - fuzzshark_<target>: fuzz target for a specific dissector target.
|
||||
# - fuzzshark_<table>-<target>: fuzz target for a specific dissector via a dissector table.
|
||||
add_custom_target(all-fuzzers)
|
||||
|
||||
function(fuzzshark_set_common_options fuzzer_name)
|
||||
add_dependencies(${fuzzer_name} version)
|
||||
# Sanitizers require a C++ runtime, so use a C++ linker.
|
||||
set_target_properties(${fuzzer_name} PROPERTIES
|
||||
FOLDER "Fuzzers"
|
||||
LINK_FLAGS "${FUZZ_LINK_FLAGS}"
|
||||
LINKER_LANGUAGE "CXX"
|
||||
)
|
||||
target_link_libraries(${fuzzer_name} ${fuzzshark_LIBS})
|
||||
add_dependencies(all-fuzzers ${fuzzer_name})
|
||||
endfunction()
|
||||
|
||||
if(BUILD_fuzzshark)
|
||||
if(NOT (ENABLE_FUZZER OR OSS_FUZZ))
|
||||
# libFuzzer includes a main routine that enables fuzzing. If
|
||||
# support for fuzzing was not enabled, add a small standalone
|
||||
# target that can be used to test-compile fuzzshark.c.
|
||||
list(APPEND fuzzshark_FILES StandaloneFuzzTargetMain.c)
|
||||
endif()
|
||||
add_executable(fuzzshark ${fuzzshark_FILES})
|
||||
fuzzshark_set_common_options(fuzzshark)
|
||||
endif()
|
||||
|
||||
# Create a new dissector fuzzer target.
|
||||
# If <dissector_table> is empty, <name> will be called directly.
|
||||
# If <dissector_table> is non-empty, a dissector with filter name <name> will be
|
||||
# looked up in dissector table <dissector_table>.
|
||||
function(generate_fuzzer dissector_table name)
|
||||
if(NOT (ENABLE_FUZZER OR OSS_FUZZ))
|
||||
return()
|
||||
endif()
|
||||
|
||||
if(dissector_table STREQUAL "")
|
||||
set(fuzzer_name fuzzshark_${name})
|
||||
else()
|
||||
# "ip.proto" and "udp" -> "ip_proto-udp"
|
||||
set(fuzzer_name fuzzshark_${dissector_table}-${name})
|
||||
string(REPLACE "." "_" fuzzer_name ${fuzzer_name})
|
||||
endif()
|
||||
|
||||
add_executable(${fuzzer_name} EXCLUDE_FROM_ALL ${fuzzshark_FILES})
|
||||
fuzzshark_set_common_options(${fuzzer_name})
|
||||
target_compile_definitions(${fuzzer_name} PRIVATE
|
||||
FUZZ_DISSECTOR_LIST=${FUZZ_DISABLED_DISSECTORS_MACRO}
|
||||
FUZZ_DISSECTOR_TABLE="${dissector_table}"
|
||||
FUZZ_DISSECTOR_TARGET="${name}"
|
||||
)
|
||||
endfunction()
|
||||
|
||||
# Add fuzzer targets for every dissector in list FUZZ_<table-var>_DISSECTORS,
|
||||
# where <table-var> changes a <table> such as "ip.proto" into "IP_PROTO".
|
||||
function(add_table_fuzzers table)
|
||||
string(REPLACE "." "_" table_var ${table})
|
||||
string(TOUPPER "${table_var}" table_var)
|
||||
foreach(dissector IN LISTS FUZZ_${table_var}_DISSECTORS)
|
||||
generate_fuzzer(${table} ${dissector})
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
foreach(dissector IN LISTS FUZZ_DISSECTORS)
|
||||
generate_fuzzer("" ${dissector})
|
||||
endforeach()
|
||||
|
||||
add_table_fuzzers("ip.proto")
|
||||
add_table_fuzzers("tcp.port")
|
||||
add_table_fuzzers("udp.port")
|
||||
add_table_fuzzers("media_type")
|
||||
|
||||
#
|
||||
# Editor modelines - http://www.wireshark.org/tools/modelines.html
|
||||
#
|
||||
# Local variables:
|
||||
# c-basic-offset: 8
|
||||
# tab-width: 8
|
||||
# indent-tabs-mode: t
|
||||
# End:
|
||||
#
|
||||
# vi: set shiftwidth=8 tabstop=8 noexpandtab:
|
||||
# :indentSize=8:tabSize=8:noTabs=false:
|
||||
#
|
|
@ -3,70 +3,20 @@
|
|||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# List of dissectors compiled below, which should be turned off.
|
||||
# This is done to avoid single fuzzer (like IP) to call UDP protocols, which can go back to IP, and so on..
|
||||
# While doing so might find some bugs, but it's likely to be the problem for too big corpus in oss-fuzzer
|
||||
# (see: https://github.com/google/oss-fuzz/issues/1087).
|
||||
# + udplite - it's sharing most of code with UDP.
|
||||
DISSECTOR_LIST='"ip", "udp", "udplite", "ospf", "bgp", "dhcp", "json"'
|
||||
|
||||
FUZZ_DISSECTORS="ip"
|
||||
|
||||
FUZZ_IP_PROTO_DISSECTORS="udp ospf"
|
||||
|
||||
FUZZ_TCP_PORT_DISSECTORS="bgp"
|
||||
# FUZZ_TCP_PORT_DISSECTORS="$FUZZ_TCP_PORT_DISSECTORS bzr" # disabled, cause of known problem.
|
||||
# FUZZ_TCP_PORT_DISSECTORS="$FUZZ_TCP_PORT_DISSECTORS echo" # disabled, too simple.
|
||||
|
||||
FUZZ_UDP_PORT_DISSECTORS="dns dhcp"
|
||||
# FUZZ_UDP_PORT_DISSECTORS="$FUZZ_UDP_PORT_DISSECTORS bfd" # disabled, too simple.
|
||||
|
||||
FUZZ_MEDIA_TYPE_DISSECTORS="json"
|
||||
|
||||
# TODO: support specifing targets in args. Google oss-fuzz specifies 'all'.
|
||||
|
||||
# generate_fuzzer <fuzzer_target> <fuzzer_cflags>
|
||||
generate_fuzzer()
|
||||
{
|
||||
local fuzzer_target="$1" fuzzer_cflags="$2" fuzzer_name
|
||||
# TODO update oss-fuzz configuration to build with OSS_FUZZ=1? This is necessary
|
||||
# to build the fuzzshark_* targets for oss-fuzz.
|
||||
cmake -DOSS_FUZZ=1 .
|
||||
|
||||
fuzzer_name="fuzzshark_$1"
|
||||
|
||||
$CC $CFLAGS -I $WIRESHARK_INSTALL_PATH/include/wireshark/ `pkg-config --cflags glib-2.0` \
|
||||
$SRC/wireshark/tools/oss-fuzzshark/fuzzshark.c \
|
||||
-c -o $WORK/${fuzzer_name}.o \
|
||||
$fuzzer_cflags -DFUZZ_DISSECTOR_LIST="$DISSECTOR_LIST"
|
||||
|
||||
$CXX $CXXFLAGS $WORK/${fuzzer_name}.o \
|
||||
-o $OUT/${fuzzer_name} \
|
||||
${WIRESHARK_FUZZERS_COMMON_FLAGS}
|
||||
cmake --build . --target all-fuzzers
|
||||
|
||||
for file in run/fuzzshark_*; do
|
||||
fuzzer_name="${file##*/}"
|
||||
fuzzer_target="${fuzzer_name#fuzzshark_}"
|
||||
mv "$file" "$OUT/"
|
||||
echo -en "[libfuzzer]\nmax_len = 1024\n" > $OUT/${fuzzer_name}.options
|
||||
if [ -d "$SAMPLES_DIR/${fuzzer_target}" ]; then
|
||||
zip -j $OUT/${fuzzer_name}_seed_corpus.zip $SAMPLES_DIR/${fuzzer_target}/*/*.bin
|
||||
fi
|
||||
}
|
||||
|
||||
WIRESHARK_FUZZERS_COMMON_FLAGS="-lFuzzingEngine \
|
||||
-L"$WIRESHARK_INSTALL_PATH/lib" -lwireshark -lwiretap -lwsutil \
|
||||
-Wl,-Bstatic `pkg-config --libs glib-2.0` -pthread -lpcre -lgcrypt -lgpg-error -lz -Wl,-Bdynamic"
|
||||
|
||||
for dissector in $FUZZ_DISSECTORS; do
|
||||
generate_fuzzer "${dissector}" -DFUZZ_DISSECTOR_TARGET=\"$dissector\"
|
||||
done
|
||||
|
||||
for dissector in $FUZZ_IP_PROTO_DISSECTORS; do
|
||||
generate_fuzzer "ip_proto-${dissector}" "-DFUZZ_DISSECTOR_TABLE=\"ip.proto\" -DFUZZ_DISSECTOR_TARGET=\"$dissector\""
|
||||
done
|
||||
|
||||
for dissector in $FUZZ_TCP_PORT_DISSECTORS; do
|
||||
generate_fuzzer "tcp_port-${dissector}" "-DFUZZ_DISSECTOR_TABLE=\"tcp.port\" -DFUZZ_DISSECTOR_TARGET=\"$dissector\""
|
||||
done
|
||||
|
||||
for dissector in $FUZZ_UDP_PORT_DISSECTORS; do
|
||||
generate_fuzzer "udp_port-${dissector}" "-DFUZZ_DISSECTOR_TABLE=\"udp.port\" -DFUZZ_DISSECTOR_TARGET=\"$dissector\""
|
||||
done
|
||||
|
||||
for dissector in $FUZZ_MEDIA_TYPE_DISSECTORS; do
|
||||
generate_fuzzer "media_type-${dissector}" "-DFUZZ_DISSECTOR_TABLE=\"media_type\" -DFUZZ_DISSECTOR_TARGET=\"$dissector\""
|
||||
done
|
||||
|
|
Loading…
Reference in New Issue