1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *  * Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in
12  *    the documentation and/or other materials provided with the
13  *    distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #pragma once
30 
31 #include <malloc.h>
32 #include <stdbool.h>
33 #include <stdint.h>
34 
35 // Structures for android_mallopt.
36 #pragma clang diagnostic push
37 #pragma clang diagnostic ignored "-Wnullability-completeness"
38 typedef struct {
39   // Pointer to the buffer allocated by a call to M_GET_MALLOC_LEAK_INFO.
40   uint8_t* buffer;
41   // The size of the "info" buffer.
42   size_t overall_size;
43   // The size of a single entry.
44   size_t info_size;
45   // The sum of all allocations that have been tracked. Does not include
46   // any heap overhead.
47   size_t total_memory;
48   // The maximum number of backtrace entries.
49   size_t backtrace_size;
50 } android_mallopt_leak_info_t;
51 #pragma clang diagnostic pop
52 // Opcodes for android_mallopt.
53 
54 enum {
55   // Marks the calling process as a profileable zygote child, possibly
56   // initializing profiling infrastructure.
57   M_INIT_ZYGOTE_CHILD_PROFILING = 1,
58 #define M_INIT_ZYGOTE_CHILD_PROFILING M_INIT_ZYGOTE_CHILD_PROFILING
59   M_RESET_HOOKS = 2,
60 #define M_RESET_HOOKS M_RESET_HOOKS
61   // Set an upper bound on the total size in bytes of all allocations made
62   // using the memory allocation APIs.
63   //   arg = size_t*
64   //   arg_size = sizeof(size_t)
65   M_SET_ALLOCATION_LIMIT_BYTES = 3,
66 #define M_SET_ALLOCATION_LIMIT_BYTES M_SET_ALLOCATION_LIMIT_BYTES
67   // Called after the zygote forks to indicate this is a child.
68   M_SET_ZYGOTE_CHILD = 4,
69 #define M_SET_ZYGOTE_CHILD M_SET_ZYGOTE_CHILD
70 
71   // Options to dump backtraces of allocations. These options only
72   // work when malloc debug has been enabled.
73 
74   // Writes the backtrace information of all current allocations to a file.
75   // NOTE: arg_size has to be sizeof(FILE*) because FILE is an opaque type.
76   //   arg = FILE*
77   //   arg_size = sizeof(FILE*)
78   M_WRITE_MALLOC_LEAK_INFO_TO_FILE = 5,
79 #define M_WRITE_MALLOC_LEAK_INFO_TO_FILE M_WRITE_MALLOC_LEAK_INFO_TO_FILE
80   // Get information about the backtraces of all
81   //   arg = android_mallopt_leak_info_t*
82   //   arg_size = sizeof(android_mallopt_leak_info_t)
83   M_GET_MALLOC_LEAK_INFO = 6,
84 #define M_GET_MALLOC_LEAK_INFO M_GET_MALLOC_LEAK_INFO
85   // Free the memory allocated and returned by M_GET_MALLOC_LEAK_INFO.
86   //   arg = android_mallopt_leak_info_t*
87   //   arg_size = sizeof(android_mallopt_leak_info_t)
88   M_FREE_MALLOC_LEAK_INFO = 7,
89 #define M_FREE_MALLOC_LEAK_INFO M_FREE_MALLOC_LEAK_INFO
90   // Query whether the current process is considered to be profileable by the
91   // Android platform. Result is assigned to the arg pointer's destination.
92   //   arg = bool*
93   //   arg_size = sizeof(bool)
94   M_GET_PROCESS_PROFILEABLE = 9,
95 #define M_GET_PROCESS_PROFILEABLE M_GET_PROCESS_PROFILEABLE
96   // Maybe enable GWP-ASan. Set *arg to force GWP-ASan to be turned on,
97   // otherwise this mallopt() will internally decide whether to sample the
98   // process. The program must be single threaded at the point when the
99   // android_mallopt function is called.
100   //   arg = android_mallopt_gwp_asan_options_t*
101   //   arg_size = sizeof(android_mallopt_gwp_asan_options_t)
102   M_INITIALIZE_GWP_ASAN = 10,
103 #define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
104   // Query whether memtag stack is enabled for this process.
105   M_MEMTAG_STACK_IS_ON = 11,
106 #define M_MEMTAG_STACK_IS_ON M_MEMTAG_STACK_IS_ON
107   // Query whether the current process has the decay time enabled so that
108   // the memory from allocations are not immediately released to the OS.
109   // Result is assigned to the arg pointer's destination.
110   //   arg = bool*
111   //   arg_size = sizeof(bool)
112   M_GET_DECAY_TIME_ENABLED = 12,
113 #define M_GET_DECAY_TIME_ENABLED M_GET_DECAY_TIME_ENABLED
114 };
115 
116 #pragma clang diagnostic push
117 #pragma clang diagnostic ignored "-Wnullability-completeness"
118 typedef struct {
119   // The null-terminated name that the zygote is spawning. Because native
120   // SpecializeCommon (where the GWP-ASan mallopt() is called from) happens
121   // before argv[0] is set, we need the zygote to tell us the new app name.
122   const char* program_name = nullptr;
123 
124   // An android_mallopt(M_INITIALIZE_GWP_ASAN) is always issued on process
125   // startup and app startup, regardless of whether GWP-ASan is desired or not.
126   // This allows the process/app's desire to be overwritten by the
127   // "libc.debug.gwp_asan.*.app_default" or "libc.debug.gwp_asan.*.<name>"
128   // system properties, as well as the "GWP_ASAN_*" environment variables.
129   //
130   // Worth noting, the "libc.debug.gwp_asan.*.app_default" sysprops *do not*
131   // apply to system apps. They use the "libc.debug.gwp_asan.*.system_default"
132   // sysprops.
133   //
134   // In recoverable mode, GWP-ASan will detect heap memory safety bugs, and bug
135   // reports will be created by debuggerd, however the process will recover and
136   // continue to function as if the memory safety bug wasn't detected. This
137   // prevents any user-visible impact as apps and processes don't crash, and
138   // probably saves us some CPU time in restarting the process.
139   //
140   // Process sampling enables GWP-ASan, but only a small percentage of the time
141   // (~1%). This helps mitigate any recurring high-frequency problems in certain
142   // processes, as it's highly likely the next restart of said process won't
143   // have GWP-ASan. In addition, for system processes and system apps, this
144   // allows us to mitigate system-wide memory overhead concerns, as each
145   // GWP-ASan enabled process uses ~70KiB of extra memory.
146   enum Mode {
147     // Used by default for apps, or by those that have an explicit
148     // `gwpAsanMode=default` in the manifest.
149     //
150     // Result:
151     //  - Android 13 and before: GWP-ASan is not enabled.
152     //  - Android 14 and after: Enables GWP-ASan with process sampling in
153     //    recoverable mode.
154     APP_MANIFEST_DEFAULT = 3,
155     // This is used by apps that have `gwpAsanMode=always` in the manifest.
156     //
157     // Result:
158     //  - Android 14 and before: Enables GWP-ASan in non-recoverable mode,
159     //    without process sampling.
160     //  - Android 15 and after: Enables GWP-ASan in recoverable mode, without
161     //    process sampling.
162     APP_MANIFEST_ALWAYS = 0,
163     // This is used by apps that have `gwpAsanMode=never` in the manifest.
164     //
165     // Result:
166     //  - GWP-ASan is not enabled, unless it's force-enabled by a system
167     //    property or environment variable.
168     APP_MANIFEST_NEVER = 2,
169     // Used by system processes and system apps.
170     //
171     // Result:
172     //  - Android 14 and before: Enables GWP-ASan with process sampling in
173     //    non-recoverable mode.
174     //  - Android 15 and after: Enables GWP-ASan with process sampling in
175     //    recoverable mode.
176     SYSTEM_PROCESS_OR_SYSTEM_APP = 1,
177     // Next enum value = 4. Numbered non-sequentially above to preserve ABI
178     // stability, but now ordered more logically.
179   };
180 
181   Mode mode = APP_MANIFEST_NEVER;
182 } android_mallopt_gwp_asan_options_t;
183 #pragma clang diagnostic pop
184 // Manipulates bionic-specific handling of memory allocation APIs such as
185 // malloc. Only for use by the Android platform and APEXes.
186 //
187 // On success, returns true. On failure, returns false and sets errno.
188 extern "C" bool android_mallopt(int opcode, void* _Nullable arg, size_t arg_size);
189