Index: docs/ScudoHardenedAllocator.rst =================================================================== --- docs/ScudoHardenedAllocator.rst +++ docs/ScudoHardenedAllocator.rst @@ -26,32 +26,45 @@ Design ====== +Allocator +--------- +Scudo can be considered a Frontend to the Sanitizers' common allocator (later +referenced as the Backend). It is split between a Primary allocator, fast and +efficient, that services smaller allocation sizes, and a Secondary allocator +that services larger allocation sizes and is backed by the operating system +memory mapping primitives. + +Scudo was designed with security in mind, but aims at striking a good balance +between security and performance. It is highly tunable and configurable. + Chunk Header ------------ Every chunk of heap memory will be preceded by a chunk header. This has two purposes, the first one being to store various information about the chunk, the second one being to detect potential heap overflows. In order to achieve -this, the header will be checksumed, involving the pointer to the chunk itself +this, the header will be checksummed, involving the pointer to the chunk itself and a global secret. Any corruption of the header will be detected when said header is accessed, and the process terminated. The following information is stored in the header: - the 16-bit checksum; -- the unused bytes amount for that chunk, which is necessary for computing the - size of the chunk; +- the class ID for that chunk, which is the "bucket" where the chunk resides + for Primary backed allocations, or 0 for Secondary backed allocations; +- the size (Primary) or unused bytes amount (Secondary) for that chunk, which is + necessary for computing the size of the chunk; - the state of the chunk (available, allocated or quarantined); - the allocation type (malloc, new, new[] or memalign), to detect potential mismatches in the allocation APIs used; - the offset of the chunk, which is the distance in bytes from the beginning of - the returned chunk to the beginning of the backend allocation; -- a 8-bit salt. + the returned chunk to the beginning of the Backend allocation; This header fits within 8 bytes, on all platforms supported. The checksum is computed as a CRC32 (made faster with hardware support) of the global secret, the chunk pointer itself, and the 8 bytes of header with -the checksum field zeroed out. +the checksum field zeroed out. It is not intended to be cryptographically +strong. The header is atomically loaded and stored to prevent races. This is important as two consecutive chunks could belong to different threads. We also want to @@ -60,9 +73,9 @@ Delayed Freelist ----------------- -A delayed freelist allows us to not return a chunk directly to the backend, but +A delayed freelist allows us to not return a chunk directly to the Backend, but to keep it aside for a while. Once a criterion is met, the delayed freelist is -emptied, and the quarantined chunks are returned to the backend. This helps +emptied, and the quarantined chunks are returned to the Backend. This helps mitigate use-after-free vulnerabilities by reducing the determinism of the allocation and deallocation patterns. @@ -107,13 +120,21 @@ LD_PRELOAD=`pwd`/scudo-allocator.so ./a.out +Clang +----- +With a recent version of Clang (post rL317337), the allocator can be linked with +a binary at compilation using the ``-fsanitize=scudo`` command-line argument, if +the target platform is supported. Currently, the only other Sanitizer Scudo is +compatible with is UBSan (eg: ``-fsanitize=scudo,undefined``). Compiling with +Scudo will also enforce PIE for the output binary. + Options ------- Several aspects of the allocator can be configured through the following ways: - by defining a ``__scudo_default_options`` function in one's program that returns the options string to be parsed. Said function must have the following - prototype: ``extern "C" const char* __scudo_default_options()``. + prototype: ``extern "C" const char* __scudo_default_options(void)``. - through the environment variable SCUDO_OPTIONS, containing the options string to be parsed. Options defined this way will override any definition made