summaryrefslogtreecommitdiff
path: root/etc/DEBUG
diff options
context:
space:
mode:
authorVibhav Pant <vibhavp@gmail.com>2022-12-19 18:04:05 +0530
committerVibhav Pant <vibhavp@gmail.com>2022-12-19 18:04:05 +0530
commitcb242bf1514ade34ab93b1db1ea7550093ae5839 (patch)
tree05b066f7a16dcba316bb34923bf64a92dca97204 /etc/DEBUG
parent79b1dede3444c07f943be34867bb2cdac236ab55 (diff)
downloademacs-cb242bf1514ade34ab93b1db1ea7550093ae5839.tar.gz
Add support for additional memory checks using AddressSanitizer.
When Emacs is compiled with AddressSanitizer support, enable poisoning/unpoisoning freed/unused Lisp objects and other internal memory management structures. If enabled, this will mark freed bytes that have been put on free lists for future use and initially allocated memory blocks/chunks as "poisoned", triggering an ASan error if they are accessed improperly. Structures are unpoisoned when they have been taken off their respective free lists. Additionally, add optional macros for performing unaligned loads, which when enabled by defining USE_SANITIZER_UNALIGNED_LOAD will use ASan provided functions for loading from unaligned addresses, which may help catch bugs that AddressSanitizer might otherwise miss. * configure.ac: Check for the existence of address and common sanitizer API headers. * src/lisp.h (UNALIGNED_LOAD_SIZE): New macro. If enabled, and the necessary sanitizer API is available, define it to __sanitizer_unaligned_load(64|32) depending on the word size of the architecture. * src/fns.c [HAVE_FAST_UNALIGNED_ACCESS] (Fstring_lessp): Use 'UNALIGNED_LOAD_SIZE' to perform unaligned loads from the two strings. * src/alloc.c (ASAN_POISON_ABLOCK, ASAN_UNPOISON_ABLOCK) (ASAN_POISON_INTERVAL_BLOCK, ASAN_UNPOISON_INTERVAL_BLOCK) (ASAN_POISON_INTERVAL, ASAN_UNPOISON_INTERVAL) (ASAN_PREPARE_DEAD_SDATA, ASAN_PREPARE_LIVE_SDATA) (ASAN_POISON_SBLOCK_DATA, ASAN_POISON_STRING_BLOCK) (ASAN_UNPOISON_STRING_BLOCK, ASAN_POISON_STRING) (ASAN_UNPOISON_STRING, ASAN_POISON_FLOAT_BLOCK) (ASAN_UNPOISON_FLOAT_BLOCK, ASAN_POISON_FLOAT) (ASAN_UNPOISON_FLOAT, ASAN_POISON_CONS_BLOCK) (ASAN_POISON_CONS, ASAN_UNPOISON_CONS) (ASAN_POISON_VECTOR_CONTENTS, ASAN_UNPOISON_VECTOR_CONTENTS) (ASAN_UNPOISON_VECTOR_BLOCK, ASAN_POISON_SYMBOL_BLOCK) (ASAN_UNPOISON_SYMBOL_BLOCK, ASAN_POISON_SYMBOL) (ASAN_UNPOISON_SYMBOL) [ADDRESS_SANITIZER]: New macros. When address sanitization is enabled, define them to poison/unpoison objects. (lisp_align_malloc): Poison newly allocated blocks on `free_ablock', unpoison ablocks taken from it respectively. (lisp_align_free): Poison individual ablocks when they are put on the free list, unpoison them when an entire `ablocks' chunk is being freed. (make_interval): Poison interval blocks on initial allocation, unpoison individual intervals on allocation and removal from `interval_free_list'. (sweep_intervals): Unpoison interval blocks before sweeping, poison dead/unmarked intervals. (allocate_string): Poison string blocks on initial allocation, unpoison Lisp_Strings on removal from the free list. (allocate_string_data): Poison `sblock' data on initial allocation, unpoison individual `sdata' contents on allocation or removal from the free list. Call `ASAN_PREPARE_LIVE_SDATA' on the new `sdata' struct. (sweep_strings): Unpoison string blocks before sweeping them, poisoning dead strings and their sdata afterwards. (compact_small_strings): Call `ASAN_PREPARE_LIVE_DATA' on the `sdata' to where compacted strings to moved to. (pin_string): Call `ASAN_PREPARE_DEAD_SDATA' on `old_sdata'. (make_float): Poison float blocks on allocation, unpoisoning individual Lisp_Floats on allocation or removal from `float_free_list'. (sweep_floats): Unpoison float blocks before sweeping, poison dead/unmarked floats. (free_cons): Poison `ptr'. (Fcons): Poison cons blocks on allocation, unpoisoning individual Lisp_Cons on allocation or removal from `cons_free_list'. (sweep_conses): Poison dead/unmarked conses. (setup_free_list): Poison vectors put on `vector_free_lists'. (allocate_vector_from_block): Unpoison vectors taken from the free list, poison excess vector bytes when vectors allocated from the free list are larger than requested. (sweep_vectors): Unpoison vector blocks before sweeping them. (Fmake_symbol): Poison symbol blocks on initial allocation, unpoisoning individual Lisp_Symbols on allocation or removal from `symbol_free_list'. (sweep_symbols): Unpoison symbol blocks before sweeping, poisoning dead/unmarked symbols. (live_string_holding, live_cons_holding, live_symbol_holding) (live_float_holding): When compiling with address sanitization and GC poisoning enabled, return NULL if the passed address is poisoned, or if the Lisp object it resides in is poisoned, avoiding a use-after-poison trigger if these functions are called on a pointer that might be referring to a now dead/swept object. * etc/DEBUG: Add information about enabling ASan memory poisoning.
Diffstat (limited to 'etc/DEBUG')
-rw-r--r--etc/DEBUG22
1 files changed, 22 insertions, 0 deletions
diff --git a/etc/DEBUG b/etc/DEBUG
index ef9160a2090..01c75f8da7a 100644
--- a/etc/DEBUG
+++ b/etc/DEBUG
@@ -1002,6 +1002,28 @@ Address sanitization is incompatible with undefined-behavior
sanitization, unfortunately. Address sanitization is also
incompatible with the --with-dumping=unexec option of 'configure'.
+*** Address poisoning/unpoisoning
+
+When compiled with address sanitization, Emacs will also try to mark
+dead/free lisp objects as poisoned, forbidding them from being
+accessed without being unpoisoned first. This adds an extra layer
+of checking with objects in internal free lists, which may otherwise
+evade traditional use-after-free checks. To disable this, add
+'allow_user_poisoning=0' to ASAN_OPTIONS, or build Emacs with
+'-DGC_ASAN_POISON_OBJECTS=0' in CFLAGS.
+
+While using GDB, memory addresses can be inspected by using helper
+functions additionally provided by the ASan library:
+
+ (gdb) call __asan_describe_address(ptr)
+
+To check whether an address range is poisoned or not, use:
+
+ (gdb) call __asan_region_is_poisoned(ptr, 8)
+
+Additional functions can be found in the header
+'sanitizer/asan_interface.h' in your compiler's headers directory.
+
** Running Emacs under Valgrind
Valgrind <https://valgrind.org/> is free software that can be useful