Add hardening build options
This commit enables hardened-specific checks and codegen, inspired by GCC 14's -fhardened command line switch and LLVM/libc++'s hardened modes. We enable (depending on compiler capabilities): * -ftrivial-auto-var-init=pattern; * -fstack-protector-strong; * -fstack-clash-protection; * -fcf-protection=full or /CETCOMPAT; * -D_FORTIFY_SOURCE=3 or 2 on Glibc, depending on the Glibc version, provided that some optimization level is enabled (release build or optimized debug build); * on libstdc++, -D_GLIBCXX_ASSERTIONS; * on libc++, -D_LIBCPP_HARDENING_MODE set to _LIBCPP_HARDENING_MODE_EXTENSIVE in debug and to _LIBCPP_HARDENING_MODE_FAST in release (_DEBUG is too slow); * -Wl,-z,relro,-z,now. This aligns us 100% with -fhardened (we already pass -fPIE and -pie anyhow). Some Linux distributions already ship GCC/Clang with some of these options enabled by default. The check for Intel CET has been amended to always test if the compiler supports the corresponding flag; and, if so, enable the feature. Before, it was behind a configure option and the test only checked if the compiler had CET support automatically active (the test didn't pass -fcf-protection to the compiler). The check for -fstack-protector-strong has been made general (rather than QNX-specific). We don't support QNX < 7 anyhow. Finally, the qt_config_linker_supports_flag_test test has been amended to also support MSVC. All of the hardening options are enabled by default. [ChangeLog][Build System] Qt builds by default in "hardened mode", meaning that a series of security-related compiler options are automatically enabled. In the unlikely case in which these options constitute an unacceptable performance hit, it is possible to disable individual hardening options when configuring Qt. Change-Id: I2c026b0438010ad10d5e7b1136fedf4ae3af8822 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
a89a916377
commit
9ff1e6d80b
@ -1359,7 +1359,16 @@ function(qt_config_linker_supports_flag_test name)
|
||||
endif()
|
||||
|
||||
cmake_parse_arguments(arg "" "LABEL;FLAG" "" ${ARGN})
|
||||
set(flags "-Wl,${arg_FLAG}")
|
||||
if(GCC OR CLANG)
|
||||
set(flags "-Wl,--fatal-warnings,${arg_FLAG}")
|
||||
elseif(MSVC)
|
||||
set(flags "${arg_FLAG}")
|
||||
else()
|
||||
# We don't know how to pass linker options in a way that
|
||||
# it reliably fails, so assume the detection failed.
|
||||
set(TEST_${name} "0" CACHE INTERNAL "${label}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Pass the linker that the main project uses to the compile test.
|
||||
qt_internal_get_active_linker_flags(linker_flags)
|
||||
|
@ -316,18 +316,52 @@ if (GCC AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "9.2")
|
||||
target_compile_options(PlatformCommonInternal INTERFACE $<$<COMPILE_LANGUAGE:CXX>:-Wsuggest-override>)
|
||||
endif()
|
||||
|
||||
# Hardening options
|
||||
if(QT_FEATURE_intelcet)
|
||||
if(MSVC)
|
||||
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE
|
||||
-CETCOMPAT
|
||||
)
|
||||
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE -CETCOMPAT)
|
||||
else()
|
||||
target_compile_options(PlatformCommonInternal INTERFACE
|
||||
-fcf-protection=full
|
||||
)
|
||||
target_compile_options(PlatformCommonInternal INTERFACE -fcf-protection=full)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_glibc_fortify_source)
|
||||
set(is_optimized_build "$<OR:$<NOT:$<CONFIG:Debug>>,$<BOOL:${QT_FEATURE_optimize_debug}>>")
|
||||
# Some compilers may define _FORTIFY_SOURCE by default when optimizing, remove it
|
||||
# before defining our own
|
||||
target_compile_options(PlatformCommonInternal BEFORE INTERFACE "$<${is_optimized_build}:-U_FORTIFY_SOURCE>")
|
||||
if(TEST_glibc_234)
|
||||
target_compile_options(PlatformCommonInternal INTERFACE "$<${is_optimized_build}:-D_FORTIFY_SOURCE=3>")
|
||||
else()
|
||||
target_compile_options(PlatformCommonInternal INTERFACE "$<${is_optimized_build}:-D_FORTIFY_SOURCE=2>")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_trivial_auto_var_init_pattern)
|
||||
target_compile_options(PlatformCommonInternal INTERFACE -ftrivial-auto-var-init=pattern)
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_stack_protector)
|
||||
target_compile_options(PlatformCommonInternal INTERFACE -fstack-protector-strong)
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_stack_clash_protection)
|
||||
target_compile_options(PlatformCommonInternal INTERFACE -fstack-clash-protection)
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_libstdcpp_assertions)
|
||||
target_compile_definitions(PlatformCommonInternal INTERFACE _GLIBCXX_ASSERTIONS)
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_libcpp_hardening)
|
||||
target_compile_definitions(PlatformCommonInternal INTERFACE -D_LIBCPP_HARDENING_MODE="$<IF:$<CONFIG:Debug>,_LIBCPP_HARDENING_MODE_EXTENSIVE,_LIBCPP_HARDENING_MODE_FAST>")
|
||||
endif()
|
||||
|
||||
if(QT_FEATURE_relro_now_linker)
|
||||
qt_internal_platform_link_options(PlatformCommonInternal INTERFACE "-Wl,-z,relro,-z,now")
|
||||
endif()
|
||||
|
||||
|
||||
if(QT_FEATURE_force_asserts)
|
||||
target_compile_definitions(PlatformCommonInternal INTERFACE QT_FORCE_ASSERTS)
|
||||
endif()
|
||||
|
@ -138,7 +138,16 @@ Build options:
|
||||
|
||||
-pch ................. Use precompiled headers [auto]
|
||||
-ltcg ................ Use Link Time Code Generation [no]
|
||||
-intelcet ............ Use Intel Control-flow Enforcement Technology [no]
|
||||
-intelcet ............ Use Intel Control-flow Enforcement Technology [auto]
|
||||
-glibc-fortify-source Use Glibc function fortification [auto]
|
||||
-trivial-auto-var-init-pattern
|
||||
Use -ftrivial-auto-var-init=pattern [auto]
|
||||
-stack-protector ..... Use -fstack-protector-strong [auto]
|
||||
-stack-clash-protection
|
||||
Use -fstack-clash-protection [auto]
|
||||
-libstdcpp-assertions Use libstdc++ assertions [auto]
|
||||
-libcpp-hardening .... Use libc++ hardening [auto]
|
||||
-relro-now-linker .... Use -z relro -z now when linking [auto]
|
||||
-linker [bfd,gold,lld,mold]
|
||||
Force use of the GNU ld, GNU gold, LLVM/LLD or mold
|
||||
linker instead of default one (GCC and clang only)
|
||||
|
163
configure.cmake
163
configure.cmake
@ -211,6 +211,28 @@ endif()
|
||||
# machineTuple
|
||||
qt_config_compile_test_machine_tuple("machine tuple")
|
||||
|
||||
# glibc
|
||||
qt_config_compile_test(glibc
|
||||
LABEL "Using Glibc"
|
||||
CODE
|
||||
"#include <features.h>
|
||||
#ifndef __GLIBC__
|
||||
#error
|
||||
#endif
|
||||
int main() {}"
|
||||
)
|
||||
|
||||
# glibc 2.34, for _FORTIFY_SOURCE == 3
|
||||
qt_config_compile_test(glibc_234
|
||||
LABEL "Using Glibc >= 2.34"
|
||||
CODE
|
||||
"#include <features.h>
|
||||
#if !defined(__GLIBC__) || !__GLIBC_PREREQ(2, 34)
|
||||
#error
|
||||
#endif
|
||||
int main() {}"
|
||||
)
|
||||
|
||||
# cxx20
|
||||
qt_config_compile_test(cxx20
|
||||
LABEL "C++20 support"
|
||||
@ -398,29 +420,40 @@ alloca(1);
|
||||
")
|
||||
|
||||
# stack_protector
|
||||
qt_config_compile_test(stack_protector
|
||||
LABEL "stack protection"
|
||||
COMPILE_OPTIONS -fstack-protector-strong
|
||||
CODE
|
||||
"#ifdef __QNXNTO__
|
||||
# include <sys/neutrino.h>
|
||||
# if _NTO_VERSION < 700
|
||||
# error stack-protector not used (by default) before QNX 7.0.0.
|
||||
# endif
|
||||
#endif
|
||||
if(NOT WASM)
|
||||
# emcc doesn't support this, but the detection accidentally succeeds
|
||||
# https://github.com/emscripten-core/emscripten/issues/17030
|
||||
qt_config_compiler_supports_flag_test(stack_protector
|
||||
LABEL "stack protection"
|
||||
FLAG "-fstack-protector-strong"
|
||||
)
|
||||
endif()
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* BEGIN TEST: */
|
||||
/* END TEST: */
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
# stack_clash_protection
|
||||
if(NOT CLANG) # https://gitlab.kitware.com/cmake/cmake/-/issues/21998
|
||||
qt_config_compiler_supports_flag_test(stack_clash_protection
|
||||
LABEL "-fstack-clash-protection support"
|
||||
FLAG "-fstack-clash-protection"
|
||||
)
|
||||
endif()
|
||||
|
||||
# trivial_auto_var_init_pattern
|
||||
qt_config_compiler_supports_flag_test(trivial_auto_var_init_pattern
|
||||
LABEL "-ftrivial-auto-var-init=pattern support"
|
||||
FLAG "-ftrivial-auto-var-init=pattern"
|
||||
)
|
||||
|
||||
# intelcet
|
||||
qt_config_compile_test(intelcet
|
||||
LABEL "Support for Intel Control-flow Enforcement Technology (CET)"
|
||||
CODE
|
||||
if(MSVC)
|
||||
qt_config_linker_supports_flag_test(intelcet
|
||||
LABEL "Support for Intel Control-flow Enforcement Technology (CET)"
|
||||
FLAG "-CETCOMPAT"
|
||||
)
|
||||
else()
|
||||
qt_config_compile_test(intelcet
|
||||
LABEL "Support for Intel Control-flow Enforcement Technology (CET)"
|
||||
COMPILE_OPTIONS -fcf-protection=full
|
||||
CODE
|
||||
"int main(void)
|
||||
{
|
||||
/* BEGIN TEST: */
|
||||
@ -430,8 +463,35 @@ qt_config_compile_test(intelcet
|
||||
/* END TEST: */
|
||||
return 0;
|
||||
}
|
||||
")
|
||||
"
|
||||
)
|
||||
endif()
|
||||
|
||||
# -z relro -z now
|
||||
if(NOT WIN32)
|
||||
qt_config_linker_supports_flag_test(relro_now_linker
|
||||
LABEL "Support for -z relro and -z now"
|
||||
FLAG "-z,relro,-z,now"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Is libc++ the default Standard Library?
|
||||
qt_config_compile_test(using_stdlib_libcpp
|
||||
LABEL "Compiler defaults to libc++"
|
||||
CODE
|
||||
"
|
||||
#include <ciso646>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* BEGIN TEST: */
|
||||
#ifndef _LIBCPP_VERSION
|
||||
# error
|
||||
#endif
|
||||
/* END TEST: */
|
||||
}
|
||||
"
|
||||
)
|
||||
|
||||
|
||||
#### Features
|
||||
@ -889,10 +949,6 @@ qt_feature("alloca" PRIVATE
|
||||
LABEL "alloca()"
|
||||
CONDITION QT_FEATURE_alloca_h OR QT_FEATURE_alloca_malloc_h OR TEST_alloca_stdlib_h
|
||||
)
|
||||
qt_feature("stack-protector-strong" PRIVATE
|
||||
LABEL "stack protection"
|
||||
CONDITION QNX AND TEST_stack_protector
|
||||
)
|
||||
qt_feature("system-zlib" PRIVATE
|
||||
LABEL "Using system zlib"
|
||||
CONDITION WrapSystemZLIB_FOUND
|
||||
@ -1056,10 +1112,56 @@ qt_feature("relocatable" PRIVATE
|
||||
AUTODETECT QT_FEATURE_shared
|
||||
CONDITION QT_FEATURE_dlopen OR WIN32 OR NOT QT_FEATURE_shared
|
||||
)
|
||||
# hardening features
|
||||
qt_feature("intelcet" PRIVATE
|
||||
LABEL "Using Intel CET"
|
||||
CONDITION ( INPUT_intelcet STREQUAL yes ) OR TEST_intelcet
|
||||
LABEL "Using Intel Control-flow Enforcement Technology (CET)"
|
||||
AUTODETECT ON
|
||||
CONDITION TEST_intelcet
|
||||
)
|
||||
qt_feature_config("intelcet" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("glibc_fortify_source" PRIVATE
|
||||
LABEL "Using Glibc function fortification"
|
||||
AUTODETECT ON
|
||||
CONDITION TEST_glibc
|
||||
)
|
||||
qt_feature_config("glibc_fortify_source" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("trivial_auto_var_init_pattern" PRIVATE
|
||||
LABEL "Using -ftrivial-auto-var-init=pattern"
|
||||
AUTODETECT ON
|
||||
CONDITION TEST_trivial_auto_var_init_pattern
|
||||
)
|
||||
qt_feature_config("trivial_auto_var_init_pattern" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("stack_protector" PRIVATE
|
||||
LABEL "Using -fstack-protector-strong"
|
||||
AUTODETECT ON
|
||||
CONDITION TEST_stack_protector
|
||||
)
|
||||
qt_feature_config("stack_protector" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("stack_clash_protection" PRIVATE
|
||||
LABEL "Using -fstack-clash-protection"
|
||||
AUTODETECT ON
|
||||
CONDITION TEST_stack_clash_protection
|
||||
)
|
||||
qt_feature_config("stack_clash_protection" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("libstdcpp_assertions" PRIVATE
|
||||
LABEL "Using libstdc++ assertions"
|
||||
AUTODETECT ON
|
||||
CONDITION (GCC OR (CLANG AND NOT MSVC AND NOT QT_FEATURE_stdlib_libcpp AND NOT TEST_using_stdlib_libcpp))
|
||||
)
|
||||
qt_feature_config("libstdcpp_assertions" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("libcpp_hardening" PRIVATE
|
||||
LABEL "Using libc++ hardening"
|
||||
AUTODETECT ON
|
||||
CONDITION (QT_FEATURE_stdlib_libcpp OR TEST_using_stdlib_libcpp)
|
||||
)
|
||||
qt_feature_config("libcpp_hardening" QMAKE_PUBLIC_CONFIG)
|
||||
qt_feature("relro_now_linker" PRIVATE
|
||||
LABEL "Using -z relro -z now when linking"
|
||||
AUTODETECT ON
|
||||
CONDITION TEST_relro_now_linker
|
||||
)
|
||||
qt_feature_config("relro_now_linker" QMAKE_PUBLIC_CONFIG)
|
||||
|
||||
|
||||
if("${INPUT_coverage}" STREQUAL "gcov")
|
||||
qt_config_compile_test(gcov
|
||||
@ -1137,6 +1239,13 @@ qt_configure_add_summary_entry(ARGS "relocatable")
|
||||
qt_configure_add_summary_entry(ARGS "precompile_header")
|
||||
qt_configure_add_summary_entry(ARGS "ltcg")
|
||||
qt_configure_add_summary_entry(ARGS "intelcet")
|
||||
qt_configure_add_summary_entry(ARGS "glibc_fortify_source")
|
||||
qt_configure_add_summary_entry(ARGS "trivial_auto_var_init_pattern")
|
||||
qt_configure_add_summary_entry(ARGS "stack_protector")
|
||||
qt_configure_add_summary_entry(ARGS "stack_clash_protection")
|
||||
qt_configure_add_summary_entry(ARGS "libstdcpp_assertions")
|
||||
qt_configure_add_summary_entry(ARGS "libcpp_hardening")
|
||||
qt_configure_add_summary_entry(ARGS "relro_now_linker")
|
||||
qt_configure_add_summary_entry(
|
||||
ARGS "wasm-simd128"
|
||||
CONDITION ( TEST_architecture_arch STREQUAL wasm )
|
||||
|
@ -76,6 +76,13 @@ qt_commandline_option(openssl-runtime TYPE void NAME openssl VALUE runtime)
|
||||
qt_commandline_option(linker TYPE optionalString VALUES bfd gold lld mold)
|
||||
qt_commandline_option(ltcg TYPE boolean)
|
||||
qt_commandline_option(intelcet TYPE boolean)
|
||||
qt_commandline_option(glibc_fortify_source TYPE boolean)
|
||||
qt_commandline_option(trivial_auto_var_init_pattern TYPE boolean)
|
||||
qt_commandline_option(stack_protector TYPE boolean)
|
||||
qt_commandline_option(stack_clash_protection TYPE boolean)
|
||||
qt_commandline_option(libstdcpp_assertions TYPE boolean)
|
||||
qt_commandline_option(libcpp_hardening TYPE boolean)
|
||||
qt_commandline_option(relro_now_linker TYPE boolean)
|
||||
qt_commandline_option(make TYPE addString VALUES examples libs tests tools
|
||||
benchmarks manual-tests minimal-static-tests)
|
||||
qt_commandline_option(install-examples-sources TYPE boolean)
|
||||
|
Loading…
x
Reference in New Issue
Block a user