• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &current);
158     if (strcmp(name, "moduleNs_default") != 0) {
159         dlns_inherit(ns, &current, "allow_all_shared_libs");
160     } else {
161         InitSharedLibsSonames();
162         dlns_inherit(ns, &current, 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, &current, "allow_all_shared_libs");
172     dlns_inherit(&current, &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, &current);
213     if (strcmp(name, "cj_app") != 0) {
214         dlns_inherit(ns, &current, "allow_all_shared_libs");
215     } else {
216         InitSharedLibsSonames();
217         dlns_inherit(ns, &current, 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