diff --git a/CMakeLists.txt b/CMakeLists.txt index b848915c..31e72449 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,18 +10,12 @@ cmake_minimum_required(VERSION 3.15) # Set before the first project() command. set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Type of build to perform") -# Include before the project() command. -set(ENABLE_PIE_FLAG OFF) -set(ENABLE_SANITIZE_CFI OFF) -set(ENABLE_SPECTRE_FLAGS OFF) -include(cmake/CompilerFlags.cmake) -define_compiler_init_variables() - project(networking-recipe VERSION 23.07 LANGUAGES C CXX) list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) include(CMakePrintHelpers) +include(CompilerSettings) include(CTest) include(FindPkgConfig) include(GNUInstallDirs) @@ -66,7 +60,6 @@ include(SelectTdiTarget) ################### option(SET_RPATH "Set RPATH in libraries and executables" OFF) - option(WITH_KRNLMON "Enable Kernel Monitor support" ON) option(WITH_OVSP4RT "Enable OVS support" ON) @@ -78,9 +71,12 @@ endif() cmake_print_variables(WITH_KRNLMON) cmake_print_variables(WITH_OVSP4RT) -########################### -# Global compiler options # -########################### +############################ +# Global compiler settings # +############################ + +add_basic_settings() +add_security_settings(${CMAKE_BUILD_TYPE}) add_compile_options(-D${TARGETFLAG}) @@ -92,8 +88,6 @@ if(NOT DEPEND_INSTALL_DIR STREQUAL "") endif() endif() -set(CMAKE_POSITION_INDEPENDENT_CODE ON) - ############################ # find_xxxx() search paths # ############################ diff --git a/cmake/CompilerFlags.cmake b/cmake/CompilerFlags.cmake deleted file mode 100644 index 7bab5a06..00000000 --- a/cmake/CompilerFlags.cmake +++ /dev/null @@ -1,262 +0,0 @@ -# CompilerFlags.cmake - Set recommended compiler flags. -# -# Copyright 2023 Intel Corporation -# SPDX-License-Identifier: Apache 2.0 -# - -include(CMakePrintHelpers) - -option(ENABLE_WARNING_FLAGS "Enable compiler warnings" OFF) -option(ENABLE_PIE_FLAG "Enable position independent executables" ON) -option(ENABLE_SANITIZE_CFI "Enable -sanitize=cfi" ON) -option(ENABLE_SPECTRE_FLAGS "Enable Spectre mitigations" ON) - -#----------------------------------------------------------------------- -# Get list of security flags. -# -# Each macro implements a section of the C & C++ Compiler Flag Standards -# in the Intel Secure Coding Standards. -#----------------------------------------------------------------------- -function(_get_security_flags_list config cflags) - - # Compiler Warnings and Error Detection - macro(setCompilerWarnings config cflags) - if(${config} STREQUAL "Debug") - list(APPEND ${cflags} - -Wall - -Wextra - ) - else() - list(APPEND ${cflags} - -Wall - -Wextra - -Werror - ) - endif() - endmacro() - - # Control Flow Integrity - macro(setFlowIntegrity config cflags) - if(ENABLE_SANITIZE_CFI) - list(APPEND ${cflags} -fsanitize=cfi) - endif() - - if(NOT ${config} STREQUAL "Debug") - list(APPEND ${cflags} - -flto # link-time optimization - -fvisibility=hidden # all ELF symbols are hidden by default - ) - endif() - endmacro() - - # Format String Defense - macro(setFormatDefense config cflags) - if(${config} STREQUAL "Debug") - list(APPEND ${cflags} - -Wformat - -Wformat-security - ) - else() - list(APPEND ${cflags} - -Wformat - -Wformat-security - -Werror=format-security - ) - endif() - endmacro() - - # Inexecutable Stack - macro(setStackDefense config cflags) - if(NOT ${config} STREQUAL "Debug") - list(APPEND ${cflags} - # passed to linker - # -z noexecstack - -Wl,-z,noexecstack - ) - endif() - endmacro() - - # Position Independent Execution - macro(setPIE config cflags) - list(APPEND ${cflags} - # passed to compiler - -fPIE - # passed to linker - -pie - ) - endmacro() - - # Preprocessor Macros - macro(setFortfy config cflags) - list(APPEND ${cflags} - -D_FORTIFY_FLAGS=2 - ) - endmacro() - - # Read-only Relocation - macro(setRelocation config cflags) - if(NOT ${config} STREQUAL "Release") - list(APPEND ${cflags} - # passed to linker - -Wl,-z,relro - ) - endif() - endmacro() - - # Bounds Check Bypass (Spectre Variant 1) - macro(setBoundsCheck config cflags) - list(APPEND ${cflags} - -mconditional-branch=keep - -mconditional-branch=pattern-report - -mconditonal-branch=pattern-fix - ) - endmacro() - - # Branch Target Injection (Spectre Variant 2) - macro(setTargetInjection config cflags) - list(APPEND ${cflags} - -mretpoline - ) - endmacro() - - set(_cflags) - set(_mode ${config}) - - if(ENABLE_WARNING_FLAGS) - setCompilerWarnings(config _cflags) - endif() - - setFlowIntegrity(config _cflags) - setFormatDefense(config _cflags) - setStackDefense(config _cflags) - if(ENABLE_PIE_FLAG) - setPIE(config _cflags) - endif() - setRelocation(config _cflags) - - if(ENABLE_SPECTRE_FLAGS) - setBoundsCheck(config _cflags) - setTargetInjection(config _cflags) - endif() - - set(${cflags} ${_cflags} PARENT_SCOPE) - -endfunction(_get_security_flags_list) - -#----------------------------------------------------------------------- -# Get extra compiler and linker flags. -#----------------------------------------------------------------------- -function(_get_extra_compiler_flags CFLAGS LDFLAGS) - - # Compiler flags - string(JOIN " " cflags - -pipe - -feliminate-unused-debug-types - ) - - # Linker Flags - string(JOIN " " ldflags - -Wl,-O1 - -Wl,--hash-style=gnu - -Wl,--as-needed - -Wl,-z,now - ) - - set(${CFLAGS} ${cflags} PARENT_SCOPE) - set(${LDFLAGS} ${ldflags} PARENT_SCOPE) - -endfunction(_get_extra_compiler_flags) - -#----------------------------------------------------------------------- -# Define SECURITY_FLAGS_ variables. -#----------------------------------------------------------------------- -function(define_security_flags_variables) - foreach(config Debug Release) - _get_security_flags_list(${config} flagsList) - - # SECURITY_FLAGS__LIST - string(TOUPPER ${config} CONFIG) - set(SECURITY_FLAGS_${CONFIG}_LIST "${flagsList}" CACHE STRING - "List of security flags for ${CONFIG} builds") - - # SECURITY_FLAGS_ - list(JOIN flagsList " " flags) - set(SECURITY_FLAGS_${CONFIG} "${flags}" CACHE STRING - "Security flags for ${CONFIG} builds") - endforeach() -endfunction(define_security_flags_variables) - -set(_COMPILER_FLAGS_CONFIGS DEBUG MINSIZEREL RELEASE RELWITHDEBINFO) -set(_COMPILER_FLAGS_RELEASE_CONFIGS MINSIZEREL RELEASE RELWITHDEBINFO) - -#----------------------------------------------------------------------- -# Define compiler and linker INIT variables. -#----------------------------------------------------------------------- -function(define_compiler_init_variables) - # These are the built-in defaults. - set(default_flags_DEBUG "-g") - set(default_flags_MINSIZEREL "-Os -DNDEBUG") - set(default_flags_RELEASE "-O3 -DNDEBUG") - set(default_flags_RELWITHDEBINFO "-O2 -g -DNDEBUG") - - _get_extra_compiler_flags(CFLAGS LDFLAGS) - - foreach(LANG C CXX) - # CMAKE__FLAGS_DEBUG_INIT - # Uses the DEBUG security flags. - set(VAR "CMAKE_${LANG}_FLAGS_DEBUG_INIT") - string(JOIN " " VALUE - "${default_flags_DEBUG}" - "${CFLAGS}" - "${SECURITY_FLAGS_DEBUG}") - set(${VAR} "${VALUE}" CACHE STRING "") - mark_as_advanced(${VAR}) - - # CMAKE__FLAGS__INIT - # These configs all use the RELEASE security flags. - foreach(CONFIG ${_COMPILER_FLAGS_RELEASE_CONFIGS}) - set(VAR CMAKE_${LANG}_FLAGS_${CONFIG}_INIT) - string(JOIN " " VALUE - "${default_flags_${CONFIG}}" - "${CFLAGS}" - "${SECURITY_FLAGS_RELEASE}") - set(${VAR} "${VALUE}" CACHE STRING "") - mark_as_advanced(${VAR}) - endforeach() - endforeach() - - # CMAKE__LINKER_FLAGS__INIT - foreach(CONFIG ${_COMPILER_FLAGS_CONFIGS}) - foreach(TYPE EXE SHARED) - set(VAR CMAKE_${TYPE}_LINKER_FLAGS_${CONFIG}_INIT) - set(${VAR} "${LDFLAGS}" CACHE STRING "") - mark_as_advanced(${VAR}) - endforeach() - endforeach() -endfunction(define_compiler_init_variables) - -#----------------------------------------------------------------------- -# Print compiler flags variables -#----------------------------------------------------------------------- -function(print_security_flags_variables) - foreach(CONFIG DEBUG RELEASE) - cmake_print_variables(SECURITY_FLAGS_${CONFIG}_LIST) - endforeach() -endfunction() - -function(print_compiler_init_variables LANG) - foreach(CONFIG ${_COMPILER_FLAGS_CONFIGS}) - cmake_print_variables(CMAKE_${LANG}_FLAGS_${CONFIG}_INIT) - endforeach() -endfunction() - -function(print_compiler_flags_variables LANG) - foreach(CONFIG ${_COMPILER_FLAGS_CONFIGS}) - cmake_print_variables(CMAKE_${LANG}_FLAGS_${CONFIG}) - endforeach() -endfunction() - -#----------------------------------------------------------------------- -# Define variables -#----------------------------------------------------------------------- -define_security_flags_variables() diff --git a/cmake/CompilerSettings.cmake b/cmake/CompilerSettings.cmake new file mode 100644 index 00000000..2d7f3335 --- /dev/null +++ b/cmake/CompilerSettings.cmake @@ -0,0 +1,98 @@ +# CompilerSettings.cmake - Apply recommended compiler settings. +# +# Copyright 2023 Intel Corporation +# SPDX-License-Identifier: Apache 2.0 +# + +include(CheckCCompilerFlag) +include(CheckPIESupported) +include(CMakePrintHelpers) + +# Disabled by default, on the assumption that the choice of warnings +# is best left to the application. +option(ENABLE_WARNING_SETTINGS "Enable compiler warnings" OFF) +option(ENABLE_SPECTRE_SETTINGS "Enable Spectre mitigations" ON) + +function(add_basic_settings) + # Compiler flags + add_compile_options("-pipe") + add_compile_options("-feliminate-unused-debug-types") + + # Linker flags + add_link_options("-Wl,-O1") + add_link_options("-Wl,--hash-style=gnu") + add_link_options("-Wl,--as-needed") + add_link_options("-Wl,-z,now") +endfunction(add_basic_settings) + +function(add_security_settings CONFIG) + string(TOUPPER ${CONFIG} CONFIG) + if(CONFIG STREQUAL "DEBUG") + set(IS_RELEASE FALSE) + else() + set(IS_RELEASE TRUE) + endif() + + macro(check_and_add_option OPTION HAVE_FLAG) + check_c_compiler_flag(${OPTION} ${HAVE_FLAG}) + if(${HAVE_FLAG}) + add_compile_options(${OPTION}) + endif() + endmacro() + + # Compiler Warnings and Error Detection + if(ENABLE_WARNING_SETTINGS) + add_compile_options("-Wall") + add_compile_options("-Wextra") + if(IS_RELEASE) + add_compile_options("-Werror") + endif() + endif() + + # Control Flow Integrity + check_and_add_option("-fsanitize=cfi" HAVE_SANITIZE_CFI) + if(IS_RELEASE) + check_and_add_option("-flto" HAVE_LTO) + check_and_add_option("-fvisibility=hidden" HAVE_VISIBILITY_HIDDEN) + endif() + + # Format String Defense + check_and_add_option("-Wformat" HAVE_WFORMAT) + check_and_add_option("-Wformat-security" HAVE_WFORMAT_SECURITY) + if(IS_RELEASE) + check_and_add_option( + "-Werror=format-security" FLAGS_WERROR_FORMAT_SECURITY) + endif() + + # Inexecutable Stack + check_and_add_option("-Wl,-z,noexecstack" HAVE_NOEXECSTACK) + + # Position Independent Code + set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) + + # Position Independent Execution + check_pie_supported(LANGUAGES C CXX) + if(CMAKE_C_PIE_SUPPORTED AND CMAKE_CXX_PIE_SUPPORTED) + add_compile_options("-fPIE -pie") + endif() + + # Preprocessor Macros + add_compile_definitions("FORTIFY_SOURCE=2") + + # Read-only Relocation + check_and_add_option("-Wl,-z,relro" HAVE_RELRO) + + # Spectre Protection + if(IS_RELEASE AND ENABLE_SPECTRE_SETTINGS) + # Mitigating Bounds Check Bypass (Spectre Variant 1) + check_and_add_option( + "-mconditional-branch=keep" HAVE_COND_BRANCH_KEEP) + check_and_add_option( + "-mconditional-branch=pattern-report" HAVE_COND_BRANCH_PATTERN_REPORT) + check_and_add_option( + "-mconditional-branch=pattern-fix" HAVE_COND_BRANCH_PATTERN_FIX) + + # Mitigating Branch Target Injection (Spectre Variant 2) + check_and_add_option("-mretpoline" HAVE_RETPOLINE) + endif() +endfunction(add_security_settings)