From f8d128be6e6e74a63f09e85bb1b6c058e9e676aa Mon Sep 17 00:00:00 2001 From: Ilya Verbin Date: Thu, 18 Aug 2022 13:46:49 +0300 Subject: [PATCH] cmake: add extra security compiler options Introduce cmake option ENABLE_HARDENING, which is TRUE by default for non-debug regular and static builds. It passess compiler flags that harden Tarantool (including the bundled libraries) against memory corruption attacks. The following flags are passed: * -Wformat - Check calls to printf and scanf, etc., to make sure that the arguments supplied have types appropriate to the format string specified. * -Wformat-security -Werror=format-security - Warn about uses of format functions that represent possible security problems. And make the warning into an error. * -fstack-protector-strong - Emit extra code to check for buffer overflows, such as stack smashing attacks. * -fPIC -pie - Generate position-independent code (PIC). It allows to take advantage of the Address Space Layout Randomization (ASLR). * -z relro -z now - Resolve all dynamically linked functions at the beginning of the execution, and then make the GOT read-only. Also do not disable hardening for Debian and RPM-based Linux distros. Closes #5372 Closes #7536 NO_DOC=build NO_TEST=build --- CMakeLists.txt | 9 ++++---- ...-7536-add-cmake-enable_hardening-option.md | 4 ++++ cmake/BuildAres.cmake | 4 ++-- cmake/BuildLibCURL.cmake | 11 ++++++---- cmake/BuildLibUnwind.cmake | 4 ++-- cmake/BuildNghttp2.cmake | 4 ++-- cmake/compiler.cmake | 18 +++++++++++++++ debian/rules | 1 - rpm/tarantool.spec | 3 --- static-build/CMakeLists.txt | 22 +++++++++++++++++++ 10 files changed, 62 insertions(+), 18 deletions(-) create mode 100644 changelogs/unreleased/gh-7536-add-cmake-enable_hardening-option.md diff --git a/CMakeLists.txt b/CMakeLists.txt index 165727a13a12..26298754fc0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -438,14 +438,14 @@ option(BUNDLED_LIBCURL_USE_NGHTTP2 "Build curl with bundled nghttp2" if (ENABLE_BUNDLED_LIBCURL) if(BUNDLED_LIBCURL_USE_ARES) include(BuildAres) - ares_build() + ares_build(${HARDENING_FLAGS}) endif() if(BUNDLED_LIBCURL_USE_NGHTTP2) include(BuildNghttp2) - nghttp2_build() + nghttp2_build(${HARDENING_FLAGS}) endif() include(BuildLibCURL) - curl_build() + curl_build(${HARDENING_FLAGS}) add_dependencies(build_bundled_libs bundled-libcurl) else() set(CURL_FIND_REQUIRED ON) @@ -522,7 +522,7 @@ if(ENABLE_BACKTRACE) endif() include(BuildLibUnwind) - libunwind_build() + libunwind_build(${HARDENING_FLAGS}) add_dependencies(build_bundled_libs bundled-libunwind bundled-libunwind-platform) @@ -744,6 +744,7 @@ set(options PACKAGE VERSION BUILD C_COMPILER CXX_COMPILER C_FLAGS CXX_FLAGS ENABLE_SSE2 ENABLE_AVX ENABLE_GCOV ENABLE_GPROF ENABLE_VALGRIND ENABLE_ASAN ENABLE_UB_SANITIZER ENABLE_FUZZER ENABLE_BACKTRACE + ENABLE_HARDENING ENABLE_DOC ENABLE_DIST ENABLE_BUNDLED_LIBCURL diff --git a/changelogs/unreleased/gh-7536-add-cmake-enable_hardening-option.md b/changelogs/unreleased/gh-7536-add-cmake-enable_hardening-option.md new file mode 100644 index 000000000000..573474d64ad2 --- /dev/null +++ b/changelogs/unreleased/gh-7536-add-cmake-enable_hardening-option.md @@ -0,0 +1,4 @@ +## feature/build + +* Added the `-DENABLE_HARDENING=ON/OFF` CMake option that enables hardening + against memory corruption attacks (gh-7536). diff --git a/cmake/BuildAres.cmake b/cmake/BuildAres.cmake index 46db51bc6065..5dc3584f4a81 100644 --- a/cmake/BuildAres.cmake +++ b/cmake/BuildAres.cmake @@ -1,11 +1,11 @@ # A macro to build the bundled libcares -macro(ares_build) +macro(ares_build CFLAGS) set(ARES_SOURCE_DIR ${PROJECT_SOURCE_DIR}/third_party/c-ares) set(ARES_BINARY_DIR ${PROJECT_BINARY_DIR}/build/ares/work) set(ARES_INSTALL_DIR ${PROJECT_BINARY_DIR}/build/ares/dest) # See BuildLibCURL.cmake for details. - set(ARES_CFLAGS "") + set(ARES_CFLAGS ${CFLAGS}) if (TARGET_OS_DARWIN AND NOT "${CMAKE_OSX_SYSROOT}" STREQUAL "") set(ARES_CFLAGS "${ARES_CFLAGS} ${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT}") endif() diff --git a/cmake/BuildLibCURL.cmake b/cmake/BuildLibCURL.cmake index c4a2e5acf5c4..99f1ead0fce4 100644 --- a/cmake/BuildLibCURL.cmake +++ b/cmake/BuildLibCURL.cmake @@ -1,9 +1,9 @@ # A macro to build the bundled libcurl -macro(curl_build) +macro(curl_build CFLAGS) set(LIBCURL_SOURCE_DIR ${PROJECT_SOURCE_DIR}/third_party/curl) set(LIBCURL_BINARY_DIR ${PROJECT_BINARY_DIR}/build/curl/work) set(LIBCURL_INSTALL_DIR ${PROJECT_BINARY_DIR}/build/curl/dest) - set(LIBCURL_CMAKE_FLAGS "") + set(LIBCURL_CFLAGS ${CFLAGS}) get_filename_component(FOUND_ZLIB_ROOT_DIR ${ZLIB_INCLUDE_DIR} DIRECTORY) list(APPEND LIBCURL_CMAKE_FLAGS "-DZLIB_ROOT=${FOUND_ZLIB_ROOT_DIR}") @@ -14,17 +14,19 @@ macro(curl_build) OUTPUT_VARIABLE OPENSSL_COMPILE_OPTIONS) # Add pthread library for openssl static library linking. if(NOT OPENSSL_COMPILE_OPTIONS MATCHES ".* -pthread .*") - list(APPEND LIBCURL_CMAKE_FLAGS "-DCMAKE_C_FLAGS=-pthread") + set(LIBCURL_CFLAGS "${LIBCURL_CFLAGS} -pthread") endif() # Add librt for clock_gettime function definition. if(${CMAKE_MAJOR_VERSION} VERSION_LESS "3") CHECK_LIBRARY_EXISTS (rt clock_gettime "" HAVE_LIBRT) if (HAVE_LIBRT) - list(APPEND LIBCURL_CMAKE_FLAGS "-DCMAKE_C_FLAGS=-lrt") + set(LIBCURL_CFLAGS "${LIBCURL_CFLAGS} -lrt") endif() endif() + list(APPEND LIBCURL_CMAKE_FLAGS "-DCMAKE_C_FLAGS=${LIBCURL_CFLAGS}") + # Switch on the static build. list(APPEND LIBCURL_CMAKE_FLAGS "-DCURL_STATICLIB=ON") @@ -243,6 +245,7 @@ macro(curl_build) unset(FOUND_ZLIB_ROOT_DIR) unset(FOUND_OPENSSL_ROOT_DIR) + unset(LIBCURL_CFLAGS) unset(LIBCURL_INSTALL_DIR) unset(LIBCURL_BINARY_DIR) unset(LIBCURL_SOURCE_DIR) diff --git a/cmake/BuildLibUnwind.cmake b/cmake/BuildLibUnwind.cmake index 741316b0ea38..750e6df6d045 100644 --- a/cmake/BuildLibUnwind.cmake +++ b/cmake/BuildLibUnwind.cmake @@ -18,12 +18,12 @@ Cache Variables The paths to the libunwind libraries. #]========================================================================] -macro(libunwind_build) +macro(libunwind_build CFLAGS) set(LIBUNWIND_SOURCE_DIR ${PROJECT_SOURCE_DIR}/third_party/libunwind) set(LIBUNWIND_BUILD_DIR ${PROJECT_BINARY_DIR}/build/libunwind) set(LIBUNWIND_BINARY_DIR ${LIBUNWIND_BUILD_DIR}/work) set(LIBUNWIND_INSTALL_DIR ${LIBUNWIND_BUILD_DIR}/dest) - set(LIBUNWIND_CFLAGS "-g -O2") + set(LIBUNWIND_CFLAGS "-g -O2 ${CFLAGS}") set(LIBUNWIND_CXXFLAGS "-g -O2") include(ExternalProject) diff --git a/cmake/BuildNghttp2.cmake b/cmake/BuildNghttp2.cmake index 864cd0bf1fd8..54c37137fa0c 100644 --- a/cmake/BuildNghttp2.cmake +++ b/cmake/BuildNghttp2.cmake @@ -1,12 +1,12 @@ # # A macro to build the bundled nghttp2 library. -macro(nghttp2_build) +macro(nghttp2_build CFLAGS) set(NGHTTP2_SOURCE_DIR ${PROJECT_SOURCE_DIR}/third_party/nghttp2) set(NGHTTP2_BINARY_DIR ${PROJECT_BINARY_DIR}/build/nghttp2/work) set(NGHTTP2_INSTALL_DIR ${PROJECT_BINARY_DIR}/build/nghttp2/dest) # See BuildLibCURL.cmake for details. - set(NGHTTP2_CFLAGS "") + set(NGHTTP2_CFLAGS ${CFLAGS}) if (TARGET_OS_DARWIN AND NOT "${CMAKE_OSX_SYSROOT}" STREQUAL "") set(NGHTTP2_CFLAGS "${NGHTTP2_CFLAGS} ${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT}") endif() diff --git a/cmake/compiler.cmake b/cmake/compiler.cmake index a5758c44de1b..1e6594c52dd6 100644 --- a/cmake/compiler.cmake +++ b/cmake/compiler.cmake @@ -211,6 +211,24 @@ option(ENABLE_WERROR "Make all compiler warnings into errors" OFF) option(ENABLE_UB_SANITIZER "Make the compiler generate runtime code to perform undefined behaviour checks" OFF) +# LuaJIT in FreeBSD doesn't work with PIC (gh-7640) +if (TARGET_OS_FREEBSD) + set(ENABLE_HARDENING_DEFAULT FALSE) +else() + set(ENABLE_HARDENING_DEFAULT TRUE) +endif() +option(ENABLE_HARDENING "Enable compiler options that harden against memory corruption attacks" ${ENABLE_HARDENING_DEFAULT}) +set(HARDENING_FLAGS " ") +set(HARDENING_LDFLAGS " ") +if (ENABLE_HARDENING) + set(HARDENING_FLAGS "-Wformat -Wformat-security -Werror=format-security -fstack-protector-strong -fPIC") + if (NOT TARGET_OS_DARWIN) + set(HARDENING_LDFLAGS "-pie -z relro -z now") + endif() + add_compile_flags("C;CXX" ${HARDENING_FLAGS}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${HARDENING_LDFLAGS}") +endif() + macro(enable_tnt_compile_flags) # Tarantool code is written in GNU C dialect. # Additionally, compile it with more strict flags than the rest diff --git a/debian/rules b/debian/rules index 5fbe7c9dac0a..45f4c4396335 100755 --- a/debian/rules +++ b/debian/rules @@ -37,7 +37,6 @@ DEB_DH_SYSTEMD_START_ARGS_tarantool-common := --no-restart-on-upgrade tarantool # Needed for proper backtraces in fiber.info() DEB_DH_STRIP_ARGS := -X/usr/bin/tarantool -export DEB_BUILD_MAINT_OPTIONS = hardening=-stackprotector DPKG_EXPORT_BUILDFLAGS = 1 include /usr/share/dpkg/buildflags.mk diff --git a/rpm/tarantool.spec b/rpm/tarantool.spec index 10aaf9945bca..9d76155e0542 100644 --- a/rpm/tarantool.spec +++ b/rpm/tarantool.spec @@ -91,9 +91,6 @@ BuildRequires: libunwind-devel %global debug_package %{nil} %global __os_install_post /usr/lib/rpm/brp-compress %{nil} %global __strip /bin/true -# -fPIE break backtraces -# https://github.com/tarantool/tarantool/issues/1262 -%undefine _hardened_build %endif # Set dependences for tests. diff --git a/static-build/CMakeLists.txt b/static-build/CMakeLists.txt index a067704df1e9..0584d54560ff 100644 --- a/static-build/CMakeLists.txt +++ b/static-build/CMakeLists.txt @@ -7,6 +7,7 @@ cmake_minimum_required(VERSION 3.1) # linux machine). project(tarantool-static C CXX) +include(FindPackageMessage) include(ExternalProject) set(LIBICU_VERSION release-71-1/icu4c-71_1) set(LIBICU_HASH e06ffc96f59762bd3c929b217445aaec) @@ -22,6 +23,8 @@ set(READLINE_VERSION 8.0) set(READLINE_HASH 7e6c1f16aee3244a69aba6e438295ca3) set(BACKUP_STORAGE https://distrib.hb.bizmrg.com) +include(../cmake/os.cmake) + # Pass -isysroot= option on Mac OS to a preprocessor and a C # compiler to find header files installed with an SDK. # @@ -43,6 +46,23 @@ if (APPLE) set(DEPENDENCY_CPPFLAGS "${CMAKE_C_SYSROOT_FLAG} ${CMAKE_OSX_SYSROOT}") endif() +# LuaJIT in FreeBSD doesn't work with PIC (gh-7640) +if (TARGET_OS_FREEBSD) + set(ENABLE_HARDENING_DEFAULT FALSE) +else() + set(ENABLE_HARDENING_DEFAULT TRUE) +endif() +option(ENABLE_HARDENING "Enable compiler options that harden against memory corruption attacks" ${ENABLE_HARDENING_DEFAULT}) +if (ENABLE_HARDENING) + set(HARDENING_FLAGS "-Wformat -Wformat-security -Werror=format-security -fstack-protector-strong -fPIC") + if (NOT TARGET_OS_DARWIN) + set(HARDENING_LDFLAGS "-pie -z relro -z now") + endif() + set(DEPENDENCY_CFLAGS "${DEPENDENCY_CFLAGS} ${HARDENING_FLAGS}") + set(DEPENDENCY_CXXFLAGS "${DEPENDENCY_CXXFLAGS} ${HARDENING_FLAGS}") + set(DEPENDENCY_LDFLAGS "${DEPENDENCY_LDFLAGS} ${HARDENING_LDFLAGS}") +endif() + # Install all libraries required by tarantool at current build dir # @@ -124,6 +144,7 @@ ExternalProject_Add(ncurses CXX=${CMAKE_CXX_COMPILER} CFLAGS=${DEPENDENCY_CFLAGS} CPPFLAGS=${DEPENDENCY_CPPFLAGS} + CXXFLAGS=${DEPENDENCY_CXXFLAGS} LDFLAGS=${DEPENDENCY_LDFLAGS} --prefix= @@ -237,6 +258,7 @@ ExternalProject_Add(tarantool -DBUILD_STATIC=TRUE -DENABLE_DIST=TRUE -DENABLE_BACKTRACE=TRUE + -DENABLE_HARDENING=${ENABLE_HARDENING} -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} ${CMAKE_TARANTOOL_ARGS}