Добавлены модули SafeStack и Control Flow Integrity
This commit is contained in:
parent
69437cd645
commit
26eced86d8
@ -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
31
cmake/FindCFI.cmake
Normal 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()
|
||||||
|
|
@ -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
24
cmake/FindSS.cmake
Normal 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()
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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 ()
|
||||||
|
Loading…
Reference in New Issue
Block a user