1 // Copyright 2016 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifdef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LINKER_WRAPPED_SYMBOLS_H_
6 #error This header is meant to be included only once by allocator_shim.cc
7 #endif
8
9 #ifndef PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LINKER_WRAPPED_SYMBOLS_H_
10 #define PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LINKER_WRAPPED_SYMBOLS_H_
11
12 // This header overrides the __wrap_X symbols when using the link-time
13 // -Wl,-wrap,malloc shim-layer approach (see README.md).
14 // All references to malloc, free, etc. within the linker unit that gets the
15 // -wrap linker flags (e.g., libchrome.so) will be rewritten to the
16 // linker as references to __wrap_malloc, __wrap_free, which are defined here.
17
18 #include "partition_alloc/partition_alloc_buildflags.h"
19
20 #if BUILDFLAG(USE_ALLOCATOR_SHIM)
21 #include <algorithm>
22 #include <cstring>
23
24 #include "partition_alloc/shim/allocator_shim_internals.h"
25
26 extern "C" {
27
__wrap_calloc(size_t n,size_t size)28 SHIM_ALWAYS_EXPORT void* __wrap_calloc(size_t n, size_t size) {
29 return ShimCalloc(n, size, nullptr);
30 }
31
__wrap_free(void * ptr)32 SHIM_ALWAYS_EXPORT void __wrap_free(void* ptr) {
33 ShimFree(ptr, nullptr);
34 }
35
__wrap_malloc(size_t size)36 SHIM_ALWAYS_EXPORT void* __wrap_malloc(size_t size) {
37 return ShimMalloc(size, nullptr);
38 }
39
__wrap_memalign(size_t align,size_t size)40 SHIM_ALWAYS_EXPORT void* __wrap_memalign(size_t align, size_t size) {
41 return ShimMemalign(align, size, nullptr);
42 }
43
__wrap_posix_memalign(void ** res,size_t align,size_t size)44 SHIM_ALWAYS_EXPORT int __wrap_posix_memalign(void** res,
45 size_t align,
46 size_t size) {
47 return ShimPosixMemalign(res, align, size);
48 }
49
__wrap_pvalloc(size_t size)50 SHIM_ALWAYS_EXPORT void* __wrap_pvalloc(size_t size) {
51 return ShimPvalloc(size);
52 }
53
__wrap_realloc(void * address,size_t size)54 SHIM_ALWAYS_EXPORT void* __wrap_realloc(void* address, size_t size) {
55 return ShimRealloc(address, size, nullptr);
56 }
57
__wrap_valloc(size_t size)58 SHIM_ALWAYS_EXPORT void* __wrap_valloc(size_t size) {
59 return ShimValloc(size, nullptr);
60 }
61
__wrap_malloc_usable_size(void * address)62 SHIM_ALWAYS_EXPORT size_t __wrap_malloc_usable_size(void* address) {
63 return ShimGetSizeEstimate(address, nullptr);
64 }
65
66 const size_t kPathMaxSize = 8192;
67 static_assert(kPathMaxSize >= PATH_MAX, "");
68
69 extern char* __wrap_strdup(const char* str);
70
71 // Override <cstdlib>
72
73 extern char* __real_realpath(const char* path, char* resolved_path);
74
__wrap_realpath(const char * path,char * resolved_path)75 SHIM_ALWAYS_EXPORT char* __wrap_realpath(const char* path,
76 char* resolved_path) {
77 if (resolved_path) {
78 return __real_realpath(path, resolved_path);
79 }
80
81 char buffer[kPathMaxSize];
82 if (!__real_realpath(path, buffer)) {
83 return nullptr;
84 }
85 return __wrap_strdup(buffer);
86 }
87
88 // Override <cstring> functions
89
__wrap_strdup(const char * str)90 SHIM_ALWAYS_EXPORT char* __wrap_strdup(const char* str) {
91 std::size_t length = std::strlen(str) + 1;
92 void* buffer = ShimMalloc(length, nullptr);
93 if (!buffer) {
94 return nullptr;
95 }
96 return reinterpret_cast<char*>(std::memcpy(buffer, str, length));
97 }
98
__wrap_strndup(const char * str,size_t n)99 SHIM_ALWAYS_EXPORT char* __wrap_strndup(const char* str, size_t n) {
100 std::size_t length = std::min(std::strlen(str), n);
101 char* buffer = reinterpret_cast<char*>(ShimMalloc(length + 1, nullptr));
102 if (!buffer) {
103 return nullptr;
104 }
105 std::memcpy(buffer, str, length);
106 buffer[length] = '\0';
107 return buffer;
108 }
109
110 // Override <unistd.h>
111
112 extern char* __real_getcwd(char* buffer, size_t size);
113
__wrap_getcwd(char * buffer,size_t size)114 SHIM_ALWAYS_EXPORT char* __wrap_getcwd(char* buffer, size_t size) {
115 if (buffer) {
116 return __real_getcwd(buffer, size);
117 }
118
119 if (!size) {
120 size = kPathMaxSize;
121 }
122 char local_buffer[size];
123 if (!__real_getcwd(local_buffer, size)) {
124 return nullptr;
125 }
126 return __wrap_strdup(local_buffer);
127 }
128
129 // Override stdio.h
130
131 // This is non-standard (_GNU_SOURCE only), but implemented by Bionic on
132 // Android, and used by libc++.
__wrap_vasprintf(char ** strp,const char * fmt,va_list va_args)133 SHIM_ALWAYS_EXPORT int __wrap_vasprintf(char** strp,
134 const char* fmt,
135 va_list va_args) {
136 // There are cases where we need to use the list of arguments twice, namely
137 // when the original buffer is too small. It is not allowed to walk the list
138 // twice, so make a copy for the second invocation of vsnprintf().
139 va_list va_args_copy;
140 va_copy(va_args_copy, va_args);
141
142 constexpr int kInitialSize = 128;
143 *strp = static_cast<char*>(
144 malloc(kInitialSize)); // Our malloc() doesn't return nullptr.
145
146 int actual_size = vsnprintf(*strp, kInitialSize, fmt, va_args);
147 if (actual_size < 0) {
148 va_end(va_args_copy);
149 return actual_size;
150 }
151 *strp =
152 static_cast<char*>(realloc(*strp, static_cast<size_t>(actual_size + 1)));
153
154 // Now we know the size. This is not very efficient, but we cannot really do
155 // better without accessing internal libc functions, or reimplementing
156 // *printf().
157 //
158 // This is very lightly used in Chromium in practice, see crbug.com/116558 for
159 // details.
160 if (actual_size >= kInitialSize) {
161 int ret = vsnprintf(*strp, static_cast<size_t>(actual_size + 1), fmt,
162 va_args_copy);
163 va_end(va_args_copy);
164 return ret;
165 }
166
167 va_end(va_args_copy);
168 return actual_size;
169 }
170
__wrap_asprintf(char ** strp,const char * fmt,...)171 SHIM_ALWAYS_EXPORT int __wrap_asprintf(char** strp, const char* fmt, ...) {
172 va_list va_args;
173 va_start(va_args, fmt);
174 int retval = vasprintf(strp, fmt, va_args);
175 va_end(va_args);
176 return retval;
177 }
178
179 } // extern "C"
180
181 #endif // BUILDFLAG(USE_ALLOCATOR_SHIM)
182
183 #endif // PARTITION_ALLOC_SHIM_ALLOCATOR_SHIM_OVERRIDE_LINKER_WRAPPED_SYMBOLS_H_
184