From 85c3fe47292f4e4e47a1f58f1347cb1f6d03b37e Mon Sep 17 00:00:00 2001 From: Manuel Bentele Date: Tue, 20 Oct 2020 15:31:52 +0200 Subject: [BUILD] add option to build the dnbd3-server with afl-fuzz support The afl-fuzz support for the dnbd3-server requires an AFL C compiler like afl-gcc and can be enabled with the CMake option DNBD3_SERVER_AFL. --- CMakeLists.txt | 17 ++++++++++++----- cmake/CheckAFLCCompiler.cmake | 24 ++++++++++++++++++++++++ inc/dnbd3/shared/log.h | 15 +++++++++++++++ src/bench/main.c | 2 ++ src/fuse/main.c | 2 ++ src/server/CMakeLists.txt | 18 ++++++++++++++++++ src/server/server.c | 17 ++++++++++++----- src/shared/log.c | 32 +++++++++++++++++++++----------- 8 files changed, 106 insertions(+), 21 deletions(-) create mode 100644 cmake/CheckAFLCCompiler.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 4bcdc10..f2485de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ OPTION(DNBD3_SERVER_FUSE "Enable FUSE-Integration for dnbd3-server" OFF) OPTION(DNBD3_SERVER_AFL "Build dnbd3-server for usage with afl-fuzz" OFF) OPTION(DNBD3_SERVER_DEBUG_LOCKS "Add lock debugging code to dnbd3-server" OFF) OPTION(DNBD3_SERVER_DEBUG_THREADS "Add thread debugging code to dnbd3-server" OFF) -OPTION(DNBD3_RELEASE_HARDENING "Harden dnbd3 programs in Release build configuration" OFF) +OPTION(DNBD3_RELEASE_HARDEN "Compile dnbd3 programs in Release build with code hardening options" OFF) # set supported build configurations set(CMAKE_CONFIGURATION_TYPES Debug Release) @@ -89,10 +89,17 @@ set(CMAKE_C_FLAGS_RELEASE "-Wno-error") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -g -Og -DDEBUG") set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3 -DNDEBUG") -if(DNBD3_RELEASE_HARDENING) - # harden Release builds with specific C flags - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2 -fstack-protector-strong -fstack-clash-protection -mfunction-return=thunk -mindirect-branch=thunk") -endif(DNBD3_RELEASE_HARDENING) +if(DNBD3_RELEASE_HARDEN AND CMAKE_BUILD_TYPE MATCHES "Release") + # harden builds with specific C flags + set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -D_FORTIFY_SOURCE=2 -fstack-protector-all -fstack-clash-protection -mfunction-return=thunk -mindirect-branch=thunk") + # set specific hardened linker flags + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,relro,-z,now,-z,defs -pie") + # print status message of configuration + message(STATUS "Set compilation of DNBD3 with hardened code options - done") +else(DNBD3_RELEASE_HARDEN AND CMAKE_BUILD_TYPE MATCHES "Release") + # print status message of disabled configuration + message(STATUS "Disabled compilation of DNBD3 with hardened code options - done") +endif(DNBD3_RELEASE_HARDEN AND CMAKE_BUILD_TYPE MATCHES "Release") # add all dnbd3 related projects from the source code directory add_subdirectory(src) diff --git a/cmake/CheckAFLCCompiler.cmake b/cmake/CheckAFLCCompiler.cmake new file mode 100644 index 0000000..249248b --- /dev/null +++ b/cmake/CheckAFLCCompiler.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) 2020 Manuel Bentele +# + +# check if corresponding AFL C Compiler form original C compiler is available +# if an AFL C compiler is available, then the path to the AFL C compiler is returned in AFL_C_COMPILER +macro(check_afl_c_compiler AFL_C_COMPILER AFL_C_COMPILER_NAME C_COMPILER_PATH C_COMPILER_ID) + # determine AFL C compiler suffix from original C compiler ID + if(${C_COMPILER_ID} MATCHES "GNU") + set(AFL_C_COMPILER_SUFFIX "gcc") + elseif(${C_COMPILER_ID} MATCHES "Clang") + set(AFL_C_COMPILER_SUFFIX "clang") + else(${C_COMPILER_ID} MATCHES "Clang") + get_filename_component(AFL_C_COMPILER_SUFFIX ${C_COMPILER_PATH} NAME) + endif(${C_COMPILER_ID} MATCHES "GNU") + + # define search file name and search for AFL C compiler program + set(AFL_C_COMPILER_SEARCH_NAME "afl-${AFL_C_COMPILER_SUFFIX}") + find_program(${AFL_C_COMPILER} NAMES ${AFL_C_COMPILER_SEARCH_NAME}) + + # return the AFL C compiler name to the caller + set(${AFL_C_COMPILER_NAME} ${AFL_C_COMPILER_SEARCH_NAME}) +endmacro(check_afl_c_compiler) \ No newline at end of file diff --git a/inc/dnbd3/shared/log.h b/inc/dnbd3/shared/log.h index 5b1e8f7..9185b18 100644 --- a/inc/dnbd3/shared/log.h +++ b/inc/dnbd3/shared/log.h @@ -23,6 +23,7 @@ #include #include +#include typedef unsigned int logmask_t; #define LOG_ERROR ((logmask_t)1) // Fatal error, server will terminate @@ -32,6 +33,10 @@ typedef unsigned int logmask_t; #define LOG_DEBUG1 ((logmask_t)16) // Debug information, use this for non-spammy stuff #define LOG_DEBUG2 ((logmask_t)32) // Use this for debug messages that will show up a lot +/** + * Initialize the logging (constructor) + */ +void log_init(void); /** * Check if cansoleMask | fileMask has all of mask set. @@ -44,6 +49,16 @@ void log_setConsoleMask(logmask_t mask); void log_setConsoleTimestamps(bool on); +/** + * Set console output stream + * The output stream can be either stdout or stderr + * + * Note: A call of this function is optional and only required if the output + * stream should be changed from stdout to stderr since the log + * implementation defaults to the output stream stdout + */ +int log_setConsoleOutputStream(FILE *outputStream); + /** * Open or reopen the log file. If path is NULL and the * function was called with a path before, the same path diff --git a/src/bench/main.c b/src/bench/main.c index a167f05..1a59747 100644 --- a/src/bench/main.c +++ b/src/bench/main.c @@ -76,6 +76,8 @@ int main(int argc, char *argv[]) int n_threads = 1; int bs = 4096; + log_init(); + if ( argc <= 1 || strcmp( argv[1], "--help" ) == 0 || strcmp( argv[1], "--usage" ) == 0 ) { printUsage( argv[0], 0 ); } diff --git a/src/fuse/main.c b/src/fuse/main.c index 5cf3e81..2a851a7 100644 --- a/src/fuse/main.c +++ b/src/fuse/main.c @@ -329,6 +329,8 @@ int main( int argc, char *argv[] ) char *mountpoint; int foreground = 0; + log_init(); + if ( argc <= 1 || strcmp( argv[1], "--help" ) == 0 || strcmp( argv[1], "--usage" ) == 0 ) { printUsage( argv[0], 0 ); } diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index 1855d91..aa981f6 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -13,9 +13,27 @@ endif(NOT JANSSON_FOUND) add_definitions(-D_GNU_SOURCE) if(DNBD3_SERVER_AFL) + # check if DNBD3_RELEASE_HARDEN is disabled + if(DNBD3_RELEASE_HARDEN) + message(FATAL_ERROR "DNBD3_SERVER_AFL can only be enabled if DNBD3_RELEASE_HARDEN is disabled") + endif(DNBD3_RELEASE_HARDEN) + # build dnbd3-server with AFL support message(STATUS "Building dnbd3-server with AFL support") add_definitions(-DDNBD3_SERVER_AFL) + + # change compiler for dnbd3-server sources if AFL enabled + include(CheckAFLCCompiler) + check_afl_c_compiler(AFL_C_COMPILER AFL_C_COMPILER_NAME ${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ID}) + if(AFL_C_COMPILER) + message(STATUS "Check for working AFL C compiler: ${AFL_C_COMPILER} - done") + # change C compiler to a corresponding AFL C compiler + set(CMAKE_C_COMPILER "${AFL_C_COMPILER}") + else(AFL_C_COMPILER) + # no corresponding AFL C compiler found + message(STATUS "Check for working AFL C compiler: ${AFL_C_COMPILER_NAME} - failed") + message(FATAL_ERROR "No corresponding AFL C compiler ${AFL_C_COMPILER_NAME} was found for the C compiler ${CMAKE_C_COMPILER}!") + endif(AFL_C_COMPILER) endif(DNBD3_SERVER_AFL) add_executable(dnbd3-server ${CMAKE_CURRENT_SOURCE_DIR}/altservers.c diff --git a/src/server/server.c b/src/server/server.c index 55ec042..0ee51c4 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -217,6 +217,16 @@ int main(int argc, char *argv[]) { 0, 0, 0, 0 } }; + log_init(); + + /* set proper output stream for AFL */ +#ifdef DNBD3_SERVER_AFL + if ( log_setConsoleOutputStream(stderr) < 0 ) { + logadd( LOG_ERROR, "Failed to set output stream for AFL to stderr" ); + exit( EXIT_FAILURE ); + } +#endif + mainPid = getpid(); mainThread = pthread_self(); opt = getopt_long( argc, argv, optString, longOpts, &longIndex ); @@ -278,6 +288,7 @@ int main(int argc, char *argv[]) opt = getopt_long( argc, argv, optString, longOpts, &longIndex ); } + // Load general config if ( _configDir == NULL ) _configDir = strdup( "/etc/dnbd3-server" ); @@ -291,8 +302,6 @@ int main(int argc, char *argv[]) timing_get( &startupTime ); #ifdef DNBD3_SERVER_AFL - // ###### AFL - // image_serverStartup(); net_init(); uplink_globalsInit(); @@ -316,9 +325,7 @@ int main(int argc, char *argv[]) net_handleNewConnection( dnbd3_client ); exit( 0 ); } - // - // ###### AFL END -#endif +#endif /* DNBD3_SERVER_AFL */ // One-shots first: diff --git a/src/shared/log.c b/src/shared/log.c index f2cab85..374bed1 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -36,6 +36,7 @@ static _Atomic logmask_t maskCon = 15; static char *logFile = NULL; static int logFd = -1; +static FILE *logOutStream; static bool consoleTimestamps = false; @@ -43,6 +44,10 @@ static bool consoleTimestamps = false; static int writeLevel(char *buffer, logmask_t level); +void log_init(void) { + logOutStream = stdout; +} + bool log_hasMask(const logmask_t mask) { return ( ( maskFile | maskCon ) & mask ) == mask; @@ -63,6 +68,15 @@ void log_setConsoleTimestamps(bool on) consoleTimestamps = on; } +int log_setConsoleOutputStream(FILE *outputStream) +{ + if ( outputStream != stdout && outputStream != stderr ) + return -EINVAL; + + logOutStream = outputStream; + return 0; +} + bool log_openLogFile(const char *path) { pthread_mutex_lock( &logLock ); @@ -93,10 +107,10 @@ void logadd(const logmask_t mask, const char *fmt, ...) struct tm timeinfo; char buffer[LINE_LEN]; bool toFile = maskFile & mask; - bool toStdout = maskCon & mask; + bool toOutStream = maskCon & mask; size_t offset; - if ( toFile || ( toStdout && consoleTimestamps ) ) { + if ( toFile || ( toOutStream && consoleTimestamps ) ) { time( &rawtime ); localtime_r( &rawtime, &timeinfo ); offset = strftime( buffer, LINE_LEN, "[%d.%m. %H:%M:%S] ", &timeinfo ); @@ -134,15 +148,11 @@ void logadd(const logmask_t mask, const char *fmt, ...) } pthread_mutex_unlock( &logLock ); } - if ( toStdout ) { - if ( consoleTimestamps ) stdoutLine = buffer; -#ifdef DNBD3_SERVER_AFL - fputs( stdoutLine, stderr ); - fflush( stderr ); -#else - fputs( stdoutLine, stdout ); - fflush( stdout ); -#endif + if ( toOutStream ) { + if ( consoleTimestamps ) + stdoutLine = buffer; + fputs( stdoutLine, logOutStream ); + fflush( logOutStream ); } } -- cgit v1.2.3-55-g7522