1 /*
2  * Copyright (C) 2024 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 #define LOG_TAG "nativebridgesupport"
18 
19 #include <android-base/properties.h>
20 #include <dlfcn.h>
21 #include <log/log_main.h>
22 
23 #include "native_bridge_support/guest_state_accessor/accessor.h"
24 
25 #if defined(__ANDROID__)
26 #include "native_bridge_support/guest_state_accessor/dlext_namespaces.h"
27 #endif
28 
OpenSystemLibrary(const char * path,int flags)29 void* OpenSystemLibrary(const char* path, int flags) {
30 #if defined(__ANDROID__)
31   // The system namespace is called "default" for binaries in /system and
32   // "system" for those in the Runtime APEX. Try "system" first since
33   // "default" always exists.
34   // TODO(b/185587109): Get rid of this error prone logic.
35   android_namespace_t* system_ns = android_get_exported_namespace("system");
36   if (system_ns == nullptr) {
37     system_ns = android_get_exported_namespace("default");
38     if (system_ns == nullptr) {
39       ALOGE("Failed to get system namespace for loading %s", path);
40     }
41   }
42   const android_dlextinfo dlextinfo = {
43       .flags = ANDROID_DLEXT_USE_NAMESPACE,
44       .library_namespace = system_ns,
45   };
46 
47   return android_dlopen_ext(path, flags, &dlextinfo);
48 #else
49   return dlopen(path, flags);
50 #endif
51 }
52 
LoadGuestStateRegisters(const void * guest_state_data,size_t guest_state_data_size,NativeBridgeGuestRegs * guest_regs)53 int LoadGuestStateRegisters(const void* guest_state_data,
54                             size_t guest_state_data_size,
55                             NativeBridgeGuestRegs* guest_regs) {
56   std::string library_name = android::base::GetProperty(
57       "ro.dalvik.vm.native.bridge", /*default_value=*/"");
58   if (library_name.empty()) {
59     return NATIVE_BRIDGE_GUEST_STATE_ACCESSOR_ERROR_INVALID_STATE;
60   }
61 
62   void *proxy = OpenSystemLibrary(library_name.c_str(), RTLD_NOW | RTLD_LOCAL);
63   if (!proxy) {
64     ALOGE("dlopen failed: %s: %s", library_name.c_str(), dlerror());
65     return NATIVE_BRIDGE_GUEST_STATE_ACCESSOR_ERROR_INVALID_STATE;
66   }
67 
68   using LoadGuestStateRegistersFunc =
69       int (*)(const void *, size_t, NativeBridgeGuestRegs *);
70   LoadGuestStateRegistersFunc LoadGuestStateRegistersImpl =
71       reinterpret_cast<LoadGuestStateRegistersFunc>(
72           dlsym(proxy, "LoadGuestStateRegisters"));
73   if (!LoadGuestStateRegistersImpl) {
74     ALOGE("failed to initialize proxy library LoadGuestStateRegisters: %s", dlerror());
75     return NATIVE_BRIDGE_GUEST_STATE_ACCESSOR_ERROR_INVALID_STATE;
76   }
77 
78   return LoadGuestStateRegistersImpl(guest_state_data, guest_state_data_size, guest_regs);
79 }
80