blob: 79e40723765f8fb3c67cb290456fa8ac8df83e91 [file] [log] [blame]
Christopher Ferris0ac5da02024-11-07 06:59:33 +00001/*
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
45extern bool gZygoteChild;
46extern _Atomic bool gZygoteChildProfileable;
47
48bool WriteMallocLeakInfo(FILE* fp);
49bool GetMallocLeakInfo(android_mallopt_leak_info_t* leak_info);
50bool 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
59extern "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}