[libcxx-commits] [libcxx] [libc++][hardening] Finish documenting hardening. (PR #92021)
Konstantin Varlamov via libcxx-commits
libcxx-commits at lists.llvm.org
Wed May 22 16:00:45 PDT 2024
================
@@ -72,17 +75,301 @@ to control the level by passing **one** of the following options to the compiler
Notes for vendors
-----------------
-Vendors can set the default hardening mode by providing ``LIBCXX_HARDENING_MODE``
-as a configuration option, with the possible values of ``none``, ``fast``,
-``extensive`` and ``debug``. The default value is ``none`` which doesn't enable
-any hardening checks (this mode is sometimes called the ``unchecked`` mode).
+Vendors can set the default hardening mode by providing
+``LIBCXX_HARDENING_MODE`` as a configuration option, with the possible values of
+``none``, ``fast``, ``extensive`` and ``debug``. The default value is ``none``
+which doesn't enable any hardening checks (this mode is sometimes called the
+``unchecked`` mode).
This option controls both the hardening mode that the precompiled library is
built with and the default hardening mode that users will build with. If set to
``none``, the precompiled library will not contain any assertions, and user code
will default to building without assertions.
-Iterator bounds checking
-------------------------
+Vendors can also override the termination handler by :ref:`providing a custom
+header <override-assertion-handler>`.
-TODO(hardening)
+Assertion categories
+====================
+
+Inside the library, individual assertions are grouped into different
+*categories*. Each hardening mode enables a different set of assertion
+categories; categories provide an additional layer of abstraction that makes it
+easier to reason about the high-level semantics of a hardening mode.
+
+- ``valid-element-access`` -- checks that any attempts to access a container
+ element, whether through the container object or through an iterator, are
+ valid and do not attempt to go out of bounds or otherwise access
+ a non-existent element. For iterator checks to work, bounded iterators must be
+ enabled in the ABI. Types like ``optional`` and ``function`` are considered
+ one-element containers for the purposes of this check.
+
+- ``valid-input-range`` -- checks that ranges (whether expressed as an iterator
+ pair, an iterator and a sentinel, an iterator and a count, or
+ a ``std::range``) given as input to library functions are valid:
+ - the sentinel is reachable from the begin iterator;
+ - TODO(hardening): both iterators refer to the same container.
+
+ ("input" here refers to "an input given to an algorithm", not to an iterator
+ category)
+
+ Violating assertions in this category leads to an out-of-bounds access.
+
+- ``non-null`` -- checks that the pointer being dereferenced is not null. On
+ most modern platforms zero address does not refer to an actual location in
+ memory, so a null pointer dereference would not compromize the memory security
+ of a program (however, it is still undefined behavior that can result in
+ strange errors due to compiler optimizations).
+
+- ``non-overlapping-ranges`` -- for functions that take several ranges as
+ arguments, checks that the given ranges do not overlap.
+
+- ``valid-deallocation`` -- checks that an attempt to deallocate memory is valid
+ (e.g. the given object was allocated by the given allocator). Violating this
+ category typically results in a memory leak.
+
+- ``valid-external-api-call`` -- checks that a call to an external API doesn't
+ fail in an unexpected manner. This includes triggering documented cases of
+ undefined behavior in an external library (like attempting to unlock an
+ unlocked mutex in pthreads). Any API external to the library falls under this
+ category (from system calls to compiler intrinsics). We generally don't expect
+ these failures to compromize memory safety or otherwise create an immediate
+ security issue.
+
+- ``compatible-allocator`` -- checks any operations that exchange nodes between
+ containers to make sure the containers have compatible allocators.
+
+- ``argument-within-domain`` -- checks that the given argument is within the
+ domain of valid arguments for the function. Violating this typically produces
+ an incorrect result (e.g. the clamp algorithm returns the original value
+ without clamping it due to incorrect functors) or puts an object into an
+ invalid state (e.g. a string view where only a subset of elements is possible
+ to access). This category is for assertions violating which doesn't cause any
+ immediate issues in the library -- whatever the consequences are, they will
+ happen in the user code.
+
+- ``pedantic`` -- checks prerequisites that are imposed by the Standard, but
+ violating which happens to be benign in our implementation.
----------------
var-const wrote:
It's true that sometimes it may be difficult to determine, and we should err on the side of caution, but sometimes it's pretty clear (e.g. we explicitly check for a "bad" input and return). For an overflow, we should focus on the worst thing that could happen given how the result of the overflow is used. If it's used for indexing, this is _not_ a benign issue -- in general, the classification should focus on the consequences of the bug, not its "mechanism".
I don't see this category as a commitment for the future -- I think we can reclassify (as well as add or remove) any check in general (obviously we should aim to avoid any potential disruption for the users, but I think we would do both our users and ourselves a disservice if we commit to freeze the initial state of the first release).
IMO it's a very valid concern that this might become out of sync, but it applies to any assertion category. We should commit to making sure that the classification of our assertions is valid for the current state of the library. But I don't think it would make us any more future-proof we deliberately classify assertions as more severe than their actual effect. I also think that simply representing the current state is the easiest mental model to work with.
https://github.com/llvm/llvm-project/pull/92021
More information about the libcxx-commits
mailing list