Hardening Modes

Using hardening modes

The hardened mode enables a set of security-critical assertions that prevent undefined behavior caused by violating preconditions of the standard library. These assertions can be done with relatively little overhead in constant time and are intended to be used in production.

In addition to the hardened mode, libc++ also provides two other hardening modes: - safe mode; - debug mode.

The safe mode contains all the checks from the hardened mode and additionally some checks for undefined behavior that incur relatively little overhead but aren’t security-critical. While the performance penalty is somewhat more significant compared to the hardened mode, the safe mode is still intended to be usable in production.

The debug mode, in turn, contains all the checks from the safe mode and additionally more expensive checks that may affect the complexity of algorithms. The debug mode is intended to be used for testing, not in production.

Vendors can set the default hardening mode by using the LIBCXX_HARDENING_MODE variable at CMake configuration time. Setting LIBCXX_HARDENING_MODE to hardened enables the hardened mode, and similarly setting the variable to safe enables the safe mode, and to debug enables the debug mode. The default value is unchecked which doesn’t enable any hardening.

When hardening is enabled, the compiled library is built with the corresponding mode enabled, and user code will be built with the same mode enabled by default. If the mode is set to “unchecked” at the CMake configuration time, the compiled library will not contain any assertions and the default when building user code will be to have assertions disabled. As a user, you can consult your vendor to know which level of hardening is enabled by default.

Furthermore, independently of any vendor-selected default, users can always control which level of hardening is enabled in their code by defining _LIBCPP_ENABLE_HARDENED_MODE=0|1 (or _LIBCPP_ENABLE_SAFE_MODE=0|1, or _LIBCPP_ENABLE_DEBUG_MODE=0|1) before including any libc++ header (we recommend passing -D_LIBCPP_ENABLE_HARDENED_MODE=X, etc. to the compiler). Note that if the compiled library was built by the vendor in the unchecked mode, functions compiled inside the static or shared library won’t have any hardening enabled even if the user compiles with hardening enabled (the same is true for the inverse case where the static or shared library was compiled with hardening enabled but the user tries to disable it). However, most of the code in libc++ is in the headers, so the user-selected value for _LIBCPP_ENABLE_HARDENED|SAFE|DEBUG_MODE, if any, will usually be respected.

Enabling hardening has no impact on the ABI.

Iterator bounds checking