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_