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