diff --git a/CMakeLists.txt b/CMakeLists.txt index 2428ba2..622bda7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,17 +3,8 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(ENV{TARGET} "x86_64-linux-gnu") -set(CMAKE_CXX_FLAGS "-Wall -fvisibility=hidden -fvisibility-inlines-hidden -Wformat -Wformat-security -rdynamic") -set(CMAKE_CXX_FLAGS_DEBUG "-g2 -O0") -set(CMAKE_CXX_FLAGS_RELEASE - "-fstack-protector-all -Wl,-z,relro,-z,now -Wl,-z,noexecstack -s -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -O3 -g2 -march=native -pipe -flto=auto" -) - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -enable_testing() - execute_process( - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/version.sh + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/scripts/versioning.sh WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE MQTTD_VERSION) @@ -22,6 +13,9 @@ project( VERSION ${MQTTD_VERSION} LANGUAGES CXX) +list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") +enable_testing() + add_subdirectory(src) add_subdirectory(tests) add_subdirectory(docs) diff --git a/cmake/SetCompileOptions.cmake b/cmake/SetCompileOptions.cmake new file mode 100644 index 0000000..17fbc48 --- /dev/null +++ b/cmake/SetCompileOptions.cmake @@ -0,0 +1,173 @@ +# Função para verificar se uma flag do compilador é suportada e retornar essa flag +function(check_compiler_flag flag required result_var) + string(REPLACE "-" "_" flag_var "${flag}") + string(TOUPPER "${flag_var}" flag_var) # Converter para maiúsculas para evitar problemas de case sensitivity + + # Verifique se a flag é suportada pelo compilador + check_cxx_compiler_flag("${flag}" "HAVE_${flag_var}_SUPPORT") + if(${HAVE_${flag_var}_SUPPORT}) + set(${result_var} + ${flag} + PARENT_SCOPE) + else() + if(required) + message(FATAL_ERROR "O compilador não suporta a flag obrigatória ${flag}") + else() + set(${result_var} + "" + PARENT_SCOPE) + endif() + endif() +endfunction() + +# Função para verificar se uma flag do linker é suportada e retornar essa flag +function(check_linker_flag flag required result_var) + string(REPLACE "-" "_" flag_var "${flag}") + string(TOUPPER "${flag_var}" flag_var) # Converter para maiúsculas para evitar problemas de case sensitivity + + # Verifique se a flag é suportada pelo compilador (usando o linker) + check_cxx_compiler_flag("${flag}" "HAVE_${flag_var}_SUPPORT" LINKER) + if(${HAVE_${flag_var}_SUPPORT}) + set(${result_var} + ${flag} + PARENT_SCOPE) + else() + if(required) + message(FATAL_ERROR "O linker não suporta a flag obrigatória ${flag}") + else() + set(${result_var} + "" + PARENT_SCOPE) + endif() + endif() +endfunction() + +# Função para filtrar flags de compilador/linker não suportadas +function(filter_unsupported_flags flags_var check_linker_flag) + # Lista temporária para armazenar flags suportadas + set(supported_flags) + + # Itera sobre a lista de flags + foreach(flag ${${flags_var}}) + if(check_linker_flag) + check_linker_flag(${flag} FALSE supported_flag) + else() + check_compiler_flag(${flag} FALSE supported_flag) + endif() + + # Verifique e adicione as flags suportadas + if(NOT "${supported_flag}" STREQUAL "") + list(APPEND supported_flags ${supported_flag}) + endif() + endforeach() + + # Atualiza a variável original com a lista filtrada + set(${flags_var} + ${supported_flags} + PARENT_SCOPE) +endfunction() + +set(C_COMPILE_FLAGS + # Enable warnings for constructs often associated with defects + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-additional-format-function-warnings + -Wall + -Wextra + # Enable additional format function warnings + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-additional-format-function-warnings + -Wformat + -Wformat-security + # Enable implicit conversion warnings + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-implicit-conversion-warnings + -Wconversion + -Wsign-conversion + # Enable warning about trampolines that require executable stacks + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-warning-about-trampolines-that-require-executable-stacks + -Wtrampolines + # Warn about implicit fallthrough in switch statements + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#warn-about-implicit-fallthrough-in-switch-statements + -Wimplicit-fallthrough) + +set(CXX_COMPILE_FLAGS # Flags enabled only for CPP + # Do not delete null pointer checks + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#do-not-delete-null-pointer-checks + -fno-delete-null-pointer-checks + # Integer overflow may occur + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#integer-overflow-may-occur + -fno-strict-overflow + # Do not assume strict aliasing + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#do-not-assume-strict-aliasing + -fno-strict-aliasing + # Perform trivial auto variable initialization + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#perform-trivial-auto-variable-initialization + -ftrivial-auto-var-init=zero + # Enable exception propagation to harden multi-threaded C code + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-exception-propagation-to-harden-multi-threaded-c-code + -fexceptions) + +# Flags enabled only on Release Mode +set(RELEASE_COMPILE_FLAGS + # Keeps only relevant symbols available to the library users + -fvisibility=hidden + -fvisibility-inlines-hidden + -ffunction-sections + -fdata-sections + # Enable code instrumentation of control-flow transfers to increase program security by checking that target addresses of + # control-flow transfer instructions are valid + # https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fcf-protection + -fcf-protection=full + # Enable run-time checks for stack-based buffer overflows + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-run-time-checks-for-stack-based-buffer-overflows + -fstack-protector-strong + # Build as position-independent code + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#build-as-position-independent-code + -pie + -fPIE + # Enable run-time checks for variable-size stack allocation validity + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-run-time-checks-for-variable-size-stack-allocation-validity + -fstack-clash-protection + # Enable strict flexible arrays + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-strict-flexible-arrays + -fstrict-flex-arrays=3 + # Precondition checks for C++ standard library calls + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#precondition-checks-for-c-standard-library-calls + -D_GLIBCXX_ASSERTIONS + # Mark relocation table entries resolved at load-time as read-only + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#mark-relocation-table-entries-resolved-at-load-time-as-read-only + -Wl,-z,relro,-z,now + # Enable data execution prevention + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#enable-data-execution-prevention + -Wl,-z,noexecstack + # Restrict dlopen calls to shared objects + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#restrict-dlopen-calls-to-shared-objects + -Wl,-z,nodlopen + -s + # Fortify sources for unsafe libc usage and buffer overflows + # https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#fortify-sources-for-unsafe-libc-usage-and-buffer-overflows + -U_FORTIFY_SOURCE + -D_FORTIFY_SOURCE=3 + -O2 + -DNDEBUG) + +# Flags enabled only on Debug Mode +set(DEBUG_COMPILE_FLAGS -g3 -Og -fno-omit-frame-pointer -fno-optimize-sibling-calls -fno-common) + +filter_unsupported_flags(C_COMPILE_FLAGS OFF) +filter_unsupported_flags(CXX_COMPILE_FLAGS OFF) +filter_unsupported_flags(RELEASE_COMPILE_FLAGS OFF) +filter_unsupported_flags(DEBUG_COMPILE_FLAGS OFF) + +include(SetSanitizers) + +set(COMPILE_FLAGS ${C_COMPILE_FLAGS}) + +if(CMAKE_CXX_COMPILER) + list(APPEND COMPILE_FLAGS ${CXX_COMPILE_FLAGS}) +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Release") + list(APPEND COMPILE_FLAGS ${RELEASE_COMPILE_FLAGS}) +elseif(CMAKE_BUILD_TYPE STREQUAL "Debug") + list(APPEND COMPILE_FLAGS ${DEBUG_COMPILE_FLAGS}) + list(APPEND COMPILE_FLAGS ${SANITIZE_FLAGS}) + set(LINK_FLAGS ${SANITIZE_FLAGS}) +endif() diff --git a/cmake/SetSanitizers.cmake b/cmake/SetSanitizers.cmake new file mode 100644 index 0000000..50d6015 --- /dev/null +++ b/cmake/SetSanitizers.cmake @@ -0,0 +1,27 @@ +include(CheckCXXCompilerFlag) + +# Flag para o AddressSanitizer +set(CMAKE_REQUIRED_FLAGS "-fsanitize=address") +check_cxx_compiler_flag("-fsanitize=address" COMPILER_SUPPORTS_ASAN) +if(COMPILER_SUPPORTS_ASAN) + set(SANITIZE_FLAGS ${SANITIZE_FLAGS} -fsanitize=address) +endif() + +# Flag para o UndefinedBehaviorSanitizer +set(CMAKE_REQUIRED_FLAGS "-fsanitize=undefined") +check_cxx_compiler_flag("-fsanitize=undefined" COMPILER_SUPPORTS_UBSAN) +if(COMPILER_SUPPORTS_UBSAN) + set(SANITIZE_FLAGS ${SANITIZE_FLAGS} -fsanitize=undefined) +endif() + +# Flag para o UndefinedBehaviorSanitizer +set(CMAKE_REQUIRED_FLAGS "-fsanitize=leak") +check_cxx_compiler_flag("-fsanitize=leak" COMPILER_SUPPORTS_LSAN) +if(COMPILER_SUPPORTS_LSAN) + set(SANITIZE_FLAGS ${SANITIZE_FLAGS} -fsanitize=leak) +endif() + +# Limpa as flags temporárias +unset(CMAKE_REQUIRED_FLAGS) + +mark_as_advanced(SANITIZE_FLAGS) diff --git a/version.sh b/scripts/versioning.sh similarity index 91% rename from version.sh rename to scripts/versioning.sh index c2f51ab..d34e247 100755 --- a/version.sh +++ b/scripts/versioning.sh @@ -1,5 +1,6 @@ #!/bin/bash set -e + VERSION_FILE="$(pwd)/src/version.hpp" MAJOR=$(grep -oP 'MQTTD_VERSION_MAJOR \K[0-9]+' "$VERSION_FILE") @@ -33,9 +34,8 @@ sed -i "s/MQTTD_VERSION_PATCH [0-9]\+/MQTTD_VERSION_PATCH $PATCH/" "$VERSION_FIL # Atualizar informações de compilação COMMIT_HASH=$(git rev-parse HEAD) BUILD_TIMESTAMP=$(date +%s) -sed -i "s/MQTTD_COMMIT_HASH [a-zA-Z0-9]\+/MQTTD_COMMIT_HASH $COMMIT_HASH/" "$VERSION_FILE" +sed -i "s/MQTTD_COMMIT_HASH \"[a-zA-Z0-9]\+\"/MQTTD_COMMIT_HASH \"$COMMIT_HASH\"/" "$VERSION_FILE" sed -i "s/MQTTD_BUILD_TIMESTAMP [0-9]\+/MQTTD_BUILD_TIMESTAMP $BUILD_TIMESTAMP/" "$VERSION_FILE" # Exibir versão atualizada printf "%d.%d.%d" "$MAJOR" "$MINOR" "$PATCH" - diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8f73d60..aa17a83 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -8,6 +8,10 @@ add_executable(mqttd mqttd.cpp) target_link_libraries(mqttd PRIVATE libcore libmqttd spdlog cpptrace::cpptrace) target_include_directories(mqttd PUBLIC "${PROJECT_BINARY_DIR}") +include(SetCompileOptions) +target_compile_options(mqttd PRIVATE "${COMPILE_FLAGS}") +target_link_options(mqttd PRIVATE "${LINK_FLAGS}") + add_executable(mqttd_stacktracer mqttd_stacktracer.cpp) target_link_libraries(mqttd_stacktracer PRIVATE cpptrace::cpptrace) target_include_directories(mqttd_stacktracer PUBLIC "${PROJECT_BINARY_DIR}") diff --git a/src/libmqttd/network/connection/connect_packet.hpp b/src/libmqttd/network/connection/connect_packet.hpp index 84f2168..1cce679 100644 --- a/src/libmqttd/network/connection/connect_packet.hpp +++ b/src/libmqttd/network/connection/connect_packet.hpp @@ -17,7 +17,7 @@ * These flags are used to control the behavior of the connection attempt. */ enum ConnectFlags : uint16_t { - RESERVERD = 0, /**< Reserved flag. */ + RESERVED = 0, /**< Reserved flag. */ CLEAN_START = 1, /**< Clean start flag. */ WILL_FLAG = 2, /**< Will flag. */ WILL_QOS = 3, /**< Will QoS flag. */ diff --git a/src/mqttd.cpp b/src/mqttd.cpp index 4ae9621..ffd015b 100644 --- a/src/mqttd.cpp +++ b/src/mqttd.cpp @@ -1,3 +1,4 @@ +#include "spdlog/common.h" #include "version.hpp" #include #include @@ -45,7 +46,7 @@ void send_trace(cpptrace::frame_ptr *buffer, std::size_t size) { void termination_handler(int signal_num) { spdlog::info("Received signal " + std::string(strsignal(signal_num))); - std::set backtrace_signals = {SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGABRT, SIGTRAP}; + std::set backtrace_signals = {SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGABRT, SIGTRAP}; auto is_backtrace_signal = backtrace_signals.find(signal_num); if (is_backtrace_signal != backtrace_signals.end()) { @@ -61,7 +62,7 @@ void termination_handler(int signal_num) { } void set_signal_handlers() { - std::set termination_signals = {SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSYS, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTRAP}; + std::set termination_signals = {SIGILL, SIGBUS, SIGFPE, SIGSEGV, SIGSYS, SIGABRT, SIGHUP, SIGINT, SIGQUIT, SIGTERM, SIGTRAP}; // Blocking signals with set sigset_t block_mask; @@ -89,7 +90,9 @@ void warmup_cpptrace() { } int main() { - std::cout << "MQTTd Version " << MQTTD_VERSION_MAJOR << "." << MQTTD_VERSION_MINOR << "." << MQTTD_VERSION_PATCH << std::endl; + spdlog::set_level(spdlog::level::level_enum::trace); + std::cout << "MQTTd Version " << VERSION << std::endl; + cpptrace::absorb_trace_exceptions(false); cpptrace::register_terminate_handler(); cpptrace::enable_inlined_call_resolution(true); diff --git a/src/version.hpp b/src/version.hpp index a70b7f4..87b1294 100644 --- a/src/version.hpp +++ b/src/version.hpp @@ -1,5 +1,10 @@ #define MQTTD_VERSION_MAJOR 0 #define MQTTD_VERSION_MINOR 0 #define MQTTD_VERSION_PATCH 1 -#define MQTTD_COMMIT_HASH 2b70078e9ce0694833dfb760747bbb7bf7f0621a -#define MQTTD_BUILD_TIMESTAMP 1720889932 +#define MQTTD_COMMIT_HASH "1a2e4ea6eb773b5db42cc3d37cc84c5b93248fb9" +#define MQTTD_BUILD_TIMESTAMP 1725026213 + +#define STRINGIFY(x) #x +#define TOSTRING(x) STRINGIFY(x) + +#define VERSION TOSTRING(MQTTD_VERSION_MAJOR) "." TOSTRING(MQTTD_VERSION_MINOR) "." TOSTRING(MQTTD_VERSION_PATCH)