1//===-- scudo/interface.h ---------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef SCUDO_INTERFACE_H_
10#define SCUDO_INTERFACE_H_
11
12#include <stddef.h>
13#include <stdint.h>
14
15extern "C" {
16
17__attribute__((weak)) const char *__scudo_default_options(void);
18
19// Post-allocation & pre-deallocation hooks.
20__attribute__((weak)) void __scudo_allocate_hook(void *ptr, size_t size);
21__attribute__((weak)) void __scudo_deallocate_hook(void *ptr);
22
23// `realloc` involves both deallocation and allocation but they are not reported
24// atomically. In one specific case which may keep taking a snapshot right in
25// the middle of `realloc` reporting the deallocation and allocation, it may
26// confuse the user by missing memory from `realloc`. To alleviate that case,
27// define the two `realloc` hooks to get the knowledge of the bundled hook
28// calls. These hooks are optional and should only be used when a hooks user
29// wants to track reallocs more closely.
30//
31// See more details in the comment of `realloc` in wrapper_c.inc.
32__attribute__((weak)) void
33__scudo_realloc_allocate_hook(void *old_ptr, void *new_ptr, size_t size);
34__attribute__((weak)) void __scudo_realloc_deallocate_hook(void *old_ptr);
35
36void __scudo_print_stats(void);
37
38typedef void (*iterate_callback)(uintptr_t base, size_t size, void *arg);
39
40// Determine the likely cause of a tag check fault or other memory protection
41// error on a system with memory tagging support. The results are returned via
42// the error_info data structure. Up to three possible causes are returned in
43// the reports array, in decreasing order of probability. The remaining elements
44// of reports are zero-initialized.
45//
46// This function may be called from a different process from the one that
47// crashed. In this case, various data structures must be copied from the
48// crashing process to the process that analyzes the crash.
49//
50// This interface is not guaranteed to be stable and may change at any time.
51// Furthermore, the version of scudo in the crashing process must be the same as
52// the version in the process that analyzes the crash.
53//
54// fault_addr is the fault address. On aarch64 this is available in the system
55// register FAR_ELx, or siginfo.si_addr in Linux 5.11 or above. This address
56// must include the pointer tag; this is available if SA_EXPOSE_TAGBITS was set
57// in sigaction.sa_flags when the signal handler was registered. Note that the
58// kernel strips the tag from the field sigcontext.fault_address, so this
59// address is not suitable to be passed as fault_addr.
60//
61// stack_depot is a pointer to the stack depot data structure, which may be
62// obtained by calling the function __scudo_get_stack_depot_addr() in the
63// crashing process. The size of the stack depot is available by calling the
64// function __scudo_get_stack_depot_size().
65//
66// region_info is a pointer to the region info data structure, which may be
67// obtained by calling the function __scudo_get_region_info_addr() in the
68// crashing process. The size of the region info is available by calling the
69// function __scudo_get_region_info_size().
70//
71// memory is a pointer to a region of memory surrounding the fault address.
72// The more memory available via this pointer, the more likely it is that the
73// function will be able to analyze a crash correctly. It is recommended to
74// provide an amount of memory equal to 16 * the primary allocator's largest
75// size class either side of the fault address.
76//
77// memory_tags is a pointer to an array of memory tags for the memory accessed
78// via memory. Each byte of this array corresponds to a region of memory of size
79// equal to the architecturally defined memory tag granule size (16 on aarch64).
80//
81// memory_addr is the start address of memory in the crashing process's address
82// space.
83//
84// memory_size is the size of the memory region referred to by the memory
85// pointer.
86void __scudo_get_error_info(struct scudo_error_info *error_info,
87 uintptr_t fault_addr, const char *stack_depot,
88 size_t stack_depot_size, const char *region_info,
89 const char *ring_buffer, size_t ring_buffer_size,
90 const char *memory, const char *memory_tags,
91 uintptr_t memory_addr, size_t memory_size);
92
93enum scudo_error_type {
94 UNKNOWN,
95 USE_AFTER_FREE,
96 BUFFER_OVERFLOW,
97 BUFFER_UNDERFLOW,
98};
99
100const size_t ScudoTraceSize = 64;
101struct scudo_error_report {
102 enum scudo_error_type error_type;
103
104 uintptr_t allocation_address;
105 uintptr_t allocation_size;
106
107 uint32_t allocation_tid;
108 uintptr_t allocation_trace[ScudoTraceSize];
109
110 uint32_t deallocation_tid;
111 uintptr_t deallocation_trace[ScudoTraceSize];
112};
113
114const size_t ScudoNumErrorReports = 3;
115struct scudo_error_info {
116 struct scudo_error_report reports[ScudoNumErrorReports];
117};
118
119const char *__scudo_get_stack_depot_addr(void);
120size_t __scudo_get_stack_depot_size(void);
121
122const char *__scudo_get_region_info_addr(void);
123size_t __scudo_get_region_info_size(void);
124
125const char *__scudo_get_ring_buffer_addr(void);
126size_t __scudo_get_ring_buffer_size(void);
127
128void __scudo_get_fault_error_info(uintptr_t fault_addr,
129 struct scudo_error_info *error_info);
130
131#ifndef M_DECAY_TIME
132#define M_DECAY_TIME -100
133#endif
134
135#ifndef M_PURGE
136#define M_PURGE -101
137#endif
138
139#ifndef M_PURGE_ALL
140#define M_PURGE_ALL -104
141#endif
142
143#ifndef M_PURGE_FAST
144#define M_PURGE_FAST -105
145#endif
146
147// Tune the allocator's choice of memory tags to make it more likely that
148// a certain class of memory errors will be detected. The value argument should
149// be one of the M_MEMTAG_TUNING_* constants below.
150#ifndef M_MEMTAG_TUNING
151#define M_MEMTAG_TUNING -102
152#endif
153
154// Per-thread memory initialization tuning. The value argument should be one of:
155// 1: Disable automatic heap initialization and, where possible, memory tagging,
156// on this thread.
157// 0: Normal behavior.
158#ifndef M_THREAD_DISABLE_MEM_INIT
159#define M_THREAD_DISABLE_MEM_INIT -103
160#endif
161
162#ifndef M_CACHE_COUNT_MAX
163#define M_CACHE_COUNT_MAX -200
164#endif
165
166#ifndef M_CACHE_SIZE_MAX
167#define M_CACHE_SIZE_MAX -201
168#endif
169
170#ifndef M_TSDS_COUNT_MAX
171#define M_TSDS_COUNT_MAX -202
172#endif
173
174// Tune for buffer overflows.
175#ifndef M_MEMTAG_TUNING_BUFFER_OVERFLOW
176#define M_MEMTAG_TUNING_BUFFER_OVERFLOW 0
177#endif
178
179// Tune for use-after-free.
180#ifndef M_MEMTAG_TUNING_UAF
181#define M_MEMTAG_TUNING_UAF 1
182#endif
183
184// Print internal stats to the log.
185#ifndef M_LOG_STATS
186#define M_LOG_STATS -205
187#endif
188
189} // extern "C"
190
191#endif // SCUDO_INTERFACE_H_
192