1 /*
2 * Copyright (c) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "native_args_child_process.h"
17
18 #include <dlfcn.h>
19 #include "hilog_tag_wrapper.h"
20 #include "securec.h"
21
22 namespace OHOS {
23 namespace AbilityRuntime {
24
Create()25 std::shared_ptr<ChildProcess> NativeArgsChildProcess::Create()
26 {
27 return std::make_shared<NativeArgsChildProcess>();
28 }
29
~NativeArgsChildProcess()30 NativeArgsChildProcess::~NativeArgsChildProcess()
31 {
32 UnloadNativeLib();
33 }
34
Init(const std::shared_ptr<ChildProcessStartInfo> & info)35 bool NativeArgsChildProcess::Init(const std::shared_ptr<ChildProcessStartInfo> &info)
36 {
37 TAG_LOGD(AAFwkTag::PROCESSMGR, "NativeArgsChildProcess init called.");
38 if (info == nullptr) {
39 TAG_LOGE(AAFwkTag::PROCESSMGR, "info is nullptr.");
40 return false;
41 }
42
43 if (!ChildProcess::Init(info)) {
44 TAG_LOGE(AAFwkTag::PROCESSMGR, "Base class init failed.");
45 return false;
46 }
47
48 return LoadNativeLib(info);
49 }
50
OnStart(std::shared_ptr<AppExecFwk::ChildProcessArgs> args)51 void NativeArgsChildProcess::OnStart(std::shared_ptr<AppExecFwk::ChildProcessArgs> args)
52 {
53 if (args == nullptr) {
54 TAG_LOGE(AAFwkTag::PROCESSMGR, "args is nullptr.");
55 return;
56 }
57 ChildProcess::OnStart(args);
58
59 TAG_LOGI(AAFwkTag::PROCESSMGR, "Enter native lib entry function");
60 auto nativeArgs = ParseToNativeArgs(args->entryParams, args->fds);
61
62 if (!entryFunc_) {
63 TAG_LOGE(AAFwkTag::PROCESSMGR, "entryFunc nullptr.");
64 return;
65 }
66 entryFunc_(nativeArgs);
67 TAG_LOGI(AAFwkTag::PROCESSMGR, "Native lib entry function returned");
68 }
69
ParseToNativeArgs(const std::string & entryParams,const std::map<std::string,int32_t> & fds)70 NativeChildProcess_Args NativeArgsChildProcess::ParseToNativeArgs(const std::string &entryParams,
71 const std::map<std::string, int32_t> &fds)
72 {
73 NativeChildProcess_Args args;
74 args.fdList.head = nullptr;
75 args.entryParams = new(std::nothrow) char[entryParams.size() + 1];
76 if (!args.entryParams) {
77 TAG_LOGE(AAFwkTag::PROCESSMGR, "entryParams nullptr.");
78 return args;
79 }
80 if (strcpy_s(args.entryParams, entryParams.size() + 1, entryParams.c_str()) != ERR_OK) {
81 delete[] args.entryParams;
82 args.entryParams = nullptr;
83 TAG_LOGE(AAFwkTag::APPKIT, "strcpy_s failed.");
84 return args;
85 }
86 NativeChildProcess_Fd *tail = nullptr;
87 for (const auto &fd : fds) {
88 auto &fdName = fd.first;
89 auto fdValue = fd.second;
90
91 NativeChildProcess_Fd *node = new(std::nothrow) NativeChildProcess_Fd;
92 if (!node) {
93 TAG_LOGE(AAFwkTag::PROCESSMGR, "fd node nullptr.");
94 return args;
95 }
96 node->next = nullptr;
97 node->fdName = new char[fdName.size() + 1];
98 if (strcpy_s(node->fdName, fdName.size() + 1, fdName.c_str()) != ERR_OK) {
99 delete[] node->fdName;
100 node->fdName = nullptr;
101 delete node;
102 node = nullptr;
103 TAG_LOGE(AAFwkTag::APPKIT, "strcpy_s failed.");
104 return args;
105 }
106 node->fd = fdValue;
107
108 if (!args.fdList.head) {
109 args.fdList.head = node;
110 } else {
111 tail->next = node;
112 }
113 tail = node;
114 }
115 return args;
116 }
117
LoadNativeLib(const std::shared_ptr<ChildProcessStartInfo> & info)118 bool NativeArgsChildProcess::LoadNativeLib(const std::shared_ptr<ChildProcessStartInfo> &info)
119 {
120 if (info == nullptr) {
121 TAG_LOGE(AAFwkTag::PROCESSMGR, "info is nullptr.");
122 return false;
123 }
124 TAG_LOGI(AAFwkTag::PROCESSMGR, "LoadNativeLib, moduleName:%{public}s, srcEntry:%{public}s, entryFunc:%{public}s",
125 info->moduleName.c_str(), info->srcEntry.c_str(), info->entryFunc.c_str());
126 if (nativeLibHandle_ != nullptr) {
127 TAG_LOGE(AAFwkTag::PROCESSMGR, "Native lib already loaded.");
128 return false;
129 }
130
131 if (info->moduleName.empty()) {
132 TAG_LOGE(AAFwkTag::PROCESSMGR, "ModuleName is empty");
133 return false;
134 }
135
136 Dl_namespace dlnsApp;
137 std::string appDlNameSpace = "moduleNs_" + info->moduleName;
138 int ret = dlns_get(appDlNameSpace.c_str(), &dlnsApp);
139 if (ret != 0) {
140 TAG_LOGE(AAFwkTag::PROCESSMGR, "Get app dlNamespace(%{private}s) failed, err:%{public}d",
141 appDlNameSpace.c_str(), ret);
142 return false;
143 }
144
145 void *libHandle = dlopen_ns(&dlnsApp, info->srcEntry.c_str(), RTLD_LAZY);
146 if (libHandle == nullptr) {
147 TAG_LOGE(AAFwkTag::PROCESSMGR, "Load lib file %{private}s failed, err %{public}s",
148 info->srcEntry.c_str(), dlerror());
149 return false;
150 }
151
152 auto entryFunc = reinterpret_cast<NativeArgsChildProcess_EntryFunc>(dlsym(libHandle, info->entryFunc.c_str()));
153 if (entryFunc == nullptr) {
154 TAG_LOGE(AAFwkTag::PROCESSMGR, "Get entryFunc address failed, err %{public}s", dlerror());
155 dlclose(libHandle);
156 return false;
157 }
158
159 entryFunc_ = entryFunc;
160 nativeLibHandle_ = libHandle;
161 return true;
162 }
163
UnloadNativeLib()164 void NativeArgsChildProcess::UnloadNativeLib()
165 {
166 if (nativeLibHandle_ != nullptr) {
167 dlclose(nativeLibHandle_);
168 nativeLibHandle_ = nullptr;
169 entryFunc_ = nullptr;
170 }
171 }
172
173 } // namespace AbilityRuntime
174 } // namespace OHOS