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 #ifndef BERBERIS_GUEST_LOADER_GUEST_LOADER_H_ 18 #define BERBERIS_GUEST_LOADER_GUEST_LOADER_H_ 19 20 #include <dlfcn.h> 21 #include <link.h> 22 23 #include <cstdint> // uintptr_t 24 #include <string> 25 26 #include "berberis/guest_state/guest_addr.h" 27 #include "berberis/tiny_loader/loaded_elf_file.h" 28 29 #if defined(__BIONIC__) 30 #include <android/dlext.h> 31 #else 32 // We do not have <android/dlfcn.h> for non-bionic environments 33 // such as glibc this part is copy of necessary structures from 34 // <android/dlext.h> 35 struct android_namespace_t; 36 37 struct android_dlextinfo { 38 uint64_t flags; 39 void* reserved_addr; 40 size_t reserved_size; 41 int relro_fd; 42 int library_fd; 43 off64_t library_fd_offset; 44 struct android_namespace_t* library_namespace; 45 }; 46 #endif 47 48 namespace berberis { 49 50 struct LinkerCallbacks { 51 using android_create_namespace_fn_t = 52 android_namespace_t* (*)(const char* name, 53 const char* ld_library_path, 54 const char* default_library_path, 55 uint64_t type, 56 const char* permitted_when_isolated_path, 57 android_namespace_t* parent_namespace, 58 const void* caller_addr); 59 using android_dlopen_ext_fn_t = void* (*)(const char* filename, 60 int flags, 61 const android_dlextinfo* extinfo, 62 const void* caller_addr); 63 using android_get_exported_namespace_fn_t = android_namespace_t* (*)(const char* name); 64 using android_init_anonymous_namespace_fn_t = bool (*)(const char* shared_libs_sonames, 65 const char* library_search_path); 66 using android_link_namespaces_fn_t = bool (*)(android_namespace_t* namespace_from, 67 android_namespace_t* namespace_to, 68 const char* shared_libs_sonames); 69 using android_set_application_target_sdk_version_fn_t = void (*)(int target); 70 using dl_unwind_find_exidx_fn_t = uintptr_t (*)(uintptr_t pc, int* pcount); 71 using dladdr_fn_t = int (*)(const void* addr, Dl_info* info); 72 using dlerror_fn_t = char* (*)(); 73 using dlsym_fn_t = void* (*)(void* handle, const char* symbol, const void* caller_addr); 74 75 android_create_namespace_fn_t create_namespace_fn_ = nullptr; 76 android_dlopen_ext_fn_t dlopen_ext_fn_ = nullptr; 77 android_get_exported_namespace_fn_t get_exported_namespace_fn_ = nullptr; 78 android_init_anonymous_namespace_fn_t init_anonymous_namespace_fn_ = nullptr; 79 android_link_namespaces_fn_t link_namespaces_fn_ = nullptr; 80 android_set_application_target_sdk_version_fn_t set_application_target_sdk_version_fn_ = nullptr; 81 dl_unwind_find_exidx_fn_t dl_unwind_find_exidx_fn_ = nullptr; 82 dladdr_fn_t dladdr_fn_ = nullptr; 83 dlerror_fn_t dlerror_fn_ = nullptr; 84 dlsym_fn_t dlsym_fn_ = nullptr; 85 }; 86 87 // Loads loader vdso and initializes callbacks to loader symbols. 88 class GuestLoader { 89 public: 90 ~GuestLoader(); 91 92 // Should be called only once. 93 static GuestLoader* StartAppProcessInNewThread(std::string* error_msg); 94 95 // Initializes GuestLoader and starts the executable in the current thread. 96 // 97 // Note that this method returns only in the case of an error. Otherwise it 98 // never returns. 99 static void StartExecutable(const char* main_executable_path, 100 const char* vdso_path, 101 const char* loader_path, 102 size_t argc, 103 const char* argv[], 104 char* envp[], 105 std::string* error_msg); 106 107 // If GetInstance() called before Initialize() it will return nullptr 108 static GuestLoader* GetInstance(); 109 110 uintptr_t DlUnwindFindExidx(uintptr_t pc, int* pcount); 111 int DlAddr(const void* addr, Dl_info* info); 112 void* DlOpen(const char* libpath, int flags); 113 void* DlOpenExt(const char* libpath, int flags, const android_dlextinfo* extinfo); 114 GuestAddr DlSym(void* handle, const char* name); 115 const char* DlError(); 116 bool InitAnonymousNamespace(const char* public_ns_sonames, const char* anon_ns_library_path); 117 android_namespace_t* CreateNamespace(const char* name, 118 const char* ld_library_path, 119 const char* default_library_path, 120 uint64_t type, 121 const char* permitted_when_isolated_path, 122 android_namespace_t* parent_ns); 123 android_namespace_t* GetExportedNamespace(const char* name); 124 bool LinkNamespaces(android_namespace_t* from, 125 android_namespace_t* to, 126 const char* shared_libs_sonames); 127 void SetTargetSdkVersion(uint32_t target_sdk_version); 128 129 const struct r_debug* FindRDebug() const; 130 131 private: 132 static GuestLoader* CreateInstance(const char* main_executable_path, 133 const char* vdso_path, 134 const char* loader_path, 135 std::string* error_msg); 136 137 GuestLoader(); 138 GuestLoader(const GuestLoader&) = delete; 139 GuestLoader& operator=(const GuestLoader&) = delete; 140 141 void StartGuestMainThread(); 142 void StartGuestExecutable(size_t argc, const char* argv[], char* envp[]); 143 void SetDlErrorIfNeeded(); 144 145 // It appears that guest and host loaders share tls slot they use to store dlerror message. 146 // To work around this we need to replicate guest dlerror here. 147 std::string dl_error_holder_; 148 const char* dl_error_; 149 150 const char* main_executable_path_; 151 LoadedElfFile executable_elf_file_; 152 LoadedElfFile linker_elf_file_; 153 LoadedElfFile vdso_elf_file_; 154 const void* caller_addr_; 155 LinkerCallbacks linker_callbacks_; 156 }; 157 158 } // namespace berberis 159 160 #endif // BERBERIS_GUEST_LOADER_GUEST_LOADER_H_