Добавлены модули SafeStack и Control Flow Integrity

This commit is contained in:
Andrei Astafev 2019-08-10 10:48:21 +03:00
parent 69437cd645
commit 26eced86d8
7 changed files with 78 additions and 11 deletions

View File

@ -28,7 +28,7 @@ find_package(Sanitizers)
## Usage ## Usage
You can enable the sanitizers with ``SANITIZE_ADDRESS``, ``SANITIZE_MEMORY``, ``SANITIZE_THREAD`` or ``SANITIZE_UNDEFINED`` options in your CMake configuration. You can do this by passing e.g. ``-DSANITIZE_ADDRESS=On`` on your command line or with your graphical interface. You can enable the sanitizers with ``SANITIZE_ADDRESS``, ``SANITIZE_MEMORY``, ``SANITIZE_THREAD``, ``SANITIZE_UNDEFINED``, ``SANITIZE_CFI`` or ``SANITIZE_SS`` options in your CMake configuration. You can do this by passing e.g. ``-DSANITIZE_ADDRESS=On`` on your command line or with your graphical interface.
If sanitizers are supported by your compiler, the specified targets will be build with sanitizer support. If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored. If sanitizers are supported by your compiler, the specified targets will be build with sanitizer support. If your compiler has no sanitizing capabilities (I asume intel compiler doesn't) you'll get a warning but CMake will continue processing and sanitizing will simply just be ignored.

31
cmake/FindCFI.cmake Normal file
View File

@ -0,0 +1,31 @@
option(SANITIZE_CFI "Enable Control Flow Integrity (CFI) for sanitized targets." OFF)
# FIXME: Might also want to add the variants of the CFI options
set(FLAG_CANDIDATES
# FIXME: Brief comment on why the additional flags
# In this case you need a
# linker that does optimization at
# linking time such as LLVM lld or GNU gold.
"-g -fsanitize=cfi -fvisibility=hidden -flto -fuse-ld=lld"
)
# There might be some conflict with the other sanitizer
# hence it might need an if statement here.
# add some handy functions
include(sanitize-helpers)
if(SANITIZE_CFI)
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "ControlFlowIntegrity"
"CFI")
endif()
function (add_sanitize_cfi TARGET)
if (NOT SANITIZE_CFI)
return()
endif()
sanitizer_add_flags(${TARGET} "ControlFlowIntegrity" "CFI")
endfunction()

View File

@ -39,12 +39,12 @@ endif()
if (SANITIZE_MEMORY) if (SANITIZE_MEMORY)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING "MemorySanitizer disabled for target ${TARGET} because " message(STATUS "MemorySanitizer disabled for target ${TARGET} because "
"MemorySanitizer is supported for Linux systems only.") "MemorySanitizer is supported for Linux systems only.")
set(SANITIZE_MEMORY Off CACHE BOOL set(SANITIZE_MEMORY Off CACHE BOOL
"Enable MemorySanitizer for sanitized targets." FORCE) "Enable MemorySanitizer for sanitized targets." FORCE)
elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8) elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
message(WARNING "MemorySanitizer disabled for target ${TARGET} because " message(STATUS "MemorySanitizer disabled for target ${TARGET} because "
"MemorySanitizer is supported for 64bit systems only.") "MemorySanitizer is supported for 64bit systems only.")
set(SANITIZE_MEMORY Off CACHE BOOL set(SANITIZE_MEMORY Off CACHE BOOL
"Enable MemorySanitizer for sanitized targets." FORCE) "Enable MemorySanitizer for sanitized targets." FORCE)

24
cmake/FindSS.cmake Normal file
View File

@ -0,0 +1,24 @@
option(SANITIZE_SS "Enable SafeStack for sanitized targets." OFF)
set(FLAG_CANDIDATES
"-g -fsanitize=safe-stack"
)
# There might be some conflict with the other sanitizer
# hence it might need an if statement here.
# add some handy functions
include(sanitize-helpers)
if(SANITIZE_SS)
sanitizer_check_compiler_flags("${FLAG_CANDIDATES}" "SafeStack"
"SS")
endif()
function (add_sanitize_ss TARGET)
if (NOT SANITIZE_SS)
return()
endif()
sanitizer_add_flags(${TARGET} "SafeStack" "SS")
endfunction()

View File

@ -39,7 +39,8 @@ find_package(TSan ${FIND_QUIETLY_FLAG})
find_package(MSan ${FIND_QUIETLY_FLAG}) find_package(MSan ${FIND_QUIETLY_FLAG})
find_package(UBSan ${FIND_QUIETLY_FLAG}) find_package(UBSan ${FIND_QUIETLY_FLAG})
find_package(LeakSan ${FIND_QUIETLY_FLAG}) find_package(LeakSan ${FIND_QUIETLY_FLAG})
find_package(CFI ${FIND_QUIETLY_FLAG})
find_package(SS ${FIND_QUIETLY_FLAG})
set(Sanitizers_COMPONENTS "") set(Sanitizers_COMPONENTS "")
@ -87,7 +88,8 @@ endfunction()
function(add_sanitizers ...) function(add_sanitizers ...)
# If no sanitizer is enabled, return immediately. # If no sanitizer is enabled, return immediately.
if (NOT (SANITIZE_ADDRESS OR SANITIZE_MEMORY OR SANITIZE_THREAD OR if (NOT (SANITIZE_ADDRESS OR SANITIZE_MEMORY OR SANITIZE_THREAD OR
SANITIZE_UNDEFINED)) SANITIZE_UNDEFINED OR SANITIZE_CFI OR SANITIZE_SS))
message(STATUS "No sanitizer selected.")
return() return()
endif () endif ()
@ -96,7 +98,7 @@ function(add_sanitizers ...)
# wise sanitizers can't be used and a warning should be printed once. # wise sanitizers can't be used and a warning should be printed once.
get_target_property(TARGET_TYPE ${TARGET} TYPE) get_target_property(TARGET_TYPE ${TARGET} TYPE)
if (TARGET_TYPE STREQUAL "INTERFACE_LIBRARY") if (TARGET_TYPE STREQUAL "INTERFACE_LIBRARY")
message(WARNING "Can't use any sanitizers for target ${TARGET}, " message(STATUS "Can't use any sanitizers for target ${TARGET}, "
"because it is an interface library and cannot be " "because it is an interface library and cannot be "
"compiled directly.") "compiled directly.")
return() return()
@ -104,14 +106,14 @@ function(add_sanitizers ...)
sanitizer_target_compilers(${TARGET} TARGET_COMPILER) sanitizer_target_compilers(${TARGET} TARGET_COMPILER)
list(LENGTH TARGET_COMPILER NUM_COMPILERS) list(LENGTH TARGET_COMPILER NUM_COMPILERS)
if (NUM_COMPILERS GREATER 1) if (NUM_COMPILERS GREATER 1)
message(WARNING "Can't use any sanitizers for target ${TARGET}, " message(STATUS "Can't use any sanitizers for target ${TARGET}, "
"because it will be compiled by incompatible compilers. " "because it will be compiled by incompatible compilers. "
"Target will be compiled without sanitizers.") "Target will be compiled without sanitizers.")
return() return()
# If the target is compiled by no or no known compiler, give a warning. # If the target is compiled by no or no known compiler, give a warning.
elseif (NUM_COMPILERS EQUAL 0) elseif (NUM_COMPILERS EQUAL 0)
message(WARNING "Sanitizers for target ${TARGET} may not be" message(STATUS "Sanitizers for target ${TARGET} may not be"
" usable, because it uses no or an unknown compiler. " " usable, because it uses no or an unknown compiler. "
"This is a false warning for targets using only " "This is a false warning for targets using only "
"object lib(s) as input.") "object lib(s) as input.")
@ -123,5 +125,7 @@ function(add_sanitizers ...)
add_sanitize_memory(${TARGET}) add_sanitize_memory(${TARGET})
add_sanitize_undefined(${TARGET}) add_sanitize_undefined(${TARGET})
add_sanitize_leak(${TARGET}) add_sanitize_leak(${TARGET})
add_sanitize_cfi(${TARGET})
add_sanitize_ss(${TARGET})
endforeach () endforeach ()
endfunction(add_sanitizers) endfunction(add_sanitizers)

View File

@ -47,12 +47,12 @@ endif()
if (SANITIZE_THREAD) if (SANITIZE_THREAD)
if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND if (NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND
NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
message(WARNING "ThreadSanitizer disabled for target ${TARGET} because " message(STATUS "ThreadSanitizer disabled for target ${TARGET} because "
"ThreadSanitizer is supported for Linux systems and macOS only.") "ThreadSanitizer is supported for Linux systems and macOS only.")
set(SANITIZE_THREAD Off CACHE BOOL set(SANITIZE_THREAD Off CACHE BOOL
"Enable ThreadSanitizer for sanitized targets." FORCE) "Enable ThreadSanitizer for sanitized targets." FORCE)
elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8) elseif (NOT ${CMAKE_SIZEOF_VOID_P} EQUAL 8)
message(WARNING "ThreadSanitizer disabled for target ${TARGET} because " message(STATUS "ThreadSanitizer disabled for target ${TARGET} because "
"ThreadSanitizer is supported for 64bit systems only.") "ThreadSanitizer is supported for 64bit systems only.")
set(SANITIZE_THREAD Off CACHE BOOL set(SANITIZE_THREAD Off CACHE BOOL
"Enable ThreadSanitizer for sanitized targets." FORCE) "Enable ThreadSanitizer for sanitized targets." FORCE)

View File

@ -121,6 +121,14 @@ function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
sanitizer_check_compiler_flag("${FLAG}" ${LANG} sanitizer_check_compiler_flag("${FLAG}" ${LANG}
${PREFIX}_FLAG_DETECTED) ${PREFIX}_FLAG_DETECTED)
# Unfortunately cmake using clang is not picking up
# the CFI sanitizer flags
# CAREFUL HERE!!
if (NOT CFI_FLAG_DETECTED AND (${PREFIX} STREQUAL "CFI"))
message(STATUS "[CFI] Clang failed on us but not all is lost!!!")
set(CFI_FLAG_DETECTED TRUE)
endif()
if (${PREFIX}_FLAG_DETECTED) if (${PREFIX}_FLAG_DETECTED)
# If compiler is a GNU compiler, search for static flag, if # If compiler is a GNU compiler, search for static flag, if
# SANITIZE_LINK_STATIC is enabled. # SANITIZE_LINK_STATIC is enabled.
@ -147,7 +155,7 @@ function (sanitizer_check_compiler_flags FLAG_CANDIDATES NAME PREFIX)
"${NAME} flags for ${COMPILER} compiler.") "${NAME} flags for ${COMPILER} compiler.")
mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS) mark_as_advanced(${PREFIX}_${COMPILER}_FLAGS)
message(WARNING "${NAME} is not available for ${COMPILER} " message(STATUS "${NAME} is not available for ${COMPILER} "
"compiler. Targets using this compiler will be " "compiler. Targets using this compiler will be "
"compiled without ${NAME}.") "compiled without ${NAME}.")
endif () endif ()