brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.2 KiB · 3f319e8 Raw
231 lines · plain
1=================2Allocation Tokens3=================4 5.. contents::6   :local:7 8Introduction9============10 11Clang provides support for allocation tokens to enable allocator-level heap12organization strategies. Clang assigns mode-dependent token IDs to allocation13calls; the runtime behavior depends entirely on the implementation of a14compatible memory allocator.15 16Possible allocator strategies include:17 18* **Security Hardening**: Placing allocations into separate, isolated heap19  partitions. For example, separating pointer-containing types from raw data20  can mitigate exploits that rely on overflowing a primitive buffer to corrupt21  object metadata.22 23* **Memory Layout Optimization**: Grouping related allocations to improve data24  locality and cache utilization.25 26* **Custom Allocation Policies**: Applying different management strategies to27  different partitions.28 29Token Assignment Mode30=====================31 32The default mode to calculate tokens is:33 34* ``typehashpointersplit``: This mode assigns a token ID based on the hash of35  the allocated type's name, where the top half ID-space is reserved for types36  that contain pointers and the bottom half for types that do not contain37  pointers.38 39Other token ID assignment modes are supported, but they may be subject to40change or removal. These may (experimentally) be selected with ``-Xclang41-falloc-token-mode=<mode>``:42 43* ``typehash``: This mode assigns a token ID based on the hash of the allocated44  type's name.45 46* ``random``: This mode assigns a statically-determined random token ID to each47  allocation site.48 49* ``increment``: This mode assigns a simple, incrementally increasing token ID50  to each allocation site.51 52The following command-line options affect generated token IDs:53 54* ``-falloc-token-max=<N>``55    Configures the maximum number of token IDs. By default the number of tokens56    is bounded by ``SIZE_MAX``.57 58Querying Token IDs with ``__builtin_infer_alloc_token``59=======================================================60 61For use cases where the token ID must be known at compile time, Clang provides62a builtin function:63 64.. code-block:: c65 66    size_t __builtin_infer_alloc_token(<args>, ...);67 68This builtin returns the token ID inferred from its argument expressions, which69mirror arguments normally passed to any allocation function. The argument70expressions are **unevaluated**, so it can be used with expressions that would71have side effects without any runtime impact.72 73For example, it can be used as follows:74 75.. code-block:: c76 77    struct MyType { ... };78    void *__partition_alloc(size_t size, size_t partition);79    #define partition_alloc(...) __partition_alloc(__VA_ARGS__, __builtin_infer_alloc_token(__VA_ARGS__))80 81    void foo(void) {82        MyType *x = partition_alloc(sizeof(*x));83    }84 85Allocation Token Instrumentation86================================87 88To enable instrumentation of allocation functions, code can be compiled with89the ``-fsanitize=alloc-token`` flag:90 91.. code-block:: console92 93    % clang++ -fsanitize=alloc-token example.cc94 95The instrumentation transforms allocation calls to include a token ID. For96example:97 98.. code-block:: c99 100    // Original:101    ptr = malloc(size);102 103    // Instrumented:104    ptr = __alloc_token_malloc(size, <token id>);105 106Runtime Interface107-----------------108 109A compatible runtime must be provided that implements the token-enabled110allocation functions. The instrumentation generates calls to functions that111take a final ``size_t token_id`` argument.112 113.. code-block:: c114 115    // C standard library functions116    void *__alloc_token_malloc(size_t size, size_t token_id);117    void *__alloc_token_calloc(size_t count, size_t size, size_t token_id);118    void *__alloc_token_realloc(void *ptr, size_t size, size_t token_id);119    // ...120 121    // C++ operators (mangled names)122    // operator new(size_t, size_t)123    void *__alloc_token__Znwm(size_t size, size_t token_id);124    // operator new[](size_t, size_t)125    void *__alloc_token__Znam(size_t size, size_t token_id);126    // ... other variants like nothrow, etc., are also instrumented.127 128Fast ABI129--------130 131An alternative ABI can be enabled with ``-fsanitize-alloc-token-fast-abi``,132which encodes the token ID in the allocation function name.133 134.. code-block:: c135 136    void *__alloc_token_0_malloc(size_t size);137    void *__alloc_token_1_malloc(size_t size);138    void *__alloc_token_2_malloc(size_t size);139    ...140    void *__alloc_token_0_Znwm(size_t size);141    void *__alloc_token_1_Znwm(size_t size);142    void *__alloc_token_2_Znwm(size_t size);143    ...144 145This ABI provides a more efficient alternative where146``-falloc-token-max`` is small.147 148Instrumenting Non-Standard Allocation Functions149-----------------------------------------------150 151By default, AllocToken only instruments standard library allocation functions.152This simplifies adoption, as a compatible allocator only needs to provide153token-enabled variants for a well-defined set of standard functions.154 155To extend instrumentation to custom allocation functions, enable broader156coverage with ``-fsanitize-alloc-token-extended``. Such functions require being157marked with the `malloc158<https://clang.llvm.org/docs/AttributeReference.html#malloc>`_ or `alloc_size159<https://clang.llvm.org/docs/AttributeReference.html#alloc-size>`_ attributes160(or a combination).161 162For example:163 164.. code-block:: c165 166    void *custom_malloc(size_t size) __attribute__((malloc));167    void *my_malloc(size_t size) __attribute__((alloc_size(1)));168 169    // Original:170    ptr1 = custom_malloc(size);171    ptr2 = my_malloc(size);172 173    // Instrumented:174    ptr1 = __alloc_token_custom_malloc(size, token_id);175    ptr2 = __alloc_token_my_malloc(size, token_id);176 177Disabling Instrumentation178-------------------------179 180To exclude specific functions from instrumentation, you can use the181``no_sanitize("alloc-token")`` attribute:182 183.. code-block:: c184 185    __attribute__((no_sanitize("alloc-token")))186    void* custom_allocator(size_t size) {187        return malloc(size);  // Uses original malloc188    }189 190Note: Independent of any given allocator support, the instrumentation aims to191remain performance neutral. As such, ``no_sanitize("alloc-token")``192functions may be inlined into instrumented functions and vice-versa. If193correctness is affected, such functions should explicitly be marked194``noinline``.195 196The ``__attribute__((disable_sanitizer_instrumentation))`` is also supported to197disable this and other sanitizer instrumentations.198 199Suppressions File (Ignorelist)200------------------------------201 202AllocToken respects the ``src`` and ``fun`` entity types in the203:doc:`SanitizerSpecialCaseList`, which can be used to omit specified source204files or functions from instrumentation.205 206.. code-block:: bash207 208    [alloc-token]209    # Exclude specific source files210    src:third_party/allocator.c211    # Exclude function name patterns212    fun:*custom_malloc*213    fun:LowLevel::*214 215.. code-block:: console216 217    % clang++ -fsanitize=alloc-token -fsanitize-ignorelist=my_ignorelist.txt example.cc218 219Conditional Compilation with ``__SANITIZE_ALLOC_TOKEN__``220-----------------------------------------------------------221 222In some cases, one may need to execute different code depending on whether223AllocToken instrumentation is enabled. The ``__SANITIZE_ALLOC_TOKEN__`` macro224can be used for this purpose.225 226.. code-block:: c227 228    #ifdef __SANITIZE_ALLOC_TOKEN__229    // Code specific to -fsanitize=alloc-token builds230    #endif231