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 #include <unistd.h>
25
26 #ifdef ENABLE_HITRACE
27 #include "hitrace_meter.h"
28 #endif
29 #include "module_load_checker.h"
30 #include "native_engine/native_engine.h"
31 #include "securec.h"
32 #include "utils/log.h"
33
34 #define NDK "ndk"
35 #define ALLOW_ALL_SHARED_LIBS "allow_all_shared_libs"
36
37 namespace {
38 constexpr static int32_t MODULE_PATH_SECONDARY_INDEX = 2;
39 constexpr static int32_t NATIVE_PATH_NUMBER = 3;
40 constexpr static int32_t IS_APP_MODULE_FLAGS = 100;
41 thread_local bool g_isLoadingModule = false;
42 enum ModuleLoadFailedReason : uint32_t {
43 MODULE_LOAD_SUCCESS = 0,
44 MODULE_NOT_EXIST = 1,
45 };
46 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
47 !defined(LINUX_PLATFORM)
48 constexpr char MODULE_NS[] = "moduleNs_";
49 #endif
50 } // namespace
51
52 NativeModuleManager* NativeModuleManager::instance_ = NULL;
53 std::mutex g_instanceMutex;
54
NativeModuleManager()55 NativeModuleManager::NativeModuleManager()
56 {
57 HILOG_DEBUG("enter");
58 pthread_mutex_init(&mutex_, nullptr);
59 moduleLoadChecker_ = std::make_unique<ModuleLoadChecker>();
60 }
61
~NativeModuleManager()62 NativeModuleManager::~NativeModuleManager()
63 {
64 HILOG_INFO("enter");
65 {
66 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
67 NativeModule* nativeModule = headNativeModule_;
68 while (nativeModule != nullptr) {
69 nativeModule = nativeModule->next;
70 if (headNativeModule_->name) {
71 delete[] headNativeModule_->name;
72 }
73 if (headNativeModule_->moduleName) {
74 delete[] headNativeModule_->moduleName;
75 }
76 if (headNativeModule_->jsABCCode) {
77 delete[] headNativeModule_->jsABCCode;
78 }
79 if (headNativeModule_->systemFilePath && headNativeModule_->systemFilePath[0] != '\0') {
80 free(const_cast<char *>(headNativeModule_->systemFilePath));
81 }
82 delete headNativeModule_;
83 headNativeModule_ = nativeModule;
84 }
85 headNativeModule_ = nullptr;
86 tailNativeModule_ = nullptr;
87 }
88
89 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
90 !defined(LINUX_PLATFORM)
91 if (sharedLibsSonames_) {
92 delete[] sharedLibsSonames_;
93 }
94 #endif
95 appLibPathMapMutex_.lock();
96 for (const auto& item : appLibPathMap_) {
97 delete[] item.second;
98 }
99 std::map<std::string, char*>().swap(appLibPathMap_);
100 appLibPathMapMutex_.unlock();
101
102 while (nativeEngineList_.size() > 0) {
103 NativeEngine* wraper = nativeEngineList_.begin()->second;
104 if (wraper != nullptr) {
105 delete wraper;
106 wraper = nullptr;
107 }
108 nativeEngineList_.erase(nativeEngineList_.begin());
109 }
110 pthread_mutex_destroy(&mutex_);
111 }
112
GetInstance()113 NativeModuleManager* NativeModuleManager::GetInstance()
114 {
115 if (instance_ == NULL) {
116 std::lock_guard<std::mutex> lock(g_instanceMutex);
117 if (instance_ == NULL) {
118 instance_ = new NativeModuleManager();
119 HILOG_DEBUG("create native module manager instance");
120 }
121 }
122 return instance_;
123 }
124
SetNativeEngine(std::string moduleKey,NativeEngine * nativeEngine)125 void NativeModuleManager::SetNativeEngine(std::string moduleKey, NativeEngine* nativeEngine)
126 {
127 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
128 if (nativeEngine != nullptr) {
129 nativeEngine->SetModuleName(moduleKey);
130 }
131 std::lock_guard<std::mutex> lock(nativeEngineListMutex_);
132 nativeEngineList_.emplace(moduleKey, nativeEngine);
133 }
134
EmplaceModuleLib(std::string moduleKey,const LIBHANDLE lib)135 void NativeModuleManager::EmplaceModuleLib(std::string moduleKey, const LIBHANDLE lib)
136 {
137 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
138 std::lock_guard<std::mutex> lock(moduleLibMutex_);
139 if (lib != nullptr) {
140 moduleLibMap_.emplace(moduleKey, lib);
141 }
142 }
143
RemoveModuleLib(const std::string moduleKey)144 bool NativeModuleManager::RemoveModuleLib(const std::string moduleKey)
145 {
146 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
147 bool deleted = false;
148 std::lock_guard<std::mutex> lock(moduleLibMutex_);
149 auto it = moduleLibMap_.find(moduleKey);
150 if (it != moduleLibMap_.end()) {
151 moduleLibMap_.erase(it);
152 HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
153 deleted = true;
154 }
155 return deleted;
156 }
157
GetNativeModuleHandle(const std::string & moduleKey) const158 LIBHANDLE NativeModuleManager::GetNativeModuleHandle(const std::string& moduleKey) const
159 {
160 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
161 std::lock_guard<std::mutex> lock(moduleLibMutex_);
162 auto it = moduleLibMap_.find(moduleKey);
163 if (it == moduleLibMap_.end()) {
164 return nullptr;
165 }
166 return it->second;
167 }
168
EmplaceModuleBuffer(const std::string moduleKey,const uint8_t * lib)169 void NativeModuleManager::EmplaceModuleBuffer(const std::string moduleKey, const uint8_t* lib)
170 {
171 HILOG_DEBUG("modulekey is '%{public}s'", moduleKey.c_str());
172 std::lock_guard<std::mutex> lock(moduleBufMutex_);
173 if (lib != nullptr) {
174 moduleBufMap_.emplace(moduleKey, lib);
175 }
176 }
177
RemoveModuleBuffer(const std::string moduleKey)178 bool NativeModuleManager::RemoveModuleBuffer(const std::string moduleKey)
179 {
180 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
181 bool deleted = false;
182 std::lock_guard<std::mutex> lock(moduleBufMutex_);
183 auto it = moduleBufMap_.find(moduleKey);
184 if (it != moduleBufMap_.end()) {
185 moduleBufMap_.erase(it);
186 HILOG_DEBUG("module '%{public}s' erased", moduleKey.c_str());
187 deleted = true;
188 }
189 return deleted;
190 }
191
GetBufferHandle(const std::string & moduleKey) const192 const uint8_t* NativeModuleManager::GetBufferHandle(const std::string& moduleKey) const
193 {
194 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
195 std::lock_guard<std::mutex> lock(moduleBufMutex_);
196 auto it = moduleBufMap_.find(moduleKey);
197 if (it == moduleBufMap_.end()) {
198 return nullptr;
199 }
200 return it->second;
201 }
202
RemoveNativeModule(const std::string & moduleKey)203 bool NativeModuleManager::RemoveNativeModule(const std::string& moduleKey)
204 {
205 bool handleAbcRemoved = RemoveModuleBuffer(moduleKey);
206 bool handleRemoved = RemoveModuleLib(moduleKey);
207 bool moduleRemoved = RemoveNativeModuleByCache(moduleKey);
208
209 HILOG_DEBUG("handleAbcRemoved is %{public}d, handleRemoved is %{public}d, moduleRemoved is %{public}d",
210 handleAbcRemoved, handleRemoved, moduleRemoved);
211 return ((handleRemoved || handleAbcRemoved) && moduleRemoved);
212 }
213
UnloadNativeModule(const std::string & moduleKey)214 bool NativeModuleManager::UnloadNativeModule(const std::string& moduleKey)
215 {
216 HILOG_DEBUG("moduleKey is '%{public}s'", moduleKey.c_str());
217 LIBHANDLE handle = GetNativeModuleHandle(moduleKey);
218 if (handle == nullptr) {
219 HILOG_ERROR("failed to get native module handle.");
220 return false;
221 }
222
223 if (RemoveNativeModule(moduleKey) == false) {
224 HILOG_ERROR("remove native module failed.");
225 return false;
226 }
227
228 return UnloadModuleLibrary(handle);
229 }
230
GetModuleFileName(const char * moduleName,bool isAppModule)231 std::string NativeModuleManager::GetModuleFileName(const char* moduleName, bool isAppModule)
232 {
233 if (moduleName == nullptr) {
234 HILOG_ERROR("invalid param. moduleName is nullptr");
235 return "";
236 }
237 HILOG_INFO("moduleName is '%{public}s', isAppModule is %{public}d", moduleName, isAppModule);
238
239 std::string loadPath;
240 std::string name = isAppModule ? (prefix_ + "/" + moduleName) : moduleName;
241 char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
242 const char* pathKey = "default";
243 if (!GetNativeModulePath(moduleName, pathKey, "", isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
244 HILOG_ERROR("get native module path failed");
245 return loadPath;
246 }
247 NativeModule* cacheNativeModule = nullptr;
248 NativeModuleHeadTailStruct cacheHeadTailNativeModule;
249 NativeModule* module =
250 FindNativeModuleByCache(name.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
251 if (module == nullptr) {
252 HILOG_ERROR("get module file name failed");
253 return loadPath;
254 }
255 loadPath = nativeModulePath[0];
256 if (isAppModule && IsExistedPath(pathKey)) {
257 std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
258 loadPath = std::string(appLibPathMap_[pathKey]) + "/" + nativeModulePath[0];
259 }
260 HILOG_ERROR("get module file name failed, moduleName is %{public}s", moduleName);
261 return loadPath;
262 }
263
Register(NativeModule * nativeModule)264 void NativeModuleManager::Register(NativeModule* nativeModule)
265 {
266 if (nativeModule == nullptr) {
267 HILOG_ERROR("nativeModule value is null");
268 return;
269 }
270
271 HILOG_DEBUG("native module name is '%{public}s'", nativeModule->name);
272 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
273 const char *nativeModuleName = nativeModule->name == nullptr ? "" : nativeModule->name;
274 std::string appName = prefix_ + "/" + nativeModuleName;
275 std::string tmpName = isAppModule_ ? appName : nativeModuleName;
276 if (nativeModule->flags == IS_APP_MODULE_FLAGS) {
277 std::string prefix = "default/";
278 tmpName = prefix + nativeModuleName;
279 }
280 char *moduleName = strdup(tmpName.c_str());
281 if (moduleName == nullptr) {
282 HILOG_ERROR("strdup failed. tmpName is %{public}s", tmpName.c_str());
283 return;
284 }
285
286 if (g_isLoadingModule || !strcmp(loadingModuleName_.c_str(), moduleName)) {
287 if (!CreateTailNativeModule()) {
288 HILOG_ERROR("create tail nativeModule failed");
289 free(moduleName);
290 return;
291 }
292 tailNativeModule_->version = nativeModule->version;
293 tailNativeModule_->fileName = nativeModule->fileName;
294 tailNativeModule_->isAppModule = isAppModule_;
295 tailNativeModule_->name = moduleName;
296 tailNativeModule_->moduleName = nullptr; /* we update moduleName latter */
297 tailNativeModule_->refCount = nativeModule->refCount;
298 tailNativeModule_->registerCallback = nativeModule->registerCallback;
299 tailNativeModule_->getJSCode = nativeModule->getJSCode;
300 tailNativeModule_->getABCCode = nativeModule->getABCCode;
301 tailNativeModule_->next = nullptr;
302 tailNativeModule_->moduleLoaded = true;
303 tailNativeModule_->systemFilePath = "";
304 if (isAppModule_) {
305 HILOG_INFO("At tail register module name is '%{public}s'", tailNativeModule_->name);
306 }
307 HILOG_DEBUG("At tail register module name is '%{public}s', isAppModule is %{public}d", tailNativeModule_->name,
308 isAppModule_);
309 } else {
310 if (!CreateHeadNativeModule()) {
311 HILOG_ERROR("create head nativeModule failed");
312 return;
313 }
314 headNativeModule_->version = nativeModule->version;
315 headNativeModule_->fileName = nativeModule->fileName;
316 headNativeModule_->isAppModule = isAppModule_;
317 headNativeModule_->name = moduleName;
318 headNativeModule_->refCount = nativeModule->refCount;
319 headNativeModule_->registerCallback = nativeModule->registerCallback;
320 headNativeModule_->getJSCode = nativeModule->getJSCode;
321 headNativeModule_->getABCCode = nativeModule->getABCCode;
322 headNativeModule_->moduleLoaded = true;
323 headNativeModule_->systemFilePath = "";
324 HILOG_INFO("At head register module name is '%{public}s', isAppModule is %{public}d",
325 headNativeModule_->name, isAppModule_);
326 }
327 }
328
CreateHeadNativeModule()329 bool NativeModuleManager::CreateHeadNativeModule()
330 {
331 if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
332 headNativeModule_ = new NativeModule();
333 if (headNativeModule_ == nullptr) {
334 HILOG_ERROR("first NativeModule create failed");
335 return false;
336 }
337 tailNativeModule_ = headNativeModule_;
338 } else {
339 auto head = new NativeModule();
340 if (head == nullptr) {
341 HILOG_ERROR("head NativeModule create failed");
342 return false;
343 }
344 if (headNativeModule_) {
345 head->next = headNativeModule_;
346 headNativeModule_ = head;
347 }
348 }
349 return true;
350 }
351
CreateTailNativeModule()352 bool NativeModuleManager::CreateTailNativeModule()
353 {
354 if (headNativeModule_ == tailNativeModule_ && tailNativeModule_ == nullptr) {
355 headNativeModule_ = new NativeModule();
356 if (headNativeModule_ == nullptr) {
357 HILOG_ERROR("first NativeModule create failed");
358 return false;
359 }
360 tailNativeModule_ = headNativeModule_;
361 } else {
362 auto tail = new NativeModule();
363 if (tail == nullptr) {
364 HILOG_ERROR("tail NativeModule create failed");
365 return false;
366 }
367 if (tailNativeModule_) {
368 tailNativeModule_->next = tail;
369 tailNativeModule_ = tailNativeModule_->next;
370 }
371 }
372 return true;
373 }
374
375 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
376 !defined(LINUX_PLATFORM)
CreateSharedLibsSonames()377 void NativeModuleManager::CreateSharedLibsSonames()
378 {
379 HILOG_DEBUG("enter");
380 const char* allowList[] = {
381 // bionic library
382 "libc.so",
383 "libdl.so",
384 "libm.so",
385 "libz.so",
386 "libclang_rt.asan.so",
387 "libclang_rt.tsan.so",
388 "libclang_rt.ubsan_standalone.so",
389 "libclang_rt.ubsan_minimal.so",
390 "libclang_rt.hwasan.so",
391 // z library
392 "libace_napi.z.so",
393 "libace_ndk.z.so",
394 "libcj_environment.z.so",
395 "libbundle_ndk.z.so",
396 "libdeviceinfo_ndk.z.so",
397 "libEGL.so",
398 "libGLESv3.so",
399 "libhiappevent_ndk.z.so",
400 "libhuks_ndk.z.so",
401 "libhukssdk.z.so",
402 "libnative_drawing.so",
403 "libnative_window.so",
404 "libnative_buffer.so",
405 "libnative_vsync.so",
406 "libOpenSLES.so",
407 "libpixelmap_ndk.z.so",
408 "libimage_ndk.z.so",
409 "libimage_receiver_ndk.z.so",
410 "libimage_source_ndk.z.so",
411 "librawfile.z.so",
412 "libuv.so",
413 "libhilog.so",
414 "libnative_image.so",
415 "libnative_media_adec.so",
416 "libnative_media_aenc.so",
417 "libnative_media_codecbase.so",
418 "libnative_media_core.so",
419 "libnative_media_vdec.so",
420 "libnative_media_venc.so",
421 "libnative_media_avmuxer.so",
422 "libnative_media_avdemuxer.so",
423 "libnative_media_avsource.so",
424 "libnative_avscreen_capture.so",
425 "libavplayer.so",
426 "libavrecorder.so",
427 // adaptor library
428 "libohosadaptor.so",
429 "libusb_ndk.z.so",
430 "libvulkan.so",
431 };
432
433 size_t allowListLength = sizeof(allowList) / sizeof(char*);
434 int32_t sharedLibsSonamesLength = 1;
435 for (size_t i = 0; i < allowListLength; i++) {
436 sharedLibsSonamesLength += strlen(allowList[i]) + 1;
437 }
438 sharedLibsSonames_ = new char[sharedLibsSonamesLength];
439 int32_t cursor = 0;
440 for (size_t i = 0; i < allowListLength; i++) {
441 if (sprintf_s(sharedLibsSonames_ + cursor, sharedLibsSonamesLength - cursor, "%s:", allowList[i]) == -1) {
442 delete[] sharedLibsSonames_;
443 sharedLibsSonames_ = nullptr;
444 return;
445 }
446 cursor += strlen(allowList[i]) + 1;
447 }
448 sharedLibsSonames_[cursor] = '\0';
449 }
450 #endif
451
CreateLdNamespace(const std::string moduleName,const char * lib_ld_path,const bool & isSystemApp)452 void NativeModuleManager::CreateLdNamespace(const std::string moduleName, const char* lib_ld_path,
453 [[maybe_unused]] const bool& isSystemApp)
454 {
455 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
456 !defined(LINUX_PLATFORM)
457 Dl_namespace current_ns;
458 Dl_namespace ns;
459
460 // Create module ns.
461 std::string nsName = MODULE_NS + moduleName;
462 dlns_init(&ns, nsName.c_str());
463 dlns_get(nullptr, ¤t_ns);
464
465 Dl_namespace ndk_ns;
466 dlns_get(NDK, &ndk_ns);
467
468 if (isSystemApp) {
469 /*
470 * The app's so may have the same name as the system library, LOCAL_NS_PREFERED means linker will check
471 * and use the app's so first.
472 */
473 dlns_create2(&ns, lib_ld_path, LOCAL_NS_PREFERED);
474 // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
475 dlns_set_namespace_separated(nsName.c_str(), true);
476 // Allows access to subdirectories of this directory for shared objects (so).
477 dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
478 // System app can visit all ndk and default ns libs.
479 if (strlen(ndk_ns.name) > 0) {
480 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
481 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
482 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
483 dlns_inherit(&ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
484 }
485 } else {
486 dlns_create2(&ns, lib_ld_path, 0);
487 // Performs a namespace check on the full path passed directly or the full path converted after setting rpath.
488 dlns_set_namespace_separated(nsName.c_str(), true);
489 // Allows access to subdirectories of this directory for shared objects (so).
490 dlns_set_namespace_permitted_paths(nsName.c_str(), lib_ld_path);
491 // Non-system app can visit all ndk ns libs and default ns shared libs.
492 if (!sharedLibsSonames_) {
493 CreateSharedLibsSonames();
494 }
495 dlns_inherit(&ns, ¤t_ns, sharedLibsSonames_);
496 if (strlen(ndk_ns.name) > 0) {
497 dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
498 dlns_inherit(&ndk_ns, ¤t_ns, ALLOW_ALL_SHARED_LIBS);
499 dlns_inherit(¤t_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
500 }
501 }
502
503 nsMap_[moduleName] = ns;
504
505 HILOG_DEBUG("end. moduleName: %{public}s, path: %{public}s", moduleName.c_str(), lib_ld_path);
506 #endif
507 }
508
GetLdNamespaceName(const std::string & moduleName,std::string & nsName)509 bool NativeModuleManager::GetLdNamespaceName(const std::string &moduleName, std::string &nsName)
510 {
511 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
512 !defined(LINUX_PLATFORM)
513 if (nsMap_.find(moduleName) == nsMap_.end()) {
514 HILOG_ERROR("not found ns: %{public}s", moduleName.c_str());
515 return false;
516 }
517 nsName = MODULE_NS + moduleName;
518 return true;
519 #else
520 return false;
521 #endif
522 }
523
SetAppLibPath(const std::string & moduleName,const std::vector<std::string> & appLibPath,const bool & isSystemApp)524 void NativeModuleManager::SetAppLibPath(const std::string& moduleName, const std::vector<std::string>& appLibPath,
525 const bool& isSystemApp)
526 {
527 HILOG_DEBUG("moduleName is %{public}s, isisSystemApp is %{public}d", moduleName.c_str(), isSystemApp);
528
529 std::string tmpPath = "";
530 for (size_t i = 0; i < appLibPath.size(); i++) {
531 if (appLibPath[i].empty()) {
532 continue;
533 }
534 tmpPath += appLibPath[i];
535 tmpPath += ":";
536 }
537 if (tmpPath.back() == ':') {
538 tmpPath.pop_back();
539 }
540
541 char *tmp = strdup(tmpPath.c_str());
542 if (tmp == nullptr) {
543 HILOG_ERROR("strdup failed. tmpPath is %{public}s", tmpPath.c_str());
544 return;
545 }
546
547 std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
548 if (appLibPathMap_[moduleName] != nullptr) {
549 delete[] appLibPathMap_[moduleName];
550 }
551 appLibPathMap_[moduleName] = tmp;
552 CreateLdNamespace(moduleName, tmp, isSystemApp);
553 HILOG_DEBUG("path: %{public}s", appLibPathMap_[moduleName]);
554 }
555
MoveApiAllowListCheckerPtr(std::unique_ptr<ApiAllowListChecker> & apiAllowListChecker,NativeModule * nativeModule)556 void NativeModuleManager::MoveApiAllowListCheckerPtr(
557 std::unique_ptr<ApiAllowListChecker>& apiAllowListChecker, NativeModule* nativeModule)
558 {
559 if (apiAllowListChecker != nullptr) {
560 nativeModule->apiAllowListChecker.reset(apiAllowListChecker.release());
561 }
562 }
563
LoadNativeModule(const char * moduleName,const char * path,bool isAppModule,std::string & errInfo,bool internal,const char * relativePath)564 NativeModule* NativeModuleManager::LoadNativeModule(const char* moduleName, const char* path, bool isAppModule,
565 std::string& errInfo, bool internal, const char* relativePath)
566 {
567 if (moduleName == nullptr) {
568 errInfo = "load native module failed. moduleName is nullptr";
569 HILOG_ERROR("%{public}s", errInfo.c_str());
570 return nullptr;
571 }
572
573 if (relativePath == nullptr) {
574 errInfo = "load native module failed. relativePath is nullptr";
575 HILOG_ERROR("%{public}s", errInfo.c_str());
576 return nullptr;
577 }
578
579 std::string relativePathStr(relativePath);
580 if (relativePathStr.find("..") != std::string::npos) {
581 HILOG_ERROR("get relativePath error,relativePath contains .., moduleName:%{public}s", moduleName);
582 return nullptr;
583 }
584
585 HILOG_DEBUG("moduleName is %{public}s, path is %{public}s, relativePath is %{public}s",
586 moduleName, path, relativePath);
587
588 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
589 if (moduleLoadChecker_ && !moduleLoadChecker_->DiskCheckOnly() &&
590 !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker, isAppModule)) {
591 errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
592 HILOG_WARN("%{public}s", errInfo.c_str());
593 return nullptr;
594 }
595 std::string prefixTmp;
596 #if defined(ANDROID_PLATFORM)
597 std::string strModule(moduleName);
598 std::string strCutName = strModule;
599 if (path != nullptr) {
600 if (IsExistedPath(path)) {
601 strModule = path;
602 }
603 prefixTmp = "default";
604 strModule = prefixTmp + '/' + moduleName;
605 } else {
606 path = "default";
607 if (strModule.find(".") != std::string::npos) {
608 char* temp = const_cast<char*>(strCutName.c_str());
609 for (char* p = strchr(temp, '.'); p != nullptr; p = strchr(p + 1, '.')) {
610 *p = '_';
611 }
612 }
613 }
614 #endif
615
616 char nativeModulePath[NATIVE_PATH_NUMBER][NAPI_PATH_MAX];
617 nativeModulePath[0][0] = 0;
618 nativeModulePath[1][0] = 0;
619 nativeModulePath[2][0] = 0; // 2 : Element index value
620 NativeModule* cacheNativeModule = nullptr;
621 NativeModuleHeadTailStruct cacheHeadTailNativeModule;
622 #if defined(ANDROID_PLATFORM)
623 if (!GetNativeModulePath(strCutName.c_str(), path, relativePath, isAppModule, nativeModulePath, NAPI_PATH_MAX)) {
624 errInfo = "failed to get native file path of module " + std::string(moduleName);
625 HILOG_WARN("%{public}s", errInfo.c_str());
626 return nullptr;
627 }
628 NativeModule* nativeModule =
629 FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
630 #else
631 std::string key(moduleName);
632 if (isAppModule) {
633 prefixTmp = "default";
634 if (path && IsExistedPath(path)) {
635 prefixTmp = path;
636 }
637 key = prefixTmp + '/' + moduleName;
638 HILOG_INFO("key is %{public}s", key.c_str());
639 }
640 if (!GetNativeModulePath(moduleName, prefixTmp.c_str(), relativePath, isAppModule, nativeModulePath,
641 NAPI_PATH_MAX)) {
642 errInfo = "failed to get native file path of module " + std::string(moduleName);
643 HILOG_WARN("%{public}s", errInfo.c_str());
644 return nullptr;
645 }
646 #ifdef ENABLE_HITRACE
647 StartTrace(HITRACE_TAG_ACE, moduleName);
648 #endif
649 NativeModule* nativeModule =
650 FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
651 #endif
652 if (nativeModule == nullptr) {
653 (void)pthread_mutex_lock(&mutex_);
654 #ifndef IOS_PLATFORM
655 if (CheckNativeListChanged(cacheHeadTailNativeModule.headNativeModule,
656 cacheHeadTailNativeModule.tailNativeModule)) {
657 #ifdef ANDROID_PLATFORM
658 nativeModule = FindNativeModuleByCache(strModule.c_str(), nativeModulePath, cacheNativeModule,
659 cacheHeadTailNativeModule);
660 #else
661 nativeModule =
662 FindNativeModuleByCache(key.c_str(), nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
663 #endif
664 }
665 #else
666 #endif
667 if (nativeModule == nullptr) {
668 prefix_ = prefixTmp;
669 isAppModule_ = isAppModule;
670 g_isLoadingModule = true;
671 #ifdef ANDROID_PLATFORM
672 HILOG_DEBUG("module '%{public}s' does not in cache", strCutName.c_str());
673 nativeModule = FindNativeModuleByDisk(strCutName.c_str(), path, relativePath, internal, isAppModule,
674 errInfo, nativeModulePath, cacheNativeModule);
675 #elif defined(IOS_PLATFORM)
676 nativeModule =
677 FindNativeModuleByCache(moduleName, nativeModulePath, cacheNativeModule, cacheHeadTailNativeModule);
678 if (nativeModule == nullptr) {
679 HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
680 nativeModule = FindNativeModuleByDisk(moduleName, path, relativePath, internal, isAppModule, errInfo,
681 nativeModulePath, cacheNativeModule);
682 }
683 #else
684 HILOG_DEBUG("module '%{public}s' does not in cache", moduleName);
685 nativeModule = FindNativeModuleByDisk(moduleName, prefix_.c_str(), relativePath, internal, isAppModule,
686 errInfo, nativeModulePath, cacheNativeModule);
687 #endif
688 g_isLoadingModule = false;
689 }
690 (void)pthread_mutex_unlock(&mutex_);
691 }
692 if (nativeModule != nullptr && nativeModule->apiAllowListChecker == nullptr) {
693 MoveApiAllowListCheckerPtr(apiAllowListChecker, nativeModule);
694 }
695 #ifdef ENABLE_HITRACE
696 FinishTrace(HITRACE_TAG_ACE);
697 #endif
698 HILOG_DEBUG("load native module %{public}s", (nativeModule == nullptr) ? "failed" : "success");
699 return nativeModule;
700 }
701
CheckNativeListChanged(const NativeModule * cacheHeadNativeModule,const NativeModule * cacheTailNativeModule)702 bool NativeModuleManager::CheckNativeListChanged(
703 const NativeModule* cacheHeadNativeModule, const NativeModule* cacheTailNativeModule)
704 {
705 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
706 if (!cacheHeadNativeModule || !cacheTailNativeModule || !headNativeModule_ || !tailNativeModule_) {
707 return true;
708 }
709 if (strcmp(cacheHeadNativeModule->name, headNativeModule_->name) != 0 ||
710 strcmp(cacheTailNativeModule->name, tailNativeModule_->name) != 0) {
711 return true;
712 }
713
714 return false;
715 }
GetNativeModulePath(const char * moduleName,const char * path,const char * relativePath,bool isAppModule,char nativeModulePath[][NAPI_PATH_MAX],int32_t pathLength)716 bool NativeModuleManager::GetNativeModulePath(const char* moduleName, const char* path,
717 const char* relativePath, bool isAppModule, char nativeModulePath[][NAPI_PATH_MAX], int32_t pathLength)
718 {
719 #ifdef WINDOWS_PLATFORM
720 const char* soPostfix = ".dll";
721 const char* zfix = "";
722 std::string sysPrefix("./module");
723 const char* abcfix = ".abc";
724 std::string sysAbcPrefix("./module");
725 #elif defined(MAC_PLATFORM)
726 const char* soPostfix = ".dylib";
727 const char* zfix = "";
728 std::string sysPrefix("./module");
729 const char* abcfix = ".abc";
730 std::string sysAbcPrefix("./module");
731 #elif defined(_ARM64_) || defined(SIMULATOR)
732 const char* soPostfix = ".so";
733 const char* zfix = ".z";
734 std::string sysPrefix("/system/lib64/module");
735 const char* abcfix = ".abc";
736 std::string sysAbcPrefix("/system/etc/abc");
737 #elif defined(LINUX_PLATFORM)
738 const char* soPostfix = ".so";
739 const char* zfix = "";
740 std::string sysPrefix("./module");
741 const char* abcfix = ".abc";
742 std::string sysAbcPrefix("./module");
743 #else
744 const char* soPostfix = ".so";
745 const char* zfix = ".z";
746 std::string sysPrefix("/system/lib/module");
747 const char* abcfix = ".abc";
748 std::string sysAbcPrefix("/system/etc/abc");
749 #endif
750
751 #ifdef ANDROID_PLATFORM
752 isAppModule = true;
753 #endif
754 int32_t lengthOfModuleName = strlen(moduleName);
755 char dupModuleName[NAPI_PATH_MAX] = { 0 };
756 if (strcpy_s(dupModuleName, NAPI_PATH_MAX, moduleName) != 0) {
757 HILOG_ERROR("strcpy_s moduleName '%{public}s' failed", moduleName);
758 return false;
759 }
760
761 const char* prefix = nullptr;
762 if (isAppModule && IsExistedPath(path)) {
763 appLibPathMapMutex_.lock();
764 prefix = appLibPathMap_[path];
765 appLibPathMapMutex_.unlock();
766 #ifdef ANDROID_PLATFORM
767 for (int32_t i = 0; i < lengthOfModuleName; i++) {
768 dupModuleName[i] = tolower(dupModuleName[i]);
769 }
770 if (prefix == nullptr) {
771 return false;
772 }
773 /*
774 * The requirement is to ensure the abc format file is placed in the path
775 * /data/user/0/com.example.myapplication/files/arkui-x/systemres/abc.
776 * Steps to follow:
777 * 1. First, check if the /files/arkui-x directory exists.
778 * 2. Verify that the original path consists of two paths separated by a colon (:).
779 * 3. Identify whether /files/arkui-x is located in the portion before or after the colon.
780 * 4. Extract and concatenate the appropriate part of the path to construct
781 * the full abc file path for subsequent logic to access the file
782 */
783 std::string prefixStr(prefix);
784 const std::string arkuiKey = "/files/arkui-x";
785 std::size_t arkuiPos = prefixStr.find(arkuiKey);
786 if (arkuiPos != std::string::npos) {
787 std::size_t endPos = arkuiPos + arkuiKey.length();
788 std::size_t delimiterPos = prefixStr.find(':');
789 if (delimiterPos != std::string::npos) {
790 sysAbcPrefix = (arkuiPos < delimiterPos)
791 ? prefixStr.substr(0, endPos) + "/systemres/abc"
792 : prefixStr.substr(delimiterPos + 1, endPos - (delimiterPos + 1)) +
793 "/systemres/abc";
794 } else {
795 sysAbcPrefix = prefixStr.substr(0, endPos) + "/systemres/abc";
796 }
797 }
798 #endif
799 } else {
800 if (relativePath[0]) {
801 if (previewSearchPath_.empty()) {
802 sysPrefix = sysPrefix + "/" + relativePath;
803 } else {
804 sysPrefix = previewSearchPath_ + "/module";
805 }
806 }
807 prefix = sysPrefix.c_str();
808 for (int32_t i = 0; i < lengthOfModuleName; i++) {
809 dupModuleName[i] = tolower(dupModuleName[i]);
810 }
811 #ifdef IOS_PLATFORM
812 if (appLibPathMap_.find("default") != appLibPathMap_.end()) {
813 std::string sandboxPath(appLibPathMap_["default"]);
814 sysAbcPrefix = sandboxPath + "/systemres/abc";
815 }
816 #endif
817 }
818
819 int32_t lengthOfPostfix = strlen(soPostfix);
820 if ((lengthOfModuleName > lengthOfPostfix) &&
821 (strcmp(dupModuleName + lengthOfModuleName - lengthOfPostfix, soPostfix) == 0)) {
822 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s", prefix, dupModuleName) == -1) {
823 return false;
824 }
825 return true;
826 }
827
828 char* lastDot = strrchr(dupModuleName, '.');
829 if (lastDot == nullptr) {
830 if (!isAppModule || !IsExistedPath(path)) {
831 #ifdef ANDROID_PLATFORM
832 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
833 return false;
834 }
835 #else
836 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s%s",
837 prefix, dupModuleName, zfix, soPostfix) == -1) {
838 return false;
839 }
840 #endif
841 if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s_napi%s%s",
842 prefix, dupModuleName, zfix, soPostfix) == -1) {
843 return false;
844 }
845
846 if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
847 sysAbcPrefix.c_str(), dupModuleName, abcfix) == -1) {
848 return false;
849 }
850 } else {
851 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
852 !defined(LINUX_PLATFORM)
853 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix) == -1) {
854 return false;
855 }
856 #elif defined(ANDROID_PLATFORM)
857 std::string libPath;
858 int sprintfResult = 0;
859 std::string prefixStr = std::string(prefix);
860 std::size_t pos = prefixStr.find(':');
861 if (pos != std::string::npos) {
862 sprintfResult = sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s",
863 prefixStr.substr(0, pos).c_str(), dupModuleName, soPostfix);
864 libPath = prefixStr.substr(pos + 1);
865 } else {
866 sprintfResult = sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", dupModuleName, soPostfix);
867 libPath = prefixStr;
868 }
869 if (sprintfResult == -1) {
870 return false;
871 }
872 #else
873 if (sprintf_s(nativeModulePath[0], pathLength, "%s/lib%s%s", prefix, dupModuleName, soPostfix) == -1) {
874 return false;
875 }
876 #endif
877 #ifdef ANDROID_PLATFORM
878 if (sprintf_s(nativeModulePath[1], pathLength, "%s/lib%s%s", libPath.c_str(),
879 dupModuleName, soPostfix) == -1) {
880 return false;
881 }
882 if (IsExistedPath(libPath.c_str())) {
883 std::swap(nativeModulePath[0], nativeModulePath[1]);
884 }
885 char* lastUnderScore = strrchr(dupModuleName, '_');
886 const char* moduleNamePart = (lastUnderScore != nullptr) ? (lastUnderScore + 1) : dupModuleName;
887 if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
888 sysAbcPrefix.c_str(), moduleNamePart, abcfix) == -1) {
889 return false;
890 }
891 #endif
892 }
893 } else {
894 char* afterDot = lastDot + 1;
895 if (*afterDot == '\0') {
896 return false;
897 }
898 *lastDot = '\0';
899 lengthOfModuleName = strlen(dupModuleName);
900 for (int32_t i = 0; i < lengthOfModuleName; i++) {
901 if (*(dupModuleName + i) == '.') {
902 *(dupModuleName + i) = '/';
903 }
904 }
905 if (!isAppModule || !IsExistedPath(path)) {
906 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s%s",
907 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
908 return false;
909 }
910 if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s_napi%s%s",
911 prefix, dupModuleName, afterDot, zfix, soPostfix) == -1) {
912 return false;
913 }
914 #ifdef IOS_PLATFORM
915 if (sprintf_s(nativeModulePath[MODULE_PATH_SECONDARY_INDEX], pathLength, "%s/%s%s",
916 sysAbcPrefix.c_str(), afterDot, abcfix) == -1) {
917 return false;
918 }
919 #else
920 if (sprintf_s(nativeModulePath[2], pathLength, "%s/%s/%s%s", // 2 : Element index value
921 sysAbcPrefix.c_str(), dupModuleName, afterDot, abcfix) == -1) {
922 return false;
923 }
924 #endif
925 } else {
926 #if !defined(WINDOWS_PLATFORM) && !defined(MAC_PLATFORM) && !defined(__BIONIC__) && !defined(IOS_PLATFORM) && \
927 !defined(LINUX_PLATFORM)
928 if (sprintf_s(nativeModulePath[0], pathLength, "lib%s%s", afterDot, soPostfix) == -1) {
929 return false;
930 }
931 #else
932 if (sprintf_s(nativeModulePath[0], pathLength, "%s/%s/lib%s%s",
933 prefix, dupModuleName, afterDot, soPostfix) == -1) {
934 return false;
935 }
936 #endif
937 #ifdef ANDROID_PLATFORM
938 if (sprintf_s(nativeModulePath[1], pathLength, "%s/%s/lib%s%s",
939 prefix, moduleName, afterDot, soPostfix) == -1) {
940 return false;
941 }
942 #endif
943 }
944 }
945 return true;
946 }
947
LoadModuleLibrary(std::string & moduleKey,const char * path,const char * pathKey,const bool isAppModule,std::string & errInfo,uint32_t & errReason)948 LIBHANDLE NativeModuleManager::LoadModuleLibrary(std::string& moduleKey, const char* path,
949 const char* pathKey, const bool isAppModule, std::string& errInfo, uint32_t& errReason)
950 {
951 if (strlen(path) == 0) {
952 errInfo += "load module " + moduleKey + " failed. module path is empty";
953 HILOG_WARN("%{public}s", errInfo.c_str());
954 return nullptr;
955 }
956
957 LIBHANDLE lib = nullptr;
958
959 HILOG_DEBUG("path: %{public}s, pathKey: %{public}s, isAppModule: %{public}d", path, pathKey, isAppModule);
960 #ifdef ENABLE_HITRACE
961 StartTrace(HITRACE_TAG_ACE, path);
962 #endif
963 #if defined(WINDOWS_PLATFORM)
964 if (CheckModuleExist(path) == false) {
965 errReason = MODULE_NOT_EXIST;
966 return nullptr;
967 }
968 lib = LoadLibrary(path);
969 if (lib == nullptr) {
970 errInfo += "load module failed. " + std::to_string(GetLastError());
971 HILOG_WARN("%{public}s", errInfo.c_str());
972 }
973 #elif defined(MAC_PLATFORM) || defined(__BIONIC__) || defined(LINUX_PLATFORM)
974 #ifndef ANDROID_PLATFORM
975 if (CheckModuleExist(path) == false) {
976 errReason = MODULE_NOT_EXIST;
977 return nullptr;
978 }
979 #endif
980 lib = dlopen(path, RTLD_LAZY);
981 if (lib == nullptr) {
982 char* dlerr = dlerror();
983 auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
984 errInfo += "load module failed. " + std::string(dlerrMsg);
985 }
986
987 #elif defined(IOS_PLATFORM)
988 lib = nullptr;
989 #else
990 if (isAppModule && IsExistedPath(pathKey)) {
991 Dl_namespace ns = nsMap_[pathKey];
992 lib = dlopen_ns(&ns, path, RTLD_LAZY);
993 } else if (access(path, F_OK) == 0) {
994 lib = dlopen(path, RTLD_LAZY);
995 }
996 if (lib == nullptr) {
997 char* dlerr = dlerror();
998 auto dlerrMsg = dlerr != nullptr ? dlerr :
999 "Error loading path " + std::string(path) + ":No such file or directory";
1000 errInfo += "load app module failed. " + std::string(dlerrMsg);
1001 }
1002 #endif
1003 #ifdef ENABLE_HITRACE
1004 FinishTrace(HITRACE_TAG_ACE);
1005 #endif
1006 EmplaceModuleLib(moduleKey, lib);
1007
1008 return lib;
1009 }
1010
GetFileBuffer(const std::string & filePath,const std::string & moduleKey,size_t & len)1011 const uint8_t* NativeModuleManager::GetFileBuffer(const std::string& filePath,
1012 const std::string& moduleKey, size_t &len)
1013 {
1014 const uint8_t* lib = nullptr;
1015 std::ifstream inFile(filePath, std::ios::ate | std::ios::binary);
1016 if (!inFile.is_open()) {
1017 HILOG_WARN("%{public}s is not existed.", filePath.c_str());
1018 return lib;
1019 }
1020 len = static_cast<size_t>(inFile.tellg());
1021 std::string abcModuleKey = moduleKey;
1022 lib = GetBufferHandle(abcModuleKey);
1023 if (lib != nullptr) {
1024 HILOG_DEBUG("get native abc handle success. moduleKey is %{public}s", moduleKey.c_str());
1025 inFile.close();
1026 return lib;
1027 }
1028
1029 std::unique_ptr<uint8_t[]> buffer = std::make_unique<uint8_t[]>(len);
1030 inFile.seekg(0);
1031 inFile.read(reinterpret_cast<char*>(buffer.get()), len);
1032 inFile.close();
1033 lib = buffer.release();
1034 EmplaceModuleBuffer(abcModuleKey, lib);
1035 return lib;
1036 }
1037
UnloadModuleLibrary(LIBHANDLE handle)1038 bool NativeModuleManager::UnloadModuleLibrary(LIBHANDLE handle)
1039 {
1040 if (handle == nullptr) {
1041 HILOG_WARN("handle is nullptr");
1042 return false;
1043 }
1044 #if !defined(WINDOWS_PLATFORM) && !defined(IOS_PLATFORM)
1045 if (!dlclose(handle)) {
1046 return true;
1047 }
1048 char* dlerr = dlerror();
1049 auto dlerrMsg = dlerr != nullptr ? dlerr : "dlerror msg is empty";
1050 HILOG_WARN("dlclose failed: %{public}s", dlerrMsg);
1051 #endif
1052 return false;
1053 }
1054
CheckModuleExist(const char * modulePath)1055 bool NativeModuleManager::CheckModuleExist(const char* modulePath)
1056 {
1057 if (modulePath) {
1058 std::ifstream inFile(modulePath, std::ios::ate | std::ios::binary);
1059 if (inFile.is_open()) {
1060 inFile.close();
1061 return true;
1062 }
1063 }
1064 return false;
1065 }
1066
Napi_onLoadCallback(LIBHANDLE lib,const char * moduleName)1067 void NativeModuleManager::Napi_onLoadCallback(LIBHANDLE lib, const char* moduleName)
1068 {
1069 auto onLoadFunc = reinterpret_cast<NapiOnLoadCallback>(LIBSYM(lib, "napi_onLoad"));
1070 if (onLoadFunc != nullptr) {
1071 onLoadFunc();
1072 HILOG_INFO("napi_onLoad call, moduleName:%{public}s", moduleName);
1073 }
1074 }
1075
FindNativeModuleByDisk(const char * moduleName,const char * path,const char * relativePath,bool internal,const bool isAppModule,std::string & errInfo,char nativeModulePath[][NAPI_PATH_MAX],NativeModule * cacheNativeModule)1076 NativeModule* NativeModuleManager::FindNativeModuleByDisk(const char* moduleName, const char* path,
1077 const char* relativePath, bool internal, const bool isAppModule, std::string& errInfo,
1078 char nativeModulePath[][NAPI_PATH_MAX], NativeModule* cacheNativeModule)
1079 {
1080 std::unique_ptr<ApiAllowListChecker> apiAllowListChecker = nullptr;
1081 if (moduleLoadChecker_ && !moduleLoadChecker_->CheckModuleLoadable(moduleName, apiAllowListChecker, isAppModule)) {
1082 errInfo = "module " + std::string(moduleName) + " is in blocklist, loading prohibited";
1083 HILOG_WARN("%{public}s", errInfo.c_str());
1084 return nullptr;
1085 }
1086
1087 std::string moduleKey(moduleName);
1088 if (isAppModule) {
1089 moduleKey = path;
1090 moduleKey = moduleKey + '/' + moduleName;
1091 }
1092 loadingModuleName_ = moduleKey;
1093
1094 // load primary module path first
1095 char* loadPath = nativeModulePath[0];
1096 HILOG_DEBUG("moduleName is %{public}s. get primary module path is %{public}s", moduleName, loadPath);
1097 uint32_t errReason0 = MODULE_LOAD_SUCCESS;
1098 errInfo = "First attempt: ";
1099 LIBHANDLE lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason0);
1100 if (lib == nullptr) {
1101 errInfo += "\nSecond attempt: ";
1102 loadPath = nativeModulePath[1];
1103 HILOG_DEBUG("try to load secondary module path: %{public}s", loadPath);
1104 uint32_t errReason1 = MODULE_LOAD_SUCCESS;
1105 lib = LoadModuleLibrary(moduleKey, loadPath, path, isAppModule, errInfo, errReason1);
1106 if (lib == nullptr && errReason0 == MODULE_NOT_EXIST && errReason1 == MODULE_NOT_EXIST) {
1107 HILOG_ERROR("%{public}s does not exist, errMsg %{public}s", nativeModulePath[0], errInfo.c_str());
1108 }
1109 }
1110
1111 //Maintain compatibility
1112 if (lib == nullptr && cacheNativeModule != nullptr) {
1113 HILOG_DEBUG("Maintain compatibility.");
1114 return cacheNativeModule;
1115 }
1116
1117 const uint8_t* abcBuffer = nullptr;
1118 size_t len = 0;
1119 if (lib == nullptr) {
1120 loadPath = nativeModulePath[2]; // 2 : Element index value
1121 HILOG_DEBUG("try to load abc module path: %{public}s", loadPath);
1122 abcBuffer = GetFileBuffer(loadPath, moduleKey, len);
1123 if (!abcBuffer) {
1124 errInfo += "\ntry to load abc file from " + std::string(loadPath) + " failed";
1125 HILOG_WARN("%{public}s", errInfo.c_str());
1126 return nullptr;
1127 }
1128 }
1129
1130 if (lib != nullptr) {
1131 Napi_onLoadCallback(lib, moduleName);
1132 }
1133
1134 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1135 if (tailNativeModule_ && !abcBuffer) {
1136 const char* moduleName = strdup(moduleKey.c_str());
1137 if (moduleName == nullptr) {
1138 HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1139 return nullptr;
1140 }
1141
1142 tailNativeModule_->moduleName = moduleName;
1143 tailNativeModule_->systemFilePath = strdup(loadPath);
1144 if (strcmp(tailNativeModule_->moduleName, tailNativeModule_->name)) {
1145 HILOG_WARN("mismatch: moduleName is %{public}s, name is %{public}s",
1146 tailNativeModule_->moduleName, tailNativeModule_->name);
1147 HILOG_DEBUG("suggestion: keep .nm_modname the same as moduleName imported or required");
1148 }
1149 }
1150
1151 if (!internal) {
1152 char symbol[NAPI_PATH_MAX] = { 0 };
1153 if (sprintf_s(symbol, sizeof(symbol), "NAPI_%s_GetABCCode", moduleKey.c_str()) == -1) {
1154 if (lib != nullptr) {
1155 LIBFREE(lib);
1156 }
1157 errInfo = "sprintf symbol NAPI_" + moduleKey + "_GetABCCode failed";
1158 HILOG_ERROR("%{public}s", errInfo.c_str());
1159 return nullptr;
1160 }
1161
1162 // replace '.' and '/' with '_'
1163 for (char* p = strchr(symbol, '.'); p != nullptr; p = strchr(p + 1, '.')) {
1164 *p = '_';
1165 }
1166 for (char* p = strchr(symbol, '/'); p != nullptr; p = strchr(p + 1, '/')) {
1167 *p = '_';
1168 }
1169
1170 if (lib != nullptr) {
1171 auto getJSCode = reinterpret_cast<GetJSCodeCallback>(LIBSYM(lib, symbol));
1172 if (getJSCode == nullptr) {
1173 HILOG_DEBUG("ignore: no %{public}s in %{public}s", symbol, loadPath);
1174 MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1175 return tailNativeModule_;
1176 }
1177 const char* buf = nullptr;
1178 int bufLen = 0;
1179 getJSCode(&buf, &bufLen);
1180 if (tailNativeModule_) {
1181 HILOG_DEBUG("get js code from module: bufLen: %{public}d", bufLen);
1182 tailNativeModule_->jsCode = buf;
1183 tailNativeModule_->jsCodeLen = bufLen;
1184 }
1185 } else {
1186 RegisterByBuffer(moduleKey, abcBuffer, len);
1187 tailNativeModule_->systemFilePath = strdup(loadPath);
1188 }
1189 }
1190 if (tailNativeModule_) {
1191 tailNativeModule_->moduleLoaded = true;
1192 if (tailNativeModule_->name && tailNativeModule_->moduleName) {
1193 HILOG_DEBUG("last native info: name is %{public}s, moduleName is %{public}s",
1194 tailNativeModule_->name, tailNativeModule_->moduleName);
1195 }
1196 MoveApiAllowListCheckerPtr(apiAllowListChecker, tailNativeModule_);
1197 }
1198 return tailNativeModule_;
1199 }
1200
RegisterByBuffer(const std::string & moduleKey,const uint8_t * abcBuffer,size_t len)1201 void NativeModuleManager::RegisterByBuffer(const std::string& moduleKey, const uint8_t* abcBuffer, size_t len)
1202 {
1203 HILOG_DEBUG("native module name is '%{public}s'", moduleKey.c_str());
1204 if (!CreateTailNativeModule()) {
1205 HILOG_ERROR("create tail nativeModule failed");
1206 return;
1207 }
1208
1209 char *moduleName = strdup(moduleKey.c_str());
1210 if (moduleName == nullptr) {
1211 HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleKey.c_str());
1212 return;
1213 }
1214 tailNativeModule_->moduleName = moduleName;
1215 tailNativeModule_->name = strdup(moduleName);
1216 if (tailNativeModule_->name == nullptr) {
1217 HILOG_ERROR("strdup failed. moduleKey is %{public}s", moduleName);
1218 free(moduleName);
1219 tailNativeModule_->moduleName = nullptr;
1220 return;
1221 }
1222 tailNativeModule_->jsABCCode = abcBuffer;
1223 tailNativeModule_->jsCodeLen = static_cast<int32_t>(len);
1224 tailNativeModule_->next = nullptr;
1225
1226 HILOG_INFO("Register by buffer success. module name is '%{public}s'", tailNativeModule_->moduleName);
1227 }
1228
RemoveNativeModuleByCache(const std::string & moduleKey)1229 bool NativeModuleManager::RemoveNativeModuleByCache(const std::string& moduleKey)
1230 {
1231 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1232 if (headNativeModule_ == nullptr) {
1233 HILOG_WARN("NativeModule list is empty");
1234 return false;
1235 }
1236 NativeModule* nativeModule = headNativeModule_;
1237 if (!strcasecmp(nativeModule->moduleName, moduleKey.c_str())) {
1238 if (headNativeModule_ == tailNativeModule_) {
1239 tailNativeModule_ = nullptr;
1240 }
1241 headNativeModule_ = headNativeModule_->next;
1242 delete[] nativeModule->name;
1243 if (nativeModule->moduleName) {
1244 delete[] nativeModule->moduleName;
1245 }
1246 if (nativeModule->jsABCCode) {
1247 delete[] nativeModule->jsABCCode;
1248 }
1249 if (nativeModule->systemFilePath && nativeModule->systemFilePath[0] != '\0') {
1250 free(const_cast<char *>(nativeModule->systemFilePath));
1251 }
1252 delete nativeModule;
1253 HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1254 return true;
1255 }
1256 bool moduleDeleted = false;
1257 NativeModule* prev = headNativeModule_;
1258 NativeModule* curr = prev->next;
1259 while (curr != nullptr) {
1260 if (!strcasecmp(curr->moduleName, moduleKey.c_str())) {
1261 if (curr == tailNativeModule_) {
1262 tailNativeModule_ = prev;
1263 }
1264 prev->next = curr->next;
1265 delete[] curr->name;
1266 if (curr->moduleName) {
1267 delete[] curr->moduleName;
1268 }
1269 if (curr->jsABCCode) {
1270 delete[] curr->jsABCCode;
1271 }
1272 if (curr->systemFilePath && curr->systemFilePath[0] != '\0') {
1273 free(const_cast<char *>(curr->systemFilePath));
1274 }
1275 delete curr;
1276 HILOG_DEBUG("module %{public}s deleted from cache", moduleKey.c_str());
1277 moduleDeleted = true;
1278 break;
1279 }
1280 prev = prev->next;
1281 curr = prev->next;
1282 }
1283 return moduleDeleted;
1284 }
1285
FindNativeModuleByCache(const char * moduleName,char nativeModulePath[][NAPI_PATH_MAX],NativeModule * & cacheNativeModule,NativeModuleHeadTailStruct & cacheHeadTailStruct)1286 NativeModule* NativeModuleManager::FindNativeModuleByCache(const char* moduleName,
1287 char nativeModulePath[][NAPI_PATH_MAX],
1288 NativeModule*& cacheNativeModule,
1289 NativeModuleHeadTailStruct& cacheHeadTailStruct)
1290 {
1291 NativeModule* result = nullptr;
1292
1293 std::lock_guard<std::mutex> lock(nativeModuleListMutex_);
1294 cacheNativeModule = nullptr;
1295 for (NativeModule* temp = headNativeModule_; temp != nullptr; temp = temp->next) {
1296 if ((temp->moduleName && !strcmp(temp->moduleName, moduleName))
1297 || !strcasecmp(temp->name, moduleName)) {
1298 int label = 0;
1299 #if !defined(ANDROID_PLATFORM) && !defined(IOS_PLATFORM)
1300 while (label < NATIVE_PATH_NUMBER && strcmp(temp->systemFilePath, nativeModulePath[label])) {
1301 label++;
1302 }
1303 #endif
1304 if (label < NATIVE_PATH_NUMBER || !strcmp(temp->systemFilePath, "")) {
1305 result = temp;
1306 break;
1307 } else {
1308 HILOG_WARN("moduleName '%{public}s' is in different path", moduleName);
1309 cacheNativeModule = temp;
1310 }
1311 }
1312 }
1313 cacheHeadTailStruct.headNativeModule = headNativeModule_;
1314 cacheHeadTailStruct.tailNativeModule = tailNativeModule_;
1315
1316 return result;
1317 }
1318
IsExistedPath(const char * pathKey) const1319 bool NativeModuleManager::IsExistedPath(const char* pathKey) const
1320 {
1321 HILOG_DEBUG("pathKey is '%{public}s'", pathKey);
1322 std::lock_guard<std::mutex> guard(appLibPathMapMutex_);
1323 return pathKey && appLibPathMap_.find(pathKey) != appLibPathMap_.end();
1324 }
1325
SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate> & moduleCheckerDelegate)1326 void NativeModuleManager::SetModuleLoadChecker(const std::shared_ptr<ModuleCheckerDelegate>& moduleCheckerDelegate)
1327 {
1328 HILOG_DEBUG("enter");
1329 if (!moduleLoadChecker_) {
1330 HILOG_ERROR("SetModuleLoadChecker failed, moduleLoadChecker_ is nullptr");
1331 return;
1332 }
1333 moduleLoadChecker_->SetDelegate(moduleCheckerDelegate);
1334 }
1335
SetPreviewSearchPath(const std::string & previewSearchPath)1336 void NativeModuleManager::SetPreviewSearchPath(const std::string& previewSearchPath)
1337 {
1338 HILOG_DEBUG("previewSearchPath is '%{public}s'", previewSearchPath.c_str());
1339 previewSearchPath_ = previewSearchPath;
1340 }
1341