forked from OSchip/llvm-project
[docs] Update Scudo documentation
Summary: The documentation has fallen a bit behind, update it with the latest evolution of the allocator: - clarify a couple of expectations regarding what is meant to be achieved; - update the header format; - document `-fsanitize=scudo`. Reviewers: alekseyshl, flowerhack Reviewed By: alekseyshl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D41670 llvm-svn: 321811
This commit is contained in:
parent
208fab193b
commit
b84053291f
|
@ -26,32 +26,45 @@ meaning Shield in Spanish and Portuguese).
|
|||
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 @@ local copies of the header for this purpose.
|
|||
|
||||
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 @@ and then use it with existing binaries as follows:
|
|||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue