| 1 | //===----------------------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef _LIBCPP___CONFIGURATION_HARDENING_H |
| 10 | #define _LIBCPP___CONFIGURATION_HARDENING_H |
| 11 | |
| 12 | #include <__config_site> |
| 13 | #include <__configuration/experimental.h> |
| 14 | #include <__configuration/language.h> |
| 15 | |
| 16 | #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER |
| 17 | # pragma GCC system_header |
| 18 | #endif |
| 19 | |
| 20 | // TODO(LLVM 23): Remove this. We're making these an error to catch folks who might not have migrated. |
| 21 | // Since hardening went through several changes (many of which impacted user-facing macros), |
| 22 | // we're keeping these checks around for a bit longer than usual. Failure to properly configure |
| 23 | // hardening results in checks being dropped silently, which is a pretty big deal. |
| 24 | #if defined(_LIBCPP_ENABLE_ASSERTIONS) |
| 25 | # error "_LIBCPP_ENABLE_ASSERTIONS has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
| 26 | #endif |
| 27 | #if defined(_LIBCPP_ENABLE_HARDENED_MODE) |
| 28 | # error "_LIBCPP_ENABLE_HARDENED_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
| 29 | #endif |
| 30 | #if defined(_LIBCPP_ENABLE_SAFE_MODE) |
| 31 | # error "_LIBCPP_ENABLE_SAFE_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
| 32 | #endif |
| 33 | #if defined(_LIBCPP_ENABLE_DEBUG_MODE) |
| 34 | # error "_LIBCPP_ENABLE_DEBUG_MODE has been removed, please use _LIBCPP_HARDENING_MODE=<mode> instead (see docs)" |
| 35 | #endif |
| 36 | |
| 37 | // The library provides the macro `_LIBCPP_HARDENING_MODE` which can be set to one of the following values: |
| 38 | // |
| 39 | // - `_LIBCPP_HARDENING_MODE_NONE`; |
| 40 | // - `_LIBCPP_HARDENING_MODE_FAST`; |
| 41 | // - `_LIBCPP_HARDENING_MODE_EXTENSIVE`; |
| 42 | // - `_LIBCPP_HARDENING_MODE_DEBUG`. |
| 43 | // |
| 44 | // These values have the following effects: |
| 45 | // |
| 46 | // - `_LIBCPP_HARDENING_MODE_NONE` -- sets the hardening mode to "none" which disables all runtime hardening checks; |
| 47 | // |
| 48 | // - `_LIBCPP_HARDENING_MODE_FAST` -- sets that hardening mode to "fast". The fast mode enables security-critical checks |
| 49 | // that can be done with relatively little runtime overhead in constant time; |
| 50 | // |
| 51 | // - `_LIBCPP_HARDENING_MODE_EXTENSIVE` -- sets the hardening mode to "extensive". The extensive mode is a superset of |
| 52 | // the fast mode that additionally enables checks that are relatively cheap and prevent common types of logic errors |
| 53 | // but are not necessarily security-critical; |
| 54 | // |
| 55 | // - `_LIBCPP_HARDENING_MODE_DEBUG` -- sets the hardening mode to "debug". The debug mode is a superset of the extensive |
| 56 | // mode and enables all checks available in the library, including internal assertions. Checks that are part of the |
| 57 | // debug mode can be very expensive and thus the debug mode is intended to be used for testing, not in production. |
| 58 | |
| 59 | // Inside the library, assertions are categorized so they can be cherry-picked based on the chosen hardening mode. These |
| 60 | // macros are only for internal use -- users should only pick one of the high-level hardening modes described above. |
| 61 | // |
| 62 | // - `_LIBCPP_ASSERT_VALID_INPUT_RANGE` -- checks that ranges (whether expressed as an iterator pair, an iterator and |
| 63 | // a sentinel, an iterator and a count, or a `std::range`) given as input to library functions are valid: |
| 64 | // - the sentinel is reachable from the begin iterator; |
| 65 | // - TODO(hardening): both iterators refer to the same container. |
| 66 | // |
| 67 | // - `_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS` -- checks that any attempts to access a container element, whether through |
| 68 | // the container object or through an iterator, are valid and do not attempt to go out of bounds or otherwise access |
| 69 | // a non-existent element. For iterator checks to work, bounded iterators must be enabled in the ABI. Types like |
| 70 | // `optional` and `function` are considered one-element containers for the purposes of this check. |
| 71 | // |
| 72 | // - `_LIBCPP_ASSERT_NON_NULL` -- checks that the pointer being dereferenced is not null. On most modern platforms zero |
| 73 | // address does not refer to an actual location in memory, so a null pointer dereference would not compromize the |
| 74 | // memory security of a program (however, it is still undefined behavior that can result in strange errors due to |
| 75 | // compiler optimizations). |
| 76 | // |
| 77 | // - `_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES` -- for functions that take several ranges as arguments, checks that the |
| 78 | // given ranges do not overlap. |
| 79 | // |
| 80 | // - `_LIBCPP_ASSERT_VALID_DEALLOCATION` -- checks that an attempt to deallocate memory is valid (e.g. the given object |
| 81 | // was allocated by the given allocator). Violating this category typically results in a memory leak. |
| 82 | // |
| 83 | // - `_LIBCPP_ASSERT_VALID_EXTERNAL_API_CALL` -- checks that a call to an external API doesn't fail in |
| 84 | // an unexpected manner. This includes triggering documented cases of undefined behavior in an external library (like |
| 85 | // attempting to unlock an unlocked mutex in pthreads). Any API external to the library falls under this category |
| 86 | // (from system calls to compiler intrinsics). We generally don't expect these failures to compromize memory safety or |
| 87 | // otherwise create an immediate security issue. |
| 88 | // |
| 89 | // - `_LIBCPP_ASSERT_COMPATIBLE_ALLOCATOR` -- checks any operations that exchange nodes between containers to make sure |
| 90 | // the containers have compatible allocators. |
| 91 | // |
| 92 | // - `_LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN` -- checks that the given argument is within the domain of valid arguments |
| 93 | // for the function. Violating this typically produces an incorrect result (e.g. the clamp algorithm returns the |
| 94 | // original value without clamping it due to incorrect functors) or puts an object into an invalid state (e.g. |
| 95 | // a string view where only a subset of elements is possible to access). This category is for assertions violating |
| 96 | // which doesn't cause any immediate issues in the library -- whatever the consequences are, they will happen in the |
| 97 | // user code. |
| 98 | // |
| 99 | // - `_LIBCPP_ASSERT_PEDANTIC` -- checks prerequisites which are imposed by the Standard, but violating which happens to |
| 100 | // be benign in our implementation. |
| 101 | // |
| 102 | // - `_LIBCPP_ASSERT_SEMANTIC_REQUIREMENT` -- checks that the given argument satisfies the semantic requirements imposed |
| 103 | // by the Standard. Typically, there is no simple way to completely prove that a semantic requirement is satisfied; |
| 104 | // thus, this would often be a heuristic check and it might be quite expensive. |
| 105 | // |
| 106 | // - `_LIBCPP_ASSERT_INTERNAL` -- checks that internal invariants of the library hold. These assertions don't depend on |
| 107 | // user input. |
| 108 | // |
| 109 | // - `_LIBCPP_ASSERT_UNCATEGORIZED` -- for assertions that haven't been properly classified yet. |
| 110 | |
| 111 | // clang-format off |
| 112 | # define _LIBCPP_HARDENING_MODE_NONE (1 << 1) |
| 113 | # define _LIBCPP_HARDENING_MODE_FAST (1 << 2) |
| 114 | # define _LIBCPP_HARDENING_MODE_EXTENSIVE (1 << 4) // Deliberately not ordered. |
| 115 | # define _LIBCPP_HARDENING_MODE_DEBUG (1 << 3) |
| 116 | // clang-format on |
| 117 | |
| 118 | #ifndef _LIBCPP_HARDENING_MODE |
| 119 | |
| 120 | # ifndef _LIBCPP_HARDENING_MODE_DEFAULT |
| 121 | # error _LIBCPP_HARDENING_MODE_DEFAULT is not defined. This definition should be set at configuration time in the \ |
| 122 | `__config_site` header, please make sure your installation of libc++ is not broken. |
| 123 | # endif |
| 124 | |
| 125 | # define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEFAULT |
| 126 | #endif |
| 127 | |
| 128 | #if _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_NONE && _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_FAST && \ |
| 129 | _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_EXTENSIVE && \ |
| 130 | _LIBCPP_HARDENING_MODE != _LIBCPP_HARDENING_MODE_DEBUG |
| 131 | # error _LIBCPP_HARDENING_MODE must be set to one of the following values: \ |
| 132 | _LIBCPP_HARDENING_MODE_NONE, \ |
| 133 | _LIBCPP_HARDENING_MODE_FAST, \ |
| 134 | _LIBCPP_HARDENING_MODE_EXTENSIVE, \ |
| 135 | _LIBCPP_HARDENING_MODE_DEBUG |
| 136 | #endif |
| 137 | |
| 138 | // The library provides the macro `_LIBCPP_ASSERTION_SEMANTIC` for configuring the assertion semantic used by hardening; |
| 139 | // it can be set to one of the following values: |
| 140 | // |
| 141 | // - `_LIBCPP_ASSERTION_SEMANTIC_IGNORE`; |
| 142 | // - `_LIBCPP_ASSERTION_SEMANTIC_OBSERVE`; |
| 143 | // - `_LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE`; |
| 144 | // - `_LIBCPP_ASSERTION_SEMANTIC_ENFORCE`. |
| 145 | // |
| 146 | // libc++ assertion semantics generally mirror the evaluation semantics of C++26 Contracts: |
| 147 | // - `ignore` evaluates the assertion but doesn't do anything if it fails (note that it differs from the Contracts |
| 148 | // `ignore` semantic which wouldn't evaluate the assertion at all); |
| 149 | // - `observe` logs an error (indicating, if possible, that the error is fatal) and continues execution; |
| 150 | // - `quick-enforce` terminates the program as fast as possible (via trapping); |
| 151 | // - `enforce` logs an error and then terminates the program. |
| 152 | // |
| 153 | // Additionally, a special `hardening-dependent` value selects the assertion semantic based on the hardening mode in |
| 154 | // effect: the production-capable modes (`fast` and `extensive`) map to `quick_enforce` and the `debug` mode maps to |
| 155 | // `enforce`. The `hardening-dependent` semantic cannot be selected explicitly, it is only used when no assertion |
| 156 | // semantic is provided by the user _and_ the library's default semantic is configured to be dependent on hardening. |
| 157 | // |
| 158 | // Notes: |
| 159 | // - Continuing execution after a hardening check fails results in undefined behavior; the `observe` semantic is meant |
| 160 | // to make adopting hardening easier but should not be used outside of this scenario; |
| 161 | // - C++26 wording for Library Hardening precludes a conforming Hardened implementation from using the Contracts |
| 162 | // `ignore` semantic when evaluating hardened preconditions in the Library. Libc++ allows using this semantic for |
| 163 | // hardened preconditions, however, be aware that using `ignore` does not produce a conforming "Hardened" |
| 164 | // implementation, unlike the other semantics above. |
| 165 | // clang-format off |
| 166 | # define _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT (1 << 1) |
| 167 | # define _LIBCPP_ASSERTION_SEMANTIC_IGNORE (1 << 2) |
| 168 | # define _LIBCPP_ASSERTION_SEMANTIC_OBSERVE (1 << 3) |
| 169 | # define _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE (1 << 4) |
| 170 | # define _LIBCPP_ASSERTION_SEMANTIC_ENFORCE (1 << 5) |
| 171 | // clang-format on |
| 172 | |
| 173 | // If the user attempts to configure the assertion semantic, check that it is allowed in the current environment. |
| 174 | #if defined(_LIBCPP_ASSERTION_SEMANTIC) |
| 175 | # if !_LIBCPP_HAS_EXPERIMENTAL_LIBRARY |
| 176 | # error "Assertion semantics are an experimental feature." |
| 177 | # endif |
| 178 | # if defined(_LIBCPP_CXX03_LANG) |
| 179 | # error "Assertion semantics are not available in the C++03 mode." |
| 180 | # endif |
| 181 | #endif // defined(_LIBCPP_ASSERTION_SEMANTIC) |
| 182 | |
| 183 | // User-provided semantic takes top priority -- don't override if set. |
| 184 | #ifndef _LIBCPP_ASSERTION_SEMANTIC |
| 185 | |
| 186 | # ifndef _LIBCPP_ASSERTION_SEMANTIC_DEFAULT |
| 187 | # error _LIBCPP_ASSERTION_SEMANTIC_DEFAULT is not defined. This definition should be set at configuration time in \ |
| 188 | the `__config_site` header, please make sure your installation of libc++ is not broken. |
| 189 | # endif |
| 190 | |
| 191 | # if _LIBCPP_ASSERTION_SEMANTIC_DEFAULT != _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT |
| 192 | # define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_DEFAULT |
| 193 | # else |
| 194 | # if _LIBCPP_HARDENING_MODE == _LIBCPP_HARDENING_MODE_DEBUG |
| 195 | # define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_ENFORCE |
| 196 | # else |
| 197 | # define _LIBCPP_ASSERTION_SEMANTIC _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE |
| 198 | # endif |
| 199 | # endif // _LIBCPP_ASSERTION_SEMANTIC_DEFAULT != _LIBCPP_ASSERTION_SEMANTIC_HARDENING_DEPENDENT |
| 200 | |
| 201 | #endif // #ifndef _LIBCPP_ASSERTION_SEMANTIC |
| 202 | |
| 203 | // Finally, validate the selected semantic (in case the user tries setting it to an incorrect value): |
| 204 | #if _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_IGNORE && \ |
| 205 | _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_OBSERVE && \ |
| 206 | _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE && \ |
| 207 | _LIBCPP_ASSERTION_SEMANTIC != _LIBCPP_ASSERTION_SEMANTIC_ENFORCE |
| 208 | # error _LIBCPP_ASSERTION_SEMANTIC must be set to one of the following values: \ |
| 209 | _LIBCPP_ASSERTION_SEMANTIC_IGNORE, \ |
| 210 | _LIBCPP_ASSERTION_SEMANTIC_OBSERVE, \ |
| 211 | _LIBCPP_ASSERTION_SEMANTIC_QUICK_ENFORCE, \ |
| 212 | _LIBCPP_ASSERTION_SEMANTIC_ENFORCE |
| 213 | #endif |
| 214 | |
| 215 | #endif // _LIBCPP___CONFIGURATION_HARDENING_H |
| 216 | |