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" {
DynamicInitNewNamespace(Dl_namespace * ns,const char * entries,const char * name)123 void DynamicInitNewNamespace(Dl_namespace* ns,
124 const char* entries, const char* name)
125 {
126 if (!ns || !entries || !name) {
127 LOGE("Invaild args for init namespace.");
128 return;
129 }
130 if (HasInited.count(std::string(name))) {
131 return;
132 }
133 dlns_init(ns, name);
134 auto status = dlns_create2(ns, entries, 0);
135 std::string errMsg;
136 if (status != 0) {
137 switch (status) {
138 case FILE_EXISTS:
139 errMsg = "dlns_create failed: File exists";
140 break;
141 case INVALID_ARGUMENT:
142 errMsg = "dlns_create failed: Invalid argument";
143 break;
144 case OUT_OF_MEMORY:
145 errMsg = "dlns_create failed: Out of memory";
146 break;
147 default:
148 errMsg = "dlns_create failed, status: " + std::to_string(status);
149 }
150 if (sprintf_s(g_dlError, sizeof(g_dlError), errMsg.c_str()) == -1) {
151 LOGE("Fail to generate error msg.");
152 return;
153 }
154 return;
155 }
156 Dl_namespace current;
157 dlns_get(nullptr, ¤t);
158 if (strcmp(name, "moduleNs_default") != 0) {
159 dlns_inherit(ns, ¤t, "allow_all_shared_libs");
160 } else {
161 InitSharedLibsSonames();
162 dlns_inherit(ns, ¤t, g_sharedLibsSonames);
163 if (g_sharedLibsSonames != nullptr) {
164 delete[] g_sharedLibsSonames;
165 g_sharedLibsSonames = nullptr;
166 }
167 }
168 Dl_namespace cjnative;
169 dlns_get("ndk", &cjnative);
170 dlns_inherit(ns, &cjnative, "allow_all_shared_libs");
171 dlns_inherit(&cjnative, ¤t, "allow_all_shared_libs");
172 dlns_inherit(¤t, &cjnative, "allow_all_shared_libs");
173 HasInited.insert(std::string(name));
174 }
175
DynamicInitNamespace(Dl_namespace * ns,void * parent,const char * entries,const char * name)176 void DynamicInitNamespace(Dl_namespace* ns, void* parent, const char* entries, const char* name)
177 {
178 if (!ns || !entries || !name) {
179 LOGE("Invaild args for init namespace.");
180 return;
181 }
182 if (HasInited.count(std::string(name))) {
183 return;
184 }
185 dlns_init(ns, name);
186 auto status = dlns_create2(ns, entries, 0);
187 std::string errMsg;
188 if (status != 0) {
189 switch (status) {
190 case FILE_EXISTS:
191 errMsg = "dlns_create failed: File exists";
192 break;
193 case INVALID_ARGUMENT:
194 errMsg = "dlns_create failed: Invalid argument";
195 break;
196 case OUT_OF_MEMORY:
197 errMsg = "dlns_create failed: Out of memory";
198 break;
199 default:
200 errMsg = "dlns_create failed, status: " + std::to_string(status);
201 }
202 if (sprintf_s(g_dlError, sizeof(g_dlError), errMsg.c_str()) == -1) {
203 LOGE("Fail to generate error msg.");
204 return;
205 }
206 return;
207 }
208 if (parent) {
209 dlns_inherit((Dl_namespace*)parent, ns, "allow_all_shared_libs");
210 }
211 Dl_namespace current;
212 dlns_get(nullptr, ¤t);
213 if (strcmp(name, "cj_app") != 0) {
214 dlns_inherit(ns, ¤t, "allow_all_shared_libs");
215 } else {
216 InitSharedLibsSonames();
217 dlns_inherit(ns, ¤t, g_sharedLibsSonames);
218 if (g_sharedLibsSonames != nullptr) {
219 delete[] g_sharedLibsSonames;
220 g_sharedLibsSonames = nullptr;
221 }
222 }
223 Dl_namespace chip_sdk;
224 dlns_get("cj_chipsdk", &chip_sdk);
225 dlns_inherit(ns, &chip_sdk, "allow_all_shared_libs");
226 HasInited.insert(std::string(name));
227 }
228
DynamicLoadLibrary(Dl_namespace * ns,const char * dlPath,unsigned int mode)229 void* DynamicLoadLibrary(Dl_namespace *ns, const char* dlPath, unsigned int mode)
230 {
231 if (ns == nullptr) {
232 dlns_get("moduleNs_default", ns);
233 }
234
235 auto result = dlopen_ns(ns, dlPath, mode | RTLD_GLOBAL | RTLD_NOW);
236 if (!result) {
237 ReadDlError();
238 }
239 return result;
240 }
241
DynamicFindSymbol(void * so,const char * symbol)242 void* DynamicFindSymbol(void* so, const char* symbol)
243 {
244 return dlsym(so, symbol);
245 }
246
DynamicFreeLibrary(void * so)247 void DynamicFreeLibrary(void* so)
248 {
249 (void)dlclose(so);
250 }
251
DynamicGetError()252 const char* DynamicGetError()
253 {
254 return g_dlError;
255 }
256 }
257