xref: /aosp_15_r20/bionic/libc/bionic/android_mallopt.cpp (revision 8d67ca893c1523eb926b9080dbe4e2ffd2a27ba1)
1 /*
2  * Copyright (C) 2009 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 #include <errno.h>
30 #include <stdatomic.h>
31 
32 #include <platform/bionic/malloc.h>
33 #include <private/bionic_globals.h>
34 
35 #include "gwp_asan_wrappers.h"
36 #include "malloc_limit.h"
37 
38 #if !defined(LIBC_STATIC)
39 #include <stdio.h>
40 
41 #include <private/bionic_defs.h>
42 
43 #include "malloc_heapprofd.h"
44 
45 extern bool gZygoteChild;
46 extern _Atomic bool gZygoteChildProfileable;
47 
48 bool WriteMallocLeakInfo(FILE* fp);
49 bool GetMallocLeakInfo(android_mallopt_leak_info_t* leak_info);
50 bool FreeMallocLeakInfo(android_mallopt_leak_info_t* leak_info);
51 #endif
52 
53 // =============================================================================
54 // Platform-internal mallopt variant.
55 // =============================================================================
56 #if !defined(LIBC_STATIC)
57 __BIONIC_WEAK_FOR_NATIVE_BRIDGE
58 #endif
android_mallopt(int opcode,void * arg,size_t arg_size)59 extern "C" bool android_mallopt(int opcode, void* arg, size_t arg_size) {
60   // Functionality available in both static and dynamic libc.
61   if (opcode == M_GET_DECAY_TIME_ENABLED) {
62     if (arg == nullptr || arg_size != sizeof(bool)) {
63       errno = EINVAL;
64       return false;
65     }
66     *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->decay_time_enabled);
67     return true;
68   }
69   if (opcode == M_INITIALIZE_GWP_ASAN) {
70     if (arg == nullptr || arg_size != sizeof(android_mallopt_gwp_asan_options_t)) {
71       errno = EINVAL;
72       return false;
73     }
74 
75     return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
76   }
77   if (opcode == M_MEMTAG_STACK_IS_ON) {
78     if (arg == nullptr || arg_size != sizeof(bool)) {
79       errno = EINVAL;
80       return false;
81     }
82     *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_memtag_stack);
83     return true;
84   }
85   if (opcode == M_SET_ALLOCATION_LIMIT_BYTES) {
86     return LimitEnable(arg, arg_size);
87   }
88 
89 #if defined(LIBC_STATIC)
90   errno = ENOTSUP;
91   return false;
92 #else
93   if (opcode == M_SET_ZYGOTE_CHILD) {
94     if (arg != nullptr || arg_size != 0) {
95       errno = EINVAL;
96       return false;
97     }
98     gZygoteChild = true;
99     return true;
100   }
101   if (opcode == M_INIT_ZYGOTE_CHILD_PROFILING) {
102     if (arg != nullptr || arg_size != 0) {
103       errno = EINVAL;
104       return false;
105     }
106     atomic_store_explicit(&gZygoteChildProfileable, true, memory_order_release);
107     // Also check if heapprofd should start profiling from app startup.
108     HeapprofdInitZygoteChildProfiling();
109     return true;
110   }
111   if (opcode == M_GET_PROCESS_PROFILEABLE) {
112     if (arg == nullptr || arg_size != sizeof(bool)) {
113       errno = EINVAL;
114       return false;
115     }
116     // Native processes are considered profileable. Zygote children are considered
117     // profileable only when appropriately tagged.
118     *reinterpret_cast<bool*>(arg) =
119         !gZygoteChild || atomic_load_explicit(&gZygoteChildProfileable, memory_order_acquire);
120     return true;
121   }
122   if (opcode == M_WRITE_MALLOC_LEAK_INFO_TO_FILE) {
123     if (arg == nullptr || arg_size != sizeof(FILE*)) {
124       errno = EINVAL;
125       return false;
126     }
127     return WriteMallocLeakInfo(reinterpret_cast<FILE*>(arg));
128   }
129   if (opcode == M_GET_MALLOC_LEAK_INFO) {
130     if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
131       errno = EINVAL;
132       return false;
133     }
134     return GetMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
135   }
136   if (opcode == M_FREE_MALLOC_LEAK_INFO) {
137     if (arg == nullptr || arg_size != sizeof(android_mallopt_leak_info_t)) {
138       errno = EINVAL;
139       return false;
140     }
141     return FreeMallocLeakInfo(reinterpret_cast<android_mallopt_leak_info_t*>(arg));
142   }
143   // Try heapprofd's mallopt, as it handles options not covered here.
144   return HeapprofdMallopt(opcode, arg, arg_size);
145 #endif
146 }
147