1 /*
2 * Copyright (c) 2021 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 "native_module_manager.h"
17
18 #include <cstring>
19 #include <dirent.h>
20 #include <fstream>
21 #include <iostream>
22 #include <mutex>
23 #include <sstream>
24
25 #ifdef ENABLE_HITRACE
26 #include "hitrace_meter.h"
27 #endif
28 #include "module_load_checker.h"
29 #include "native_engine/native_engine.h"
30 #include "securec.h"
31 #include "utils/log.h"
32
33 #define NDK "ndk"
34 #define ALLOW_ALL_SHARED_LIBS "allow_all_shared_libs"
35
36 namespace {
37 constexpr static int32_t NATIVE_PATH_NUMBER = 3;
38 } // namespace
39
40 NativeModuleManager* NativeModuleManager::instance_ = NULL;
41 std::mutex g_instanceMutex;
42
NativeModuleManager()43 NativeModuleManager::NativeModuleManager()
44 {
45 HILOG_INFO("enter");
46 pthread_mutex_init(&mutex_, nullptr);
47 moduleLoadChecker_ = std::make_unique<ModuleLoadChecker>();
48 }
49
~NativeModuleManager()50 NativeModuleManager::~NativeModuleManager()
51 {
52 HILOG_INFO("enter");
53 {
54 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
55 NativeModule* nativeModule = firstNativeModule_;
56 while (nativeModule != nullptr) {
57 nativeModule = nativeModule->next;
58 delete[] firstNativeModule_->name;
59 if (firstNativeModule_->jsABCCode) {
60 delete[] firstNativeModule_->jsABCCode;
61 }
62 delete firstNativeModule_;
63 firstNativeModule_ = nativeModule;
64 }
65 firstNativeModule_ = nullptr;
66 lastNativeModule_ = nullptr;
67 }
68
69 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
70 !defined(LINUX_PLATFORM)
71 if (sharedLibsSonames_) {
72 delete[] sharedLibsSonames_;
73 }
74 #endif
75
76 for (const auto& item : appLibPathMap_) {
77 delete[] item.second;
78 }
79 std::map<std::string, char*>().swap(appLibPathMap_);
80
81 while (nativeEngineList_.size() > 0) {
82 NativeEngine* wraper = nativeEngineList_.begin()->second;
83 if (wraper != nullptr) {
84 delete wraper;
85 wraper = nullptr;
86 }
87 nativeEngineList_.erase(nativeEngineList_.begin());
88 }
89 pthread_mutex_destroy(&mutex_);
90 }
91
GetInstance()92 NativeModuleManager* NativeModuleManager::GetInstance()
93 {
94 if (instance_ == NULL) {
95 std::lock_guard<std::mutex> lock(g_instanceMutex);
96 if (instance_ == NULL) {
97 instance_ = new NativeModuleManager();
98 HILOG_DEBUG("create native module manager instance");
99 }
100 }
101 return instance_;
102 }
103
SetNativeEngine(std::string moduleKey,NativeEngine * nativeEngine)104 void NativeModuleManager::SetNativeEngine(std::string moduleKey, NativeEngine* nativeEngine)
105 {
106 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
107 if (nativeEngine != nullptr) {
108 nativeEngine->SetModuleName(moduleKey);
109 }
110 std::lock_guard<std::mutex> lock(nativeEngineListMutex_);
111 nativeEngineList_.emplace(moduleKey, nativeEngine);
112 }
113
EmplaceModuleLib(std::string moduleKey,const LIBHANDLE lib)114 void NativeModuleManager::EmplaceModuleLib(std::string moduleKey, const LIBHANDLE lib)
115 {
116 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
117 std::lock_guard<std::mutex> lock(moduleLibMutex_);
118 if (lib != nullptr) {
119 moduleLibMap_.emplace(moduleKey, lib);
120 }
121 }
122
RemoveModuleLib(const std::string moduleKey)123 bool NativeModuleManager::RemoveModuleLib(const std::string moduleKey)
124 {
125 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
126 bool deleted = false;
127 std::lock_guard<std::mutex> lock(moduleLibMutex_);
128 auto it = moduleLibMap_.find(moduleKey);
129 if (it != moduleLibMap_.end()) {
130 moduleLibMap_.erase(it);
131 HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
132 deleted = true;
133 }
134 return deleted;
135 }
136
GetNativeModuleHandle(const std::string & moduleKey) const137 LIBHANDLE NativeModuleManager::GetNativeModuleHandle(const std::string& moduleKey) const
138 {
139 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
140 std::lock_guard<std::mutex> lock(moduleLibMutex_);
141 auto it = moduleLibMap_.find(moduleKey);
142 if (it == moduleLibMap_.end()) {
143 return nullptr;
144 }
145 return it->second;
146 }
147
EmplaceModuleBuffer(const std::string moduleKey,const uint8_t * lib)148 void NativeModuleManager::EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib)
149 {
150 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
151 std::lock_guard<std::mutex> lock(moduleBufMutex_);
152 if (lib != nullptr) {
153 moduleBufMap_.emplace(moduleKey, lib);
154 }
155 }
156
RemoveModuleBuffer(const std::string moduleKey)157 bool NativeModuleManager::RemoveModuleBuffer(const std::string moduleKey)
158 {
159 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
160 bool deleted = false;
161 std::lock_guard<std::mutex> lock(moduleBufMutex_);
162 auto it = moduleBufMap_.find(moduleKey);
163 if (it != moduleBufMap_.end()) {
164 moduleBufMap_.erase(it);
165 HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
166 deleted = true;
167 }
168 return deleted;
169 }
170
GetBufferHandle(const std::string & moduleKey) const171 const uint8_t* NativeModuleManager::GetBufferHandle(const std::string& moduleKey) const
172 {
173 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
174 std::lock_guard<std::mutex> lock(moduleBufMutex_);
175 auto it = moduleBufMap_.find(moduleKey);
176 if (it == moduleBufMap_.end()) {
177 return nullptr;
178 }
179 return it->second;
180 }
181
RemoveNativeModule(const std::string & moduleKey)182 bool NativeModuleManager::RemoveNativeModule(const std::string& moduleKey)
183 {
184 bool handleAbcRemoved = RemoveModuleBuffer(moduleKey);
185 bool handleRemoved = RemoveModuleLib(moduleKey);
186 bool moduleRemoved = RemoveNativeModuleByCache(moduleKey);
187
188 HILOG_DEBUG("handleAbcRemoved is %{public}d, handleRemoved is %{public}d, moduleRemoved is %{public}d",
189 handleAbcRemoved, handleRemoved, moduleRemoved);
190 return ((handleRemoved || handleAbcRemoved) && moduleRemoved);
191 }
192
UnloadNativeModule(const std::string & moduleKey)193 bool NativeModuleManager::UnloadNativeModule(const std::string& moduleKey)
194 {
195 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
196 LIBHANDLE handle = GetNativeModuleHandle(moduleKey);
197 if (handle == nullptr) {
198 HILOG_ERROR("failed to get native module handle.");
199 return false;
200 }
201
202 if (RemoveNativeModule(moduleKey) == false) {
203 HILOG_ERROR("remove native module failed.");
204 return false;
205 }
206
207 return UnloadModuleLibrary(handle);
208 }
209
GetModuleFileName(const char * moduleName,bool isAppModule)210 std::string NativeModuleManager::GetModuleFileName(const char* moduleName, bool isAppModule)
211 {
212 HILOG_INFO("moduleName is '%{public}s', isAppModule is %{public}d", moduleName, isAppModule);
213
214 std::string loadPath;
215 std::string name = isAppModule ? (prefix_ + "/" + moduleName) : moduleName;
216 NativeModule* module = FindNativeModuleByCache(name.c_str());
217 if (module != nullptr) {
218 char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
219 const char* pathKey = "default";
220 if (!GetNativeModulePath(moduleName, pathKey, "", isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
221 HILOG_ERROR("get native module path failed");
222 return loadPath;
223 }
224 loadPath = nativeModulePath[0];
225 if (isAppModule && IsExistedPath(pathKey)) {
226 loadPath = std::string(appLibPathMap_[pathKey]) + "/" + nativeModulePath[0];
227 }
228 return loadPath;
229 }
230 HILOG_ERROR("get module file name failed");
231 return loadPath;
232 }
233
Register(NativeModule * nativeModule)234 void NativeModuleManager::Register(NativeModule* nativeModule)
235 {
236 if (nativeModule == nullptr) {
237 HILOG_ERROR("nativeModule value is null");
238 return;
239 }
240
241 HILOG_DEBUG("native module name is '%{public}s'", nativeModule->name);
242 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
243 if (!CreateNewNativeModule()) {
244 HILOG_ERROR("create new nativeModule failed");
245 return;
246 }
247
248 const char *nativeModuleName = nativeModule->name == nullptr ? "" : nativeModule->name;
249 std::string appName = prefix_ + "/" + nativeModuleName;
250 const char *tmpName = isAppModule_ ? appName.c_str() : nativeModuleName;
251 char *moduleName = strdup(tmpName);
252 if (moduleName == nullptr) {
253 HILOG_ERROR("strdup failed. tmpName is %{public}s", tmpName);
254 return;
255 }
256
257 lastNativeModule_->version = nativeModule->version;
258 lastNativeModule_->fileName = nativeModule->fileName;
259 lastNativeModule_->isAppModule = isAppModule_;
260 lastNativeModule_->name = moduleName;
261 lastNativeModule_->refCount = nativeModule->refCount;
262 lastNativeModule_->registerCallback = nativeModule->registerCallback;
263 lastNativeModule_->getJSCode = nativeModule->getJSCode;
264 lastNativeModule_->getABCCode = nativeModule->getABCCode;
265 lastNativeModule_->next = nullptr;
266 lastNativeModule_->moduleLoaded = true;
267
268 HILOG_DEBUG("register module name is '%{public}s', isAppModule is %{public}d",
269 lastNativeModule_->name, isAppModule_);
270 }
271
CreateNewNativeModule()272 bool NativeModuleManager::CreateNewNativeModule()
273 {
274 if (firstNativeModule_ == lastNativeModule_ && lastNativeModule_ == nullptr) {
275 firstNativeModule_ = new NativeModule();
276 if (firstNativeModule_ == nullptr) {
277 HILOG_ERROR("first NativeModule create failed");
278 return false;
279 }
280 lastNativeModule_ = firstNativeModule_;
281 } else {
282 auto next = new NativeModule();
283 if (next == nullptr) {
284 HILOG_ERROR("next NativeModule create failed");
285 return false;
286 }
287 if (lastNativeModule_) {
288 lastNativeModule_->next = next;
289 lastNativeModule_ = lastNativeModule_->next;
290 }
291 }
292 return true;
293 }
294
295 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
296 !defined(LINUX_PLATFORM)
CreateSharedLibsSonames()297 void NativeModuleManager::CreateSharedLibsSonames()
298 {
299 HILOG_DEBUG("enter");
300 const char* allowList[] = {
301 // bionic library
302 "libc.so",
303 "libdl.so",
304 "libm.so",
305 "libz.so",
306 "libclang_rt.asan.so",
307 // z library
308 "libace_napi.z.so",
309 "libace_ndk.z.so",
310 "libbundle_ndk.z.so",
311 "libdeviceinfo_ndk.z.so",
312 "libEGL.so",
313 "libGLESv3.so",
314 "libhiappevent_ndk.z.so",
315 "libhuks_ndk.z.so",
316 "libhukssdk.z.so",
317 "libnative_drawing.so",
318 "libnative_window.so",
319 "libnative_buffer.so",
320 "libnative_vsync.so",
321 "libOpenSLES.so",
322 "libpixelmap_ndk.z.so",
323 "libimage_ndk.z.so",
324 "libimage_receiver_ndk.z.so",
325 "libimage_source_ndk.z.so",
326 "librawfile.z.so",
327 "libuv.so",
328 "libhilog.so",
329 "libnative_image.so",
330 "libnative_media_adec.so",
331 "libnative_media_aenc.so",
332 "libnative_media_codecbase.so",
333 "libnative_media_core.so",
334 "libnative_media_vdec.so",
335 "libnative_media_venc.so",
336 "libnative_media_avmuxer.so",
337 "libnative_media_avdemuxer.so",
338 "libnative_media_avsource.so",
339 "libnative_avscreen_capture.so",
340 "libavplayer.so",
341 // adaptor library
342 "libohosadaptor.so",
343 "libusb_ndk.z.so",
344 "libvulkan.so",
345 };
346
347 size_t allowListLength = sizeof(allowList) / sizeof(char*);
348 int32_t sharedLibsSonamesLength = 1;
349 for (size_t i = 0; i < allowListLength; i++) {
350 sharedLibsSonamesLength += strlen(allowList[i]) + 1;
351 }
352 sharedLibsSonames_ = new char[sharedLibsSonamesLength];
353 int32_t cursor = 0;
354 for (size_t i = 0; i < allowListLength; i++) {
355 if (sprintf_s(sharedLibsSonames_ + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
356 delete[] sharedLibsSonames_;
357 sharedLibsSonames_ = nullptr;
358 return;
359 }
360 cursor += strlen(allowList[i]) + 1;
361 }
362 sharedLibsSonames_[cursor] = '\0';
363 }
364 #endif
365
CreateLdNamespace(const std::string moduleName,const char * lib_ld_path,const bool & isSystemApp)366 void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const char* lib_ld_path,
367 [[maybe_unused]] const bool& isSystemApp)
368 {
369 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
370 !defined(LINUX_PLATFORM)
371 Dl_namespace current_ns;
372 Dl_namespace ns;
373
374 // Create module ns.
375 std::string nsName = "moduleNs_" + moduleName;
376 dlns_init(&ns, nsName.c_str());
377 dlns_get(nullptr, ¤t_ns);
378
379 Dl_namespace ndk_ns;
380 dlns_get(NDK, &ndk_ns);
381
382 if (isSystemApp) {
383 /*
384 * The app's so may have the same name as the system library, LOCAL_NS_PREFERED means linker will check
385 * and use the app's so first.
386 */
387 dlns_create2(&ns, lib_ld_path, LOCAL_NS_PREFERED);
388 // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
389 dlns_set_namespace_separated(nsName.c_str(), true);
390 // Allows access to subdirectories of this directory for shared objects (so).
391 dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
392 // System app can visit all ndk and default ns libs.
393 if (strlen(ndk_ns.name) > 0) {
394 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
395 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
396 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
397 dlns_inherit(&ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
398 }
399 } else {
400 dlns_create2(&ns, lib_ld_path, 0);
401 // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
402 dlns_set_namespace_separated(nsName.c_str(), true);
403 // Allows access to subdirectories of this directory for shared objects (so).
404 dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
405 // Non-system app can visit all ndk ns libs and default ns shared libs.
406 if (!sharedLibsSonames_) {
407 CreateSharedLibsSonames();
408 }
409 dlns_inherit(&ns, ¤t_ns, sharedLibsSonames_);
410 if (strlen(ndk_ns.name) > 0) {
411 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
412 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
413 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
414 }
415 }
416
417 nsMap_[moduleName] = ns;
418
419 HILOG_DEBUG("end. moduleName: %{public}s, path: %{public}s", moduleName.c_str(), lib_ld_path);
420 #endif
421 }
422
SetAppLibPath(const std::string & moduleName,const std::vector<std::string> & appLibPath,const bool & isSystemApp)423 void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
424 const bool& isSystemApp)
425 {
426 HILOG_DEBUG("moduleName is %{public}s, isisSystemApp is %{public}d", moduleName.c_str(), isSystemApp);
427
428 std::string tmpPath = "";
429 for (size_t i = 0; i < appLibPath.size(); i++) {
430 if (appLibPath[i].empty()) {
431 continue;
432 }
433 tmpPath += appLibPath[i];
434 tmpPath += ":";
435 }
436 if (tmpPath.back() == ':') {
437 tmpPath.pop_back();
438 }
439
440 char *tmp = strdup(tmpPath.c_str());
441 if (tmp == nullptr) {
442 HILOG_ERROR("strdup failed. tmpPath is %{public}s", tmpPath.c_str());
443 return;
444 }
445
446 if (appLibPathMap_[moduleName] != nullptr) {
447 delete[] appLibPathMap_[moduleName];
448 }
449 appLibPathMap_[moduleName] = tmp;
450 CreateLdNamespace(moduleName, tmp, isSystemApp);
451 HILOG_DEBUG("path: %{public}s", appLibPathMap_[moduleName]);
452 }
453
CheckModuleRestricted(const std::string & moduleName)454 bool NativeModuleManager::CheckModuleRestricted(const std::string& moduleName)
455 {
456 const std::string whiteList[] = {
457 "worker",
458 };
459
460 size_t listLen = sizeof(whiteList) / sizeof(whiteList[0]);
461 for (size_t i = 0; i < listLen; ++i) {
462 if (moduleName == whiteList[i]) {
463 HILOG_DEBUG("module %{public}s found in whitelist", moduleName.c_str());
464 return false;
465 }
466 }
467
468 HILOG_DEBUG("module %{public}s does not found in whitelist", moduleName.c_str());
469 return true;
470 }
471
MoveApiAllowListCheckerPtr(std::unique_ptr<ApiAllowListChecker> & apiAllowListChecker,NativeModule * nativeModule)472 void NativeModuleManager::MoveApiAllowListCheckerPtr(
473 std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule)
474 {
475 if (apiAllowListChecker != nullptr) {
476 nativeModule->apiAllowListChecker.reset(apiAllowListChecker.release());
477 }
478 }
479
LoadNativeModule(const char * moduleName,const char * path,bool isAppModule,bool internal,const char * relativePath,bool isModuleRestricted)480 NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName,
481 const char* path, bool isAppModule, bool internal, const char* relativePath, bool isModuleRestricted)
482 {
483 if (moduleName == nullptr || relativePath == nullptr) {
484 HILOG_ERROR("moduleName or relativePath is nullptr");
485 return nullptr;
486 }
487
488 HILOG_DEBUG("moduleName is %{public}s, path is %{public}s, relativePath is %{public}s",
489 moduleName, path, relativePath);
490 // we only check system so in restricted runtime.
491 if (isModuleRestricted == true && isAppModule == false) {
492 if (CheckModuleRestricted(moduleName) == true) {
493 HILOG_WARN("module is not allowed to load.");
494 return nullptr;
495 }
496 }
497
498 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
499 if (moduleLoadChecker_ && !moduleLoadChecker_->DiskCheckOnly() &&
500 !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker)) {
501 HILOG_ERROR("Block module name: %{public}s", moduleName);
502 return nullptr;
503 }
504 #ifdef ANDROID_PLATFORM
505 std::string strModule(moduleName);
506 std::string strCutName = strModule;
507 if (path != nullptr) {
508 if (IsExistedPath(path)) {
509 strModule = path;
510 }
511 prefix_ = "default";
512 strModule = prefix_ + '/' + moduleName;
513 } else {
514 path = "default";
515 if (strModule.find(".") != std::string::npos) {
516 char* temp = const_cast<char*>(strCutName.c_str());
517 for (char* p = strchr(temp, '.'); p != nullptr; p = strchr(p + 1, '.')) {
518 *p = '_';
519 }
520 }
521 }
522 #endif
523
524 (void)pthread_mutex_lock(&mutex_);
525
526 #ifdef ANDROID_PLATFORM
527 NativeModule* nativeModule = FindNativeModuleByCache(strModule.c_str());
528 #else
529 std::string key(moduleName);
530 isAppModule_ = isAppModule;
531 if (isAppModule) {
532 prefix_ = "default";
533 if (path && IsExistedPath(path)) {
534 prefix_ = path;
535 }
536 key = prefix_ + '/' + moduleName;
537 HILOG_INFO("key is %{public}s", key.c_str());
538 }
539 NativeModule* nativeModule = FindNativeModuleByCache(key.c_str());
540 #endif
541
542 #ifndef IOS_PLATFORM
543 if (nativeModule == nullptr) {
544 #ifdef ANDROID_PLATFORM
545 HILOG_DEBUG("module '%{public}s' does not in cache", strCutName.c_str());
546 nativeModule = FindNativeModuleByDisk(strCutName.c_str(), path, relativePath, internal, isAppModule);
547 #else
548 HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
549 nativeModule = FindNativeModuleByDisk(moduleName, prefix_.c_str(), relativePath, internal, isAppModule);
550 #endif
551 }
552 #endif
553 MoveApiAllowListCheckerPtr(apiAllowListChecker, nativeModule);
554
555 (void) pthread_mutex_unlock(&mutex_);
556
557 HILOG_DEBUG("load native module %{public}s", (nativeModule == nullptr) ? "failed" : "success");
558 return nativeModule;
559 }
560
GetNativeModulePath(const char * moduleName,const char * path,const char * relativePath,bool isAppModule,char nativeModulePath[][NAPI_PATH_MAX],int32_t pathLength)561 bool NativeModuleManager::GetNativeModulePath(const char* moduleName, const char* path,
562 const char* relativePath, bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength)
563 {
564 #ifdef WINDOWS_PLATFORM
565 const char* soPostfix = ".dll";
566 const char* zfix = "";
567 std::string sysPrefix("./module");
568 #elif defined(MAC_PLATFORM)
569 const char* soPostfix = ".dylib";
570 const char* zfix = "";
571 std::string sysPrefix("./module");
572 #elif defined(_ARM64_) || defined(SIMULATOR)
573 const char* soPostfix = ".so";
574 const char* zfix = ".z";
575 std::string sysPrefix("/system/lib64/module");
576 #elif defined(LINUX_PLATFORM)
577 const char* soPostfix = ".so";
578 const char* zfix = "";
579 std::string sysPrefix("./module");
580 #else
581 const char* soPostfix = ".so";
582 const char* zfix = ".z";
583 std::string sysPrefix("/system/lib/module");
584 #endif
585 const char* abcfix = ".abc";
586 std::string sysAbcPrefix("/system/etc/abc");
587
588 #ifdef ANDROID_PLATFORM
589 isAppModule = true;
590 #endif
591 int32_t lengthOfModuleName = strlen(moduleName);
592 char dupModuleName[NAPI_PATH_MAX] = { 0 };
593 if (strcpy_s(dupModuleName, NAPI_PATH_MAX, moduleName) != 0) {
594 HILOG_ERROR("strcpy_s moduleName '%{public}s' failed", moduleName);
595 return false;
596 }
597
598 const char* prefix = nullptr;
599 if (isAppModule && IsExistedPath(path)) {
600 prefix = appLibPathMap_[path];
601 #ifdef ANDROID_PLATFORM
602 for (int32_t i = 0; i < lengthOfModuleName; i++) {
603 dupModuleName[i] = tolower(dupModuleName[i]);
604 }
605 #endif
606 } else {
607 if (relativePath[0]) {
608 if (previewSearchPath_.empty()) {
609 sysPrefix = sysPrefix + "/" + relativePath;
610 } else {
611 sysPrefix = previewSearchPath_ + "/module";
612 }
613 }
614 prefix = sysPrefix.c_str();
615 for (int32_t i = 0; i < lengthOfModuleName; i++) {
616 dupModuleName[i] = tolower(dupModuleName[i]);
617 }
618 }
619
620 int32_t lengthOfPostfix = strlen(soPostfix);
621 if ((lengthOfModuleName > lengthOfPostfix) &&
622 (strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
623 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s", prefix, dupModuleName) == -1) {
624 return false;
625 }
626 return true;
627 }
628
629 char* lastDot = strrchr(dupModuleName, '.');
630 if (lastDot == nullptr) {
631 if (!isAppModule || !IsExistedPath(path)) {
632 #ifdef ANDROID_PLATFORM
633 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
634 return false;
635 }
636 #else
637 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s%s",
638 prefix, dupModuleName, zfix, soPostfix) == -1) {
639 return false;
640 }
641 #endif
642 if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s_napi%s%s",
643 prefix, dupModuleName, zfix, soPostfix) == -1) {
644 return false;
645 }
646
647 if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s%s", // 2 : Element index value
648 sysAbcPrefix.c_str(), dupModuleName, abcfix) == -1) {
649 return false;
650 }
651 } else {
652 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
653 !defined(LINUX_PLATFORM)
654 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
655 return false;
656 }
657 #elif defined(ANDROID_PLATFORM)
658 std::istringstream iss(prefix);
659 std::string libPath;
660 while (std::getline(iss, libPath, ':')) {
661 std::ifstream dupModuleFile(libPath + "/lib" + dupModuleName + soPostfix);
662 std::ifstream moduleFile(libPath + "/lib" + moduleName + soPostfix);
663 if(dupModuleFile.good() || moduleFile.good()) {
664 break;
665 }
666 }
667 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", libPath.c_str(),
668 dupModuleName, soPostfix) == -1) {
669 return false;
670 }
671 #else
672 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", prefix, dupModuleName, soPostfix) == -1) {
673 return false;
674 }
675 #endif
676 #ifdef ANDROID_PLATFORM
677 if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s%s", libPath.c_str(),
678 moduleName, soPostfix) == -1) {
679 return false;
680 }
681 #endif
682 }
683 } else {
684 char* afterDot = lastDot + 1;
685 if (*afterDot == '\0') {
686 return false;
687 }
688 *lastDot = '\0';
689 lengthOfModuleName = strlen(dupModuleName);
690 for (int32_t i = 0; i < lengthOfModuleName; i++) {
691 if (*(dupModuleName + i) == '.') {
692 *(dupModuleName + i) = '/';
693 }
694 }
695 if (!isAppModule || !IsExistedPath(path)) {
696 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s%s",
697 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
698 return false;
699 }
700 if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s_napi%s%s",
701 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
702 return false;
703 }
704 if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s/%s%s", // 2 : Element index value
705 sysAbcPrefix.c_str(), dupModuleName, afterDot, abcfix) == -1) {
706 return false;
707 }
708 } else {
709 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
710 !defined(LINUX_PLATFORM)
711 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", afterDot, soPostfix) == -1) {
712 return false;
713 }
714 #else
715 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s",
716 prefix, dupModuleName, afterDot, soPostfix) == -1) {
717 return false;
718 }
719 #endif
720 #ifdef ANDROID_PLATFORM
721 if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s%s",
722 prefix, moduleName, afterDot, soPostfix) == -1) {
723 return false;
724 }
725 #endif
726 }
727 }
728 return true;
729 }
730
LoadModuleLibrary(std::string & moduleKey,const char * path,const char * pathKey,const bool isAppModule)731 LIBHANDLE NativeModuleManager::LoadModuleLibrary(std::string& moduleKey, const char* path,
732 const char* pathKey, const bool isAppModule)
733 {
734 if (strlen(path) == 0) {
735 HILOG_ERROR("primary module path is empty");
736 return nullptr;
737 }
738
739 LIBHANDLE lib = nullptr;
740 lib = GetNativeModuleHandle(moduleKey);
741 if (lib != nullptr) {
742 HILOG_DEBUG("get native module handle success. moduleKey is %{public}s", moduleKey.c_str());
743 return lib;
744 }
745
746 HILOG_INFO("path: %{public}s, pathKey: %{public}s, isAppModule: %{public}d", path, pathKey, isAppModule);
747 #ifdef ENABLE_HITRACE
748 StartTrace(HITRACE_TAG_ACE, path);
749 #endif
750 #if defined(WINDOWS_PLATFORM)
751 lib = LoadLibrary(path);
752 if (lib == nullptr) {
753 HILOG_WARN("LoadLibrary failed, error: %{public}d", GetLastError());
754 }
755 #elif defined(MAC_PLATFORM) || defined(__BIONIC__) || defined(LINUX_PLATFORM)
756 lib = dlopen(path, RTLD_LAZY);
757 if (lib == nullptr) {
758 HILOG_WARN("dlopen failed: %{public}s", dlerror());
759 }
760
761 #elif defined(IOS_PLATFORM)
762 lib = nullptr;
763 #else
764 if (isAppModule && IsExistedPath(pathKey)) {
765 Dl_namespace ns = nsMap_[pathKey];
766 lib = dlopen_ns(&ns, path, RTLD_LAZY);
767 } else {
768 lib = dlopen(path, RTLD_LAZY);
769 }
770 if (lib == nullptr) {
771 HILOG_WARN("dlopen failed: %{public}s", dlerror());
772 }
773 #endif
774 #ifdef ENABLE_HITRACE
775 FinishTrace(HITRACE_TAG_ACE);
776 #endif
777 EmplaceModuleLib(moduleKey, lib);
778
779 return lib;
780 }
781
GetFileBuffer(const std::string & filePath,const std::string & moduleKey,size_t & len)782 const uint8_t* NativeModuleManager::GetFileBuffer(const std::string& filePath,
783 const std::string& moduleKey, size_t &len)
784 {
785 const uint8_t* lib = nullptr;
786 std::ifstream inFile(filePath, std::ios::ate | std::ios::binary);
787 if (!inFile.is_open()) {
788 HILOG_ERROR("%{public}s is not existed.", filePath.c_str());
789 return lib;
790 }
791 len = static_cast<size_t>(inFile.tellg());
792 std::string abcModuleKey = moduleKey;
793 lib = GetBufferHandle(abcModuleKey);
794 if (lib != nullptr) {
795 HILOG_DEBUG("get native abc handle success. moduleKey is %{public}s", moduleKey.c_str());
796 inFile.close();
797 return lib;
798 }
799
800 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
801 inFile.seekg(0);
802 inFile.read(reinterpret_cast<char*>(buffer.get()), len);
803 inFile.close();
804 lib = buffer.release();
805 EmplaceModuleBuffer(abcModuleKey, lib);
806 return lib;
807 }
808
UnloadModuleLibrary(LIBHANDLE handle)809 bool NativeModuleManager::UnloadModuleLibrary(LIBHANDLE handle)
810 {
811 if (handle == nullptr) {
812 HILOG_WARN("handle is nullptr");
813 return false;
814 }
815 #if !defined(WINDOWS_PLATFORM) && !defined(IOS_PLATFORM)
816 if (!dlclose(handle)) {
817 return true;
818 }
819 HILOG_WARN("dlclose failed: %{public}s", dlerror());
820 #endif
821 return false;
822 }
823
FindNativeModuleByDisk(const char * moduleName,const char * path,const char * relativePath,bool internal,const bool isAppModule)824 NativeModule* NativeModuleManager::FindNativeModuleByDisk(
825 const char* moduleName, const char* path, const char* relativePath, bool internal, const bool isAppModule)
826 {
827 char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
828 nativeModulePath[0][0] = 0;
829 nativeModulePath[1][0] = 0;
830 nativeModulePath[2][0] = 0; // 2 : Element index value
831 if (!GetNativeModulePath(moduleName, path, relativePath, isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
832 HILOG_WARN("get module '%{public}s' path failed", moduleName);
833 return nullptr;
834 }
835 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
836 if (moduleLoadChecker_ && !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker)) {
837 HILOG_ERROR("module '%{public}s' is not allowed to load", moduleName);
838 return nullptr;
839 }
840
841 std::string moduleKey(moduleName);
842 if (isAppModule) {
843 moduleKey = path;
844 moduleKey = moduleKey + '/' + moduleName;
845 }
846
847 // load primary module path first
848 char* loadPath = nativeModulePath[0];
849 HILOG_DEBUG("moduleName: %{public}s. get primary module path: %{public}s", moduleName, loadPath);
850 LIBHANDLE lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule);
851 if (lib == nullptr) {
852 loadPath = nativeModulePath[1];
853 HILOG_DEBUG("try to load secondary module path: %{public}s", loadPath);
854 lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule);
855 }
856
857 const uint8_t* abcBuffer = nullptr;
858 size_t len = 0;
859 if (lib == nullptr) {
860 loadPath = nativeModulePath[2]; // 2 : Element index value
861 HILOG_DEBUG("try to load abc module path: %{public}s", loadPath);
862 abcBuffer = GetFileBuffer(loadPath, moduleKey, len);
863 if (!abcBuffer) {
864 HILOG_ERROR("all path load module '%{public}s' failed", moduleName);
865 return nullptr;
866 }
867 }
868
869 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
870 if (lastNativeModule_ && !abcBuffer && strcmp(lastNativeModule_->name, moduleKey.c_str())) {
871 HILOG_WARN("moduleName '%{public}s' seems not match plugin's name '%{public}s'",
872 moduleKey.c_str(), lastNativeModule_->name);
873 }
874
875 if (!internal) {
876 char symbol[NAPI_PATH_MAX] = { 0 };
877 if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetABCCode", moduleKey.c_str()) == -1) {
878 if (lib != nullptr) {
879 LIBFREE(lib);
880 }
881 HILOG_ERROR("sprintf_s failed. moduleKey is %{public}s", moduleKey.c_str());
882 return nullptr;
883 }
884
885 // replace '.' and '/' with '_'
886 for (char* p = strchr(symbol, '.'); p != nullptr; p = strchr(p + 1, '.')) {
887 *p = '_';
888 }
889 for (char* p = strchr(symbol, '/'); p != nullptr; p = strchr(p + 1, '/')) {
890 *p = '_';
891 }
892
893 if (lib != nullptr) {
894 auto getJSCode = reinterpret_cast<GetJSCodeCallback>(LIBSYM(lib, symbol));
895 if (getJSCode == nullptr) {
896 HILOG_DEBUG("ignore: no %{public}s in %{public}s", symbol, loadPath);
897 MoveApiAllowListCheckerPtr(apiAllowListChecker, lastNativeModule_);
898 return lastNativeModule_;
899 }
900 const char* buf = nullptr;
901 int bufLen = 0;
902 getJSCode(&buf, &bufLen);
903 if (lastNativeModule_) {
904 HILOG_DEBUG("get js code from module: bufLen: %{public}d", bufLen);
905 lastNativeModule_->jsCode = buf;
906 lastNativeModule_->jsCodeLen = bufLen;
907 }
908 } else {
909 RegisterByBuffer(moduleKey, abcBuffer, len);
910 }
911 }
912 if (lastNativeModule_) {
913 lastNativeModule_->moduleLoaded = true;
914 HILOG_DEBUG("last native module name is %{public}s", lastNativeModule_->name);
915 MoveApiAllowListCheckerPtr(apiAllowListChecker, lastNativeModule_);
916 }
917 return lastNativeModule_;
918 }
919
RegisterByBuffer(const std::string & moduleKey,const uint8_t * abcBuffer,size_t len)920 void NativeModuleManager::RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len)
921 {
922 HILOG_DEBUG("native module name is '%{public}s'", moduleKey.c_str());
923 if (!CreateNewNativeModule()) {
924 HILOG_ERROR("create new nativeModule failed");
925 return;
926 }
927
928 char *moduleName = strdup(moduleKey.c_str());
929 if (moduleName == nullptr) {
930 HILOG_ERROR("strdup failed. tmpName is %{public}s", moduleKey.c_str());
931 return;
932 }
933 lastNativeModule_->name = moduleName;
934 lastNativeModule_->jsABCCode = abcBuffer;
935 lastNativeModule_->jsCodeLen = static_cast<int32_t>(len);
936 lastNativeModule_->next = nullptr;
937
938 HILOG_INFO("NativeModule Register by buffer success. module name is '%{public}s'", lastNativeModule_->name);
939 }
940
RemoveNativeModuleByCache(const std::string & moduleKey)941 bool NativeModuleManager::RemoveNativeModuleByCache(const std::string& moduleKey)
942 {
943 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
944
945 if (firstNativeModule_ == nullptr) {
946 HILOG_WARN("NativeModule list is empty");
947 return false;
948 }
949
950 NativeModule* nativeModule = firstNativeModule_;
951 if (!strcasecmp(nativeModule->name, moduleKey.c_str())) {
952 if (firstNativeModule_ == lastNativeModule_) {
953 lastNativeModule_ = nullptr;
954 }
955 firstNativeModule_ = firstNativeModule_->next;
956 delete[] nativeModule->name;
957 if (firstNativeModule_->jsABCCode) {
958 delete[] firstNativeModule_->jsABCCode;
959 }
960 delete nativeModule;
961 HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
962 return true;
963 }
964
965 bool moduleDeleted = false;
966 NativeModule* prev = firstNativeModule_;
967 NativeModule* curr = prev->next;
968 while (curr != nullptr) {
969 if (!strcasecmp(curr->name, moduleKey.c_str())) {
970 if (curr == lastNativeModule_) {
971 lastNativeModule_ = prev;
972 }
973 prev->next = curr->next;
974 delete[] curr->name;
975 if (firstNativeModule_->jsABCCode) {
976 delete[] firstNativeModule_->jsABCCode;
977 }
978 delete curr;
979 HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
980 moduleDeleted = true;
981 break;
982 }
983 prev = prev->next;
984 curr = prev->next;
985 }
986
987 return moduleDeleted;
988 }
989
FindNativeModuleByCache(const char * moduleName)990 NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName)
991 {
992 NativeModule* result = nullptr;
993 NativeModule* preNativeModule = nullptr;
994
995 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
996 for (NativeModule* temp = firstNativeModule_; temp != nullptr; temp = temp->next) {
997 if (!strcasecmp(temp->name, moduleName)) {
998 if (strcmp(temp->name, moduleName)) {
999 HILOG_WARN("moduleName '%{public}s' seems not match plugin's name '%{public}s'",
1000 moduleName, temp->name);
1001 }
1002 result = temp;
1003 break;
1004 }
1005 preNativeModule = temp;
1006 }
1007
1008 if (result && !result->moduleLoaded) {
1009 if (result == lastNativeModule_) {
1010 HILOG_WARN("module '%{public}s' does not load", result->name);
1011 return nullptr;
1012 }
1013 if (preNativeModule) {
1014 preNativeModule->next = result->next;
1015 } else {
1016 firstNativeModule_ = firstNativeModule_->next;
1017 }
1018 result->next = nullptr;
1019 lastNativeModule_->next = result;
1020 lastNativeModule_ = result;
1021 HILOG_WARN("module '%{public}s' does not found", moduleName);
1022 return nullptr;
1023 }
1024 HILOG_DEBUG("module '%{public}s' found in cache", moduleName);
1025 return result;
1026 }
1027
IsExistedPath(const char * pathKey) const1028 bool NativeModuleManager::IsExistedPath(const char* pathKey) const
1029 {
1030 HILOG_DEBUG("pathKey is '%{public}s'", pathKey);
1031 return pathKey && appLibPathMap_.find(pathKey) != appLibPathMap_.end();
1032 }
1033
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> & moduleCheckerDelegate)1034 void NativeModuleManager::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
1035 {
1036 HILOG_DEBUG("enter");
1037 if (!moduleLoadChecker_) {
1038 HILOG_ERROR("SetModuleLoadChecker failed, moduleLoadChecker_ is nullptr");
1039 return;
1040 }
1041 moduleLoadChecker_->SetDelegate(moduleCheckerDelegate);
1042 }
1043
SetPreviewSearchPath(const std::string & previewSearchPath)1044 void NativeModuleManager::SetPreviewSearchPath(const std::string& previewSearchPath)
1045 {
1046 HILOG_DEBUG("previewSearchPath is '%{public}s'", previewSearchPath.c_str());
1047 previewSearchPath_ = previewSearchPath;
1048 }
1049