Line data Source code
1 : #ifndef HEADER_fd_src_util_sanitize_fd_asan_h 2 : #define HEADER_fd_src_util_sanitize_fd_asan_h 3 : 4 : #include "../fd_util_base.h" 5 : 6 : /* AddressSanitizer (ASan) tracks allocated memory regions and 7 : instruments all memory accesses to detect possible out-of-bounds 8 : errors. 9 : 10 : This API is used to mark memory regions at runtime where default ASan 11 : instrumentation is missing. Firedancer objects are mainly backed by 12 : shared memory segments via huge pages managed by a custom memory 13 : allocator. 14 : 15 : More info on ASan: 16 : - https://clang.llvm.org/docs/AddressSanitizer.html 17 : - https://github.com/google/sanitizers/wiki/AddressSanitizer 18 : 19 : For a guide on how to setup manual ASan memory poisoning, see 20 : https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */ 21 : 22 : /* Based on https://github.com/llvm/llvm-project/blob/main/compiler-rt/include/sanitizer/asan_interface.h 23 : 24 : Part of the LLVM Project, under the Apache License v2.0 with LLVM 25 : Exceptions. See https://llvm.org/LICENSE.txt for license 26 : information. SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 27 : 28 : This file was originally part of AddressSanitizer (ASan). */ 29 : 30 : #ifndef FD_HAS_ASAN 31 : #if defined(__has_feature) 32 : #define FD_HAS_ASAN __has_feature(address_sanitizer) 33 : #elif defined(__SANITIZE_ADDRESS__) 34 : #define FD_HAS_ASAN 1 35 : #else 36 : #define FD_HAS_ASAN 0 37 : #endif 38 : #endif 39 : 40 : /* FD_FN_NO_ASAN is a function attribute to disable ASan instrumentation 41 : when FD_HAS_ASAN is set (and expands to nothing if not). */ 42 : 43 : #if FD_HAS_ASAN 44 : #define FD_FN_NO_ASAN __attribute__((no_sanitize("address"))) 45 : #else 46 : #define FD_FN_NO_ASAN 47 : #endif 48 : 49 : FD_PROTOTYPES_BEGIN 50 : 51 : /* If FD_HAS_ASAN is set: 52 : 53 : fd_asan_poison marks a memory region `[addr,addr+sz)` as 54 : unaddressable and returns addr. This memory must be previously 55 : allocated by your program. Instrumented code is forbidden from 56 : accessing addresses in this region until it is unpoisoned. This 57 : function is not guaranteed to poison the entire region; it might 58 : poison only a sub-region of `[addr,addr+sz)` due to ASan alignment 59 : restrictions. 60 : 61 : fd_asan_unpoison marks a memory region `[addr,addr+sz)` as 62 : addressable and returns addr. This memory must be previously 63 : allocated by your program. Accessing addresses in this region is 64 : allowed until this region is poisoned again. This function might 65 : unpoison a super-region of `[addr,addr+sz)` due to ASan alignment 66 : restrictions. 67 : 68 : fd_asan_test tests if an address is poisoned. Returns 1 if addr is 69 : poisoned (that is, a 1-byte read/write access to this address would 70 : result in an error report from ASan). Otherwise returns 0. 71 : 72 : fd_asan_query checks if a region is poisoned. If at least one byte 73 : in `[addr,addr+sz)` is poisoned, returns the address of the first 74 : such byte. Otherwise returns NULL. 75 : 76 : If FD_HAS_ASAN is not set fd_asan_{poison,unpoison} just return addr, 77 : fd_asan_test returns 0 and fd_asan_query returns NULL. 78 : 79 : FIXME: CONST CORRECT VERSIONS? */ 80 : 81 : #ifdef FD_HAS_DEEPASAN 82 : #define FD_ASAN_ALIGN (8UL) 83 : #endif 84 : 85 : #if FD_HAS_ASAN 86 : 87 : /* These are for internal use only */ 88 : 89 : void __asan_poison_memory_region ( void const volatile * addr, ulong sz ); 90 : void __asan_unpoison_memory_region( void const volatile * addr, ulong sz ); 91 : int __asan_address_is_poisoned ( void const volatile * addr ); 92 : void * __asan_region_is_poisoned ( void * addr, ulong sz ); 93 : 94 : static inline void * fd_asan_poison ( void * addr, ulong sz ) { __asan_poison_memory_region ( addr, sz ); return addr; } 95 : static inline void * fd_asan_unpoison( void * addr, ulong sz ) { __asan_unpoison_memory_region( addr, sz ); return addr; } 96 : static inline int fd_asan_test ( void * addr ) { return __asan_address_is_poisoned( addr ); } 97 : static inline void * fd_asan_query ( void * addr, ulong sz ) { return __asan_region_is_poisoned ( addr, sz ); } 98 : 99 : #else 100 : 101 9 : static inline void * fd_asan_poison ( void * addr, ulong sz ) { (void)sz; return addr; } 102 9 : static inline void * fd_asan_unpoison( void * addr, ulong sz ) { (void)sz; return addr; } 103 0 : static inline int fd_asan_test ( void * addr ) { (void)addr; return 0; } 104 0 : static inline void * fd_asan_query ( void * addr, ulong sz ) { (void)addr; (void)sz; return NULL; } 105 : 106 : #endif 107 : 108 : FD_PROTOTYPES_END 109 : 110 : #endif /* HEADER_fd_src_util_sanitize_fd_asan_h */