1 /*
2 * Copyright (C) 2023 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "berberis/guest_loader/guest_loader.h"
18
19 #include <cinttypes>
20 #include <string>
21
22 #include "berberis/base/tracing.h"
23
24 #include "guest_loader_impl.h" // FindSymbol
25
26 namespace berberis {
27
28 namespace {
29
uninitialized_create_namespace(const char *,const char *,const char *,uint64_t,const char *,android_namespace_t *,const void *)30 android_namespace_t* uninitialized_create_namespace(const char* /* name */,
31 const char* /* ld_library_path */,
32 const char* /* default_library_path */,
33 uint64_t /* type */,
34 const char* /* permitted_when_isolated_path */,
35 android_namespace_t* /* parent_namespace */,
36 const void* /* caller_addr */) {
37 return nullptr;
38 }
39
uninitialized_dlopen_ext(const char *,int,const android_dlextinfo *,const void *)40 void* uninitialized_dlopen_ext(const char* /* filename */,
41 int /* flags */,
42 const android_dlextinfo* /* extinfo */,
43 const void* /* caller_addr */) {
44 return nullptr;
45 }
46
uninitialized_init_anonymous_namespace(const char *,const char *)47 bool uninitialized_init_anonymous_namespace(const char* /* shared_libs_sonames */,
48 const char* /* library_search_path */) {
49 return false;
50 }
51
uninitialized_link_namespaces(android_namespace_t *,android_namespace_t *,const char *)52 bool uninitialized_link_namespaces(android_namespace_t* /* namespace_from */,
53 android_namespace_t* /* namespace_to */,
54 const char* /* shared_libs_sonames */) {
55 return false;
56 }
57
uninitialized_dl_unwind_find_exidx(uintptr_t,int *)58 uintptr_t uninitialized_dl_unwind_find_exidx(uintptr_t /* pc */, int* /* pcount */) {
59 return 0;
60 }
61
uninitialized_dladdr(const void *,Dl_info *)62 int uninitialized_dladdr(const void* /* addr */, Dl_info* /* info */) {
63 return 0;
64 }
65
uninitialized_dlerror()66 char* uninitialized_dlerror() {
67 static char error_msg[] =
68 "Linker callbacks are not initialized, likely because "
69 "the loaded executable is a static executable";
70 return error_msg;
71 }
72
uninitialized_dlsym(void *,const char *,const void *)73 void* uninitialized_dlsym(void* /* handle */,
74 const char* /* symbol */,
75 const void* /* caller_addr */) {
76 return nullptr;
77 }
78
79 LinkerCallbacks g_uninitialized_callbacks{
80 .create_namespace_fn_ = uninitialized_create_namespace,
81 .dlopen_ext_fn_ = uninitialized_dlopen_ext,
82 .init_anonymous_namespace_fn_ = uninitialized_init_anonymous_namespace,
83 .link_namespaces_fn_ = uninitialized_link_namespaces,
84 .dl_unwind_find_exidx_fn_ = uninitialized_dl_unwind_find_exidx,
85 .dladdr_fn_ = uninitialized_dladdr,
86 .dlerror_fn_ = uninitialized_dlerror,
87 .dlsym_fn_ = uninitialized_dlsym,
88 };
89
90 } // namespace
91
DlUnwindFindExidx(uintptr_t pc,int * pcount)92 uintptr_t GuestLoader::DlUnwindFindExidx(uintptr_t pc, int* pcount) {
93 TRACE("GuestLoader::DlUnwindFindExidx(pc=%p, pcount=%p)", reinterpret_cast<void*>(pc), pcount);
94 return linker_callbacks_.dl_unwind_find_exidx_fn_(pc, pcount);
95 }
96
DlAddr(const void * addr,Dl_info * info)97 int GuestLoader::DlAddr(const void* addr, Dl_info* info) {
98 TRACE("GuestLoader::DlAddr(addr=%p, info=%p)", addr, info);
99 // dladdr does *not* set dlerror
100 return linker_callbacks_.dladdr_fn_(addr, info);
101 }
102
DlOpen(const char * libpath,int flags)103 void* GuestLoader::DlOpen(const char* libpath, int flags) {
104 TRACE("GuestLoader::DlOpen(libpath=%s, flags=0x%x)", libpath, flags);
105 return DlOpenExt(libpath, flags, nullptr);
106 }
107
DlOpenExt(const char * libpath,int flags,const android_dlextinfo * extinfo)108 void* GuestLoader::DlOpenExt(const char* libpath, int flags, const android_dlextinfo* extinfo) {
109 TRACE("GuestLoader::DlOpen(libpath=\"%s\", flags=0x%x, extinfo=%p)", libpath, flags, extinfo);
110 auto handle = linker_callbacks_.dlopen_ext_fn_(libpath, flags, extinfo, caller_addr_);
111 TRACE("GuestLoader::DlOpen(...) = %p", handle);
112 SetDlErrorIfNeeded();
113 return handle;
114 }
115
DlSym(void * handle,const char * name)116 GuestAddr GuestLoader::DlSym(void* handle, const char* name) {
117 TRACE("GuestLoader::DlSym(handle=%p, name=\"%s\")", handle, name);
118 auto* result = linker_callbacks_.dlsym_fn_(handle, name, caller_addr_);
119 SetDlErrorIfNeeded();
120 return ToGuestAddr(result);
121 }
122
DlError()123 const char* GuestLoader::DlError() {
124 TRACE("GuestLoader::DlError()");
125 const char* dlerror_msg = dl_error_;
126 dl_error_ = nullptr;
127 return dlerror_msg;
128 }
129
InitAnonymousNamespace(const char * public_ns_sonames,const char * anon_ns_library_path)130 bool GuestLoader::InitAnonymousNamespace(const char* public_ns_sonames,
131 const char* anon_ns_library_path) {
132 TRACE(
133 "GuestLoader::InitAnonymousNamespace("
134 "public_ns_sonames=\"%s\", "
135 "anon_ns_library_path=\"%s\")",
136 public_ns_sonames,
137 anon_ns_library_path);
138 #if defined(__BIONIC__)
139 SetTargetSdkVersion(android_get_application_target_sdk_version());
140 #endif
141 bool success =
142 linker_callbacks_.init_anonymous_namespace_fn_(public_ns_sonames, anon_ns_library_path);
143 SetDlErrorIfNeeded();
144 return success;
145 }
146
CreateNamespace(const char * name,const char * ld_library_path,const char * default_library_path,uint64_t type,const char * permitted_when_isolated_path,android_namespace_t * parent_ns)147 android_namespace_t* GuestLoader::CreateNamespace(const char* name,
148 const char* ld_library_path,
149 const char* default_library_path,
150 uint64_t type,
151 const char* permitted_when_isolated_path,
152 android_namespace_t* parent_ns) {
153 TRACE(
154 "GuestLoader::CreateNamespace("
155 "name=\"%s\", "
156 "ld_library_path=\"%s\", "
157 "default_library_path=\"%s\", "
158 "type=%" PRIx64
159 ", "
160 "permitted_when_isolated_path=\"%s\", "
161 "parent_ns=%p)",
162 name,
163 ld_library_path,
164 default_library_path,
165 type,
166 permitted_when_isolated_path,
167 parent_ns);
168
169 #if defined(__BIONIC__)
170 SetTargetSdkVersion(android_get_application_target_sdk_version());
171 #endif
172
173 auto result = linker_callbacks_.create_namespace_fn_(name,
174 ld_library_path,
175 default_library_path,
176 type,
177 permitted_when_isolated_path,
178 parent_ns,
179 caller_addr_);
180 TRACE("GuestLoader::CreateNamespace(...) .. = %p", result);
181 SetDlErrorIfNeeded();
182 return result;
183 }
184
GetExportedNamespace(const char * name)185 android_namespace_t* GuestLoader::GetExportedNamespace(const char* name) {
186 auto result = linker_callbacks_.get_exported_namespace_fn_(name);
187 TRACE("GuestLoader::GetExportedNamespace(name=\"%s\") = %p", name, result);
188 // Does *not* set dlerror()
189 return result;
190 }
191
LinkNamespaces(android_namespace_t * from,android_namespace_t * to,const char * shared_libs_sonames)192 bool GuestLoader::LinkNamespaces(android_namespace_t* from,
193 android_namespace_t* to,
194 const char* shared_libs_sonames) {
195 TRACE("GuestLoader::LinkNamespaces(from=%p, to=%p, shared_libs_sonames=\"%s\")",
196 from,
197 to,
198 shared_libs_sonames);
199 bool success = linker_callbacks_.link_namespaces_fn_(from, to, shared_libs_sonames);
200 SetDlErrorIfNeeded();
201 return success;
202 }
203
SetTargetSdkVersion(uint32_t target_sdk_version)204 void GuestLoader::SetTargetSdkVersion(uint32_t target_sdk_version) {
205 TRACE("GuestLoader::SetTargetSdkVersion(%u)", target_sdk_version);
206 linker_callbacks_.set_application_target_sdk_version_fn_(target_sdk_version);
207 }
208
SetDlErrorIfNeeded()209 void GuestLoader::SetDlErrorIfNeeded() {
210 const char* dl_error = linker_callbacks_.dlerror_fn_();
211 if (dl_error != nullptr) {
212 dl_error_holder_ = dl_error;
213 dl_error_ = dl_error_holder_.c_str();
214 }
215 }
216
InitializeLinkerCallbacksToStubs(LinkerCallbacks * linker_callbacks)217 void InitializeLinkerCallbacksToStubs(LinkerCallbacks* linker_callbacks) {
218 *linker_callbacks = g_uninitialized_callbacks;
219 }
220
InitializeLinkerCallbacks(LinkerCallbacks * linker_callbacks,const LoadedElfFile & linker_elf_file,std::string * error_msg)221 bool InitializeLinkerCallbacks(LinkerCallbacks* linker_callbacks,
222 const LoadedElfFile& linker_elf_file,
223 std::string* error_msg) {
224 return FindSymbol(linker_elf_file,
225 "__loader_android_create_namespace",
226 &linker_callbacks->create_namespace_fn_,
227 error_msg) &&
228 FindSymbol(linker_elf_file,
229 "__loader_android_dlopen_ext",
230 &linker_callbacks->dlopen_ext_fn_,
231 error_msg) &&
232 FindSymbol(linker_elf_file,
233 "__loader_android_get_exported_namespace",
234 &linker_callbacks->get_exported_namespace_fn_,
235 error_msg) &&
236 FindSymbol(linker_elf_file,
237 "__loader_android_init_anonymous_namespace",
238 &linker_callbacks->init_anonymous_namespace_fn_,
239 error_msg) &&
240 FindSymbol(linker_elf_file,
241 "__loader_android_link_namespaces",
242 &linker_callbacks->link_namespaces_fn_,
243 error_msg) &&
244 FindSymbol(linker_elf_file,
245 "__loader_android_set_application_target_sdk_version",
246 &linker_callbacks->set_application_target_sdk_version_fn_,
247 error_msg) &&
248 FindSymbol(linker_elf_file, "__loader_dladdr", &linker_callbacks->dladdr_fn_, error_msg) &&
249 FindSymbol(
250 linker_elf_file, "__loader_dlerror", &linker_callbacks->dlerror_fn_, error_msg) &&
251 FindSymbol(linker_elf_file, "__loader_dlsym", &linker_callbacks->dlsym_fn_, error_msg);
252 }
253
254 } // namespace berberis
255