1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dynamic_loader.h"
17
18 #include "cj_hilog.h"
19 #include <dlfcn.h>
20 #include <cstdio>
21 #include <securec.h>
22 #include <unordered_set>
23 #include <string>
24
25 namespace {
26 constexpr auto ERROR_BUF_SIZE = 255;
27 static char g_dlError[ERROR_BUF_SIZE];
28 static std::unordered_set<std::string> HasInited;
29 static char* g_sharedLibsSonames = nullptr;
30
31 enum ErrorCode {
32 OUT_OF_MEMORY = 12,
33 FILE_EXISTS = 17,
34 INVALID_ARGUMENT = 22,
35 };
36
ReadDlError()37 static void ReadDlError()
38 {
39 char* errMsg = dlerror();
40 if (!errMsg) {
41 return;
42 }
43 auto ends = sprintf_s(g_dlError, sizeof(g_dlError), "%s", errMsg);
44 if (ends >= ERROR_BUF_SIZE) {
45 g_dlError[ERROR_BUF_SIZE - 1] = '\0';
46 } else {
47 g_dlError[ends] = '\0';
48 }
49 }
50
InitSharedLibsSonames()51 static void InitSharedLibsSonames()
52 {
53 if (g_sharedLibsSonames != nullptr) {
54 return;
55 }
56 const char* allowList[] = {
57 "libc.so",
58 "libdl.so",
59 "libm.so",
60 "libz.so",
61 "libclang_rt.asan.so",
62 "libclang_rt.tsan.so",
63 // z library
64 "libace_napi.z.so",
65 "libace_ndk.z.so",
66 "libbundle_ndk.z.so",
67 "libdeviceinfo_ndk.z.so",
68 "libEGL.so",
69 "libGLESv3.so",
70 "libhiappevent_ndk.z.so",
71 "libhuks_ndk.z.so",
72 "libhukssdk.z.so",
73 "libnative_drawing.so",
74 "libnative_window.so",
75 "libnative_buffer.so",
76 "libnative_vsync.so",
77 "libOpenSLES.so",
78 "libpixelmap_ndk.z.so",
79 "libimage_ndk.z.so",
80 "libimage_receiver_ndk.z.so",
81 "libimage_source_ndk.z.so",
82 "librawfile.z.so",
83 "libuv.so",
84 "libhilog.so",
85 "libnative_image.so",
86 "libnative_media_adec.so",
87 "libnative_media_aenc.so",
88 "libnative_media_codecbase.so",
89 "libnative_media_core.so",
90 "libnative_media_vdec.so",
91 "libnative_media_venc.so",
92 "libnative_media_avmuxer.so",
93 "libnative_media_avdemuxer.so",
94 "libnative_media_avsource.so",
95 "libnative_avscreen_capture.so",
96 "libavplayer.so",
97 // adaptor library
98 "libohosadaptor.so",
99 "libusb_ndk.z.so",
100 "libvulkan.so",
101 };
102
103 size_t allowListLength = sizeof(allowList) / sizeof(char*);
104 int32_t sharedLibsSonamesLength = 1;
105 for (size_t i = 0; i < allowListLength; i++) {
106 sharedLibsSonamesLength += strlen(allowList[i]) + 1;
107 }
108 g_sharedLibsSonames = new char[sharedLibsSonamesLength];
109 int32_t cursor = 0;
110 for (size_t i = 0; i < allowListLength; i++) {
111 if (sprintf_s(g_sharedLibsSonames + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
112 delete[] g_sharedLibsSonames;
113 g_sharedLibsSonames = nullptr;
114 return;
115 }
116 cursor += strlen(allowList[i]) + 1;
117 }
118 g_sharedLibsSonames[cursor] = '\0';
119 }
120 }
121
122 extern "C" {
DynamicInitNamespace(Dl_namespace * ns,void * parent,const char * entries,const char * name)123 void DynamicInitNamespace(Dl_namespace* ns, void* parent, const char* entries, const char* name)
124 {
125 if (!ns || !entries || !name) {
126 LOGE("Invaild args for init namespace.");
127 return;
128 }
129 if (HasInited.count(std::string(name))) {
130 return;
131 }
132 dlns_init(ns, name);
133 auto status = dlns_create2(ns, entries, 0);
134 std::string errMsg;
135 if (status != 0) {
136 switch (status) {
137 case FILE_EXISTS:
138 errMsg = "dlns_create failed: File exists";
139 break;
140 case INVALID_ARGUMENT:
141 errMsg = "dlns_create failed: Invalid argument";
142 break;
143 case OUT_OF_MEMORY:
144 errMsg = "dlns_create failed: Out of memory";
145 break;
146 default:
147 errMsg = "dlns_create failed, status: " + std::to_string(status);
148 }
149 if (sprintf_s(g_dlError, sizeof(g_dlError), errMsg.c_str()) == -1) {
150 LOGE("Fail to generate error msg.");
151 return;
152 }
153 return;
154 }
155 if (parent) {
156 dlns_inherit((Dl_namespace*)parent, ns, "allow_all_shared_libs");
157 }
158 Dl_namespace current;
159 dlns_get(nullptr, ¤t);
160 if (strcmp(name, "cj_app") != 0) {
161 dlns_inherit(ns, ¤t, "allow_all_shared_libs");
162 } else {
163 InitSharedLibsSonames();
164 dlns_inherit(ns, ¤t, g_sharedLibsSonames);
165 if (g_sharedLibsSonames != nullptr) {
166 delete[] g_sharedLibsSonames;
167 g_sharedLibsSonames = nullptr;
168 }
169 }
170 Dl_namespace chip_sdk;
171 dlns_get("cj_chipsdk", &chip_sdk);
172 dlns_inherit(ns, &chip_sdk, "allow_all_shared_libs");
173 HasInited.insert(std::string(name));
174 }
175
DynamicLoadLibrary(Dl_namespace * ns,const char * dlPath,unsigned int mode)176 void* DynamicLoadLibrary(Dl_namespace *ns, const char* dlPath, unsigned int mode)
177 {
178 if (ns == nullptr) {
179 dlns_get("cj_app", ns);
180 }
181
182 auto result = dlopen_ns(ns, dlPath, mode | RTLD_GLOBAL | RTLD_NOW);
183 if (!result) {
184 ReadDlError();
185 }
186 return result;
187 }
188
DynamicFindSymbol(void * so,const char * symbol)189 void* DynamicFindSymbol(void* so, const char* symbol)
190 {
191 return dlsym(so, symbol);
192 }
193
DynamicFreeLibrary(void * so)194 void DynamicFreeLibrary(void* so)
195 {
196 (void)dlclose(so);
197 }
198
DynamicGetError()199 const char* DynamicGetError()
200 {
201 return g_dlError;
202 }
203 }
204