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