• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &current_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, &current_ns, ALLOW_ALL_SHARED_LIBS);
482             dlns_inherit(&current_ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
483             dlns_inherit(&ns, &current_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, &current_ns, sharedLibsSonames_);
496         if (strlen(ndk_ns.name) > 0) {
497             dlns_inherit(&ns, &ndk_ns, ALLOW_ALL_SHARED_LIBS);
498             dlns_inherit(&ndk_ns, &current_ns, ALLOW_ALL_SHARED_LIBS);
499             dlns_inherit(&current_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