1 /*
2 * Copyright (c) 2023-2025 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 "aot/aot_executor.h"
17
18 #include <cerrno>
19 #include <csignal>
20 #include <cstdint>
21 #include <cstdlib>
22 #include <cstring>
23 #include <filesystem>
24 #include <iostream>
25 #include <sstream>
26 #include <string>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30 #include <unistd.h>
31
32 #include "app_log_tag_wrapper.h"
33 #include "app_log_wrapper.h"
34 #include "bundle_constants.h"
35 #include "bundle_extractor.h"
36 #include "bundle_service_constants.h"
37 #if defined(CODE_SIGNATURE_ENABLE)
38 #include "aot_compiler_client.h"
39 #include "code_sign_utils.h"
40 #endif
41 #include "installd/installd_operator.h"
42 #include "system_ability_definition.h"
43
44 namespace OHOS {
45 namespace AppExecFwk {
46 namespace {
47 constexpr const char* ABC_RELATIVE_PATH = "ets/modules.abc";
48 constexpr const char* STATIC_ABC_RELATIVE_PATH = "ets/modules_static.abc";
49 constexpr const char* HEX_PREFIX = "0x";
50 constexpr const char* BUNDLE_NAME = "bundleName";
51 constexpr const char* MODULE_NAME = "moduleName";
52 constexpr const char* PKG_PATH = "pkgPath";
53 constexpr const char* ABC_NAME = "abcName";
54 constexpr const char* ABC_PATH = "ABC-Path";
55 constexpr const char* AN_FILE_NAME = "anFileName";
56 constexpr const char* ABC_OFFSET = "abcOffset";
57 constexpr const char* ABC_SIZE = "abcSize";
58 constexpr const char* PROCESS_UID = "processUid";
59 constexpr const char* BUNDLE_UID = "bundleUid";
60 constexpr const char* APP_IDENTIFIER = "appIdentifier";
61 constexpr const char* IS_ENCRYPTED_BUNDLE = "isEncryptedBundle";
62 constexpr const char* IS_SCREEN_OFF = "isScreenOff";
63 constexpr const char* PGO_DIR = "pgoDir";
64 constexpr const char* IS_SYS_COMP = "isSysComp";
65 constexpr const char* IS_SYS_COMP_FALSE = "0";
66 constexpr const char* IS_SYS_COMP_TRUE = "1";
67 #if defined(CODE_SIGNATURE_ENABLE)
68 constexpr int16_t ERR_AOT_COMPILER_SIGN_FAILED = 10004;
69 constexpr int16_t ERR_AOT_COMPILER_CALL_CRASH = 10008;
70 constexpr int16_t ERR_AOT_COMPILER_CALL_CANCELLED = 10009;
71 #endif
72 }
73
GetInstance()74 AOTExecutor& AOTExecutor::GetInstance()
75 {
76 static AOTExecutor executor;
77 return executor;
78 }
79
DecToHex(uint32_t decimal) const80 std::string AOTExecutor::DecToHex(uint32_t decimal) const
81 {
82 APP_LOGD("DecToHex begin, decimal : %{public}u", decimal);
83 std::stringstream ss;
84 ss << std::hex << decimal;
85 std::string hexString = HEX_PREFIX + ss.str();
86 APP_LOGD("hex : %{public}s", hexString.c_str());
87 return hexString;
88 }
89
CheckArgs(const AOTArgs & aotArgs) const90 bool AOTExecutor::CheckArgs(const AOTArgs &aotArgs) const
91 {
92 if (aotArgs.compileMode.empty() || aotArgs.hapPath.empty() || aotArgs.outputPath.empty()) {
93 APP_LOGE("aotArgs check failed");
94 return false;
95 }
96 if (aotArgs.compileMode == ServiceConstants::COMPILE_PARTIAL && aotArgs.arkProfilePath.empty()) {
97 APP_LOGE("partial mode, arkProfilePath can't be empty");
98 return false;
99 }
100 return true;
101 }
102
GetAbcRelativePath(const std::string & moduleArkTSMode) const103 std::string AOTExecutor::GetAbcRelativePath(const std::string &moduleArkTSMode) const
104 {
105 if (moduleArkTSMode == Constants::ARKTS_MODE_DYNAMIC) {
106 return ABC_RELATIVE_PATH;
107 }
108 if (moduleArkTSMode == Constants::ARKTS_MODE_STATIC || moduleArkTSMode == Constants::ARKTS_MODE_HYBRID) {
109 return STATIC_ABC_RELATIVE_PATH;
110 }
111 APP_LOGW("invalid moduleArkTSMode : %{public}s", moduleArkTSMode.c_str());
112 return Constants::EMPTY_STRING;
113 }
114
GetAbcFileInfo(const std::string & hapPath,const std::string & moduleArkTSMode,uint32_t & offset,uint32_t & length) const115 bool AOTExecutor::GetAbcFileInfo(const std::string &hapPath, const std::string &moduleArkTSMode,
116 uint32_t &offset, uint32_t &length) const
117 {
118 BundleExtractor extractor(hapPath);
119 if (!extractor.Init()) {
120 APP_LOGE("init BundleExtractor failed");
121 return false;
122 }
123 std::string abcRelativePath = GetAbcRelativePath(moduleArkTSMode);
124 if (abcRelativePath.empty()) {
125 APP_LOGE("abcRelativePath empty");
126 return false;
127 }
128 if (!extractor.GetFileInfo(abcRelativePath, offset, length)) {
129 APP_LOGE("GetFileInfo failed");
130 return false;
131 }
132 APP_LOGD("GetFileInfo success, offset : %{public}u, length : %{public}u", offset, length);
133 return true;
134 }
135
PrepareArgs(const AOTArgs & aotArgs,AOTArgs & completeArgs) const136 ErrCode AOTExecutor::PrepareArgs(const AOTArgs &aotArgs, AOTArgs &completeArgs) const
137 {
138 APP_LOGD("PrepareArgs begin");
139 if (aotArgs.isSysComp) {
140 APP_LOGD("sysComp, no need to prepare args");
141 completeArgs = aotArgs;
142 return ERR_OK;
143 }
144 if (!CheckArgs(aotArgs)) {
145 APP_LOGE("param check failed");
146 return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
147 }
148 completeArgs = aotArgs;
149 if (!GetAbcFileInfo(completeArgs.hapPath, completeArgs.moduleArkTSMode,
150 completeArgs.offset, completeArgs.length)) {
151 APP_LOGE("GetAbcFileInfo failed");
152 return ERR_APPEXECFWK_INSTALLD_AOT_ABC_NOT_EXIST;
153 }
154 // handle hsp
155 for (auto &hspInfo : completeArgs.hspVector) {
156 (void)GetAbcFileInfo(hspInfo.hapPath, hspInfo.moduleArkTSMode, hspInfo.offset, hspInfo.length);
157 }
158 APP_LOGD("PrepareArgs success");
159 return ERR_OK;
160 }
161
GetSubjectInfo(const AOTArgs & aotArgs) const162 nlohmann::json AOTExecutor::GetSubjectInfo(const AOTArgs &aotArgs) const
163 {
164 /* obtain the uid of current process */
165 int32_t currentProcessUid = static_cast<int32_t>(getuid());
166
167 std::filesystem::path filePath(aotArgs.arkProfilePath);
168 nlohmann::json subject;
169 subject[BUNDLE_NAME] = aotArgs.bundleName;
170 subject[MODULE_NAME] = aotArgs.moduleName;
171 subject[PKG_PATH] = aotArgs.hapPath;
172 subject[ABC_NAME] = GetAbcRelativePath(aotArgs.moduleArkTSMode);
173 subject[ABC_OFFSET] = DecToHex(aotArgs.offset);
174 subject[ABC_SIZE] = DecToHex(aotArgs.length);
175 subject[PROCESS_UID] = DecToHex(currentProcessUid);
176 subject[BUNDLE_UID] = DecToHex(aotArgs.bundleUid);
177 subject[APP_IDENTIFIER] = aotArgs.appIdentifier;
178 subject[IS_ENCRYPTED_BUNDLE] = DecToHex(aotArgs.isEncryptedBundle);
179 subject[IS_SCREEN_OFF] = DecToHex(aotArgs.isScreenOff);
180 subject[PGO_DIR] = filePath.parent_path().string();
181 return subject;
182 }
183
MapSysCompArgs(const AOTArgs & aotArgs,std::unordered_map<std::string,std::string> & argsMap)184 void AOTExecutor::MapSysCompArgs(const AOTArgs &aotArgs, std::unordered_map<std::string, std::string> &argsMap)
185 {
186 APP_LOGI_NOFUNC("MapSysCompArgs : %{public}s", aotArgs.ToString().c_str());
187 argsMap.emplace(IS_SYS_COMP, IS_SYS_COMP_TRUE);
188 argsMap.emplace(ABC_PATH, aotArgs.sysCompPath);
189 argsMap.emplace(AN_FILE_NAME, aotArgs.anFileName);
190 uid_t uid = getuid();
191 if (uid > UINT32_MAX) {
192 APP_LOGE_NOFUNC("invalid uid");
193 return;
194 }
195 argsMap.emplace(PROCESS_UID, DecToHex(uid));
196 }
197
MapHapArgs(const AOTArgs & aotArgs,std::unordered_map<std::string,std::string> & argsMap)198 void AOTExecutor::MapHapArgs(const AOTArgs &aotArgs, std::unordered_map<std::string, std::string> &argsMap)
199 {
200 APP_LOGD("MapHapArgs : %{public}s", aotArgs.ToString().c_str());
201 nlohmann::json subject = GetSubjectInfo(aotArgs);
202
203 nlohmann::json objectArray = nlohmann::json::array();
204 for (const auto &hspInfo : aotArgs.hspVector) {
205 nlohmann::json object;
206 object[BUNDLE_NAME] = hspInfo.bundleName;
207 object[MODULE_NAME] = hspInfo.moduleName;
208 object[PKG_PATH] = hspInfo.hapPath;
209 object[ABC_NAME] = GetAbcRelativePath(hspInfo.moduleArkTSMode);
210 object[Constants::MODULE_ARKTS_MODE] = hspInfo.moduleArkTSMode;
211 object[ABC_OFFSET] = DecToHex(hspInfo.offset);
212 object[ABC_SIZE] = DecToHex(hspInfo.length);
213 objectArray.push_back(object);
214 }
215 argsMap.emplace("target-compiler-mode", aotArgs.compileMode);
216 argsMap.emplace("aot-file", aotArgs.outputPath + ServiceConstants::PATH_SEPARATOR + aotArgs.moduleName);
217 argsMap.emplace("compiler-pkg-info", subject.dump());
218 argsMap.emplace("compiler-external-pkg-info", objectArray.dump());
219 argsMap.emplace("compiler-opt-bc-range", aotArgs.optBCRangeList);
220 argsMap.emplace("compiler-device-state", std::to_string(aotArgs.isScreenOff));
221 argsMap.emplace("compiler-baseline-pgo", std::to_string(aotArgs.isEnableBaselinePgo));
222 std::string abcPath =
223 aotArgs.hapPath + ServiceConstants::PATH_SEPARATOR + GetAbcRelativePath(aotArgs.moduleArkTSMode);
224 argsMap.emplace(ABC_PATH, abcPath);
225 argsMap.emplace("BundleUid", std::to_string(aotArgs.bundleUid));
226 argsMap.emplace("BundleGid", std::to_string(aotArgs.bundleGid));
227 argsMap.emplace(AN_FILE_NAME, aotArgs.anFileName);
228 argsMap.emplace("appIdentifier", aotArgs.appIdentifier);
229 argsMap.emplace(Constants::MODULE_ARKTS_MODE, aotArgs.moduleArkTSMode);
230 argsMap.emplace(IS_SYS_COMP, IS_SYS_COMP_FALSE);
231
232 for (const auto &arg : argsMap) {
233 LOG_NOFUNC_I(BMS_TAG_AOT, "%{public}s: %{public}s", arg.first.c_str(), arg.second.c_str());
234 }
235 }
236
PendSignAOT(const std::string & anFileName,const std::vector<uint8_t> & signData) const237 ErrCode AOTExecutor::PendSignAOT(const std::string &anFileName, const std::vector<uint8_t> &signData) const
238 {
239 return EnforceCodeSign(anFileName, signData);
240 }
241
EnforceCodeSign(const std::string & anFileName,const std::vector<uint8_t> & signData) const242 ErrCode AOTExecutor::EnforceCodeSign(const std::string &anFileName, const std::vector<uint8_t> &signData) const
243 {
244 #if defined(CODE_SIGNATURE_ENABLE)
245 if (signData.empty()) {
246 APP_LOGI("not enforce code sign if no aot file save");
247 return ERR_OK;
248 }
249 uint32_t dataSize = static_cast<uint32_t>(signData.size());
250 auto retCS =
251 Security::CodeSign::CodeSignUtils::EnforceCodeSignForFile(anFileName, signData.data(), dataSize);
252 if (retCS == VerifyErrCode::CS_ERR_ENABLE) {
253 APP_LOGI("pending enforce code sign as screen not first unlock after reboot");
254 return ERR_APPEXECFWK_INSTALLD_SIGN_AOT_DISABLE;
255 }
256 if (retCS != CommonErrCode::CS_SUCCESS) {
257 APP_LOGE("fail to enable code signature for the aot file");
258 return ERR_APPEXECFWK_INSTALLD_SIGN_AOT_FAILED;
259 }
260 APP_LOGI("sign aot file success");
261 return ERR_OK;
262 #else
263 APP_LOGI("code signature disable, ignore");
264 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
265 #endif
266 }
267
StartAOTCompiler(const AOTArgs & aotArgs,std::vector<uint8_t> & signData)268 ErrCode AOTExecutor::StartAOTCompiler(const AOTArgs &aotArgs, std::vector<uint8_t> &signData)
269 {
270 #if defined(CODE_SIGNATURE_ENABLE)
271 std::unordered_map<std::string, std::string> argsMap;
272 if (aotArgs.isSysComp) {
273 MapSysCompArgs(aotArgs, argsMap);
274 } else {
275 MapHapArgs(aotArgs, argsMap);
276 std::string aotFilePath = ServiceConstants::ARK_CACHE_PATH + aotArgs.bundleName;
277 if (!InstalldOperator::IsExistDir(ServiceConstants::ARK_CACHE_PATH)) {
278 APP_LOGE("ark cache dir not exist");
279 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
280 }
281 if (!InstalldOperator::MkOwnerDir(aotFilePath, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
282 aotArgs.bundleUid, aotArgs.bundleGid)) {
283 APP_LOGE("mk bundle ark cache dir failed");
284 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
285 }
286 }
287 APP_LOGI("start to aot compiler");
288 std::vector<int16_t> fileData;
289 ErrCode ret = ArkCompiler::AotCompilerClient::GetInstance().AotCompiler(argsMap, fileData);
290 if (ret == ERR_AOT_COMPILER_SIGN_FAILED) {
291 APP_LOGE("aot compiler local signature fail");
292 return ERR_APPEXECFWK_INSTALLD_SIGN_AOT_FAILED;
293 } else if (ret == ERR_AOT_COMPILER_CALL_CRASH) {
294 APP_LOGE("aot compiler crash");
295 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_CRASH;
296 } else if (ret == ERR_AOT_COMPILER_CALL_CANCELLED) {
297 APP_LOGE("aot compiler cancel");
298 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_CANCELLED;
299 } else if (ret != ERR_OK) {
300 APP_LOGE("aot compiler fail");
301 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
302 }
303 uint32_t byteSize = static_cast<uint32_t>(fileData.size());
304 for (uint32_t i = 0; i < byteSize; ++i) {
305 signData.emplace_back(static_cast<uint8_t>(fileData[i]));
306 }
307 APP_LOGI("aot compiler success");
308 return ERR_OK;
309 #else
310 APP_LOGI("code signature disable, ignore");
311 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
312 #endif
313 }
314
ExecuteAOT(const AOTArgs & aotArgs,ErrCode & ret,std::vector<uint8_t> & pendSignData)315 void AOTExecutor::ExecuteAOT(const AOTArgs &aotArgs, ErrCode &ret, std::vector<uint8_t> &pendSignData)
316 {
317 #if defined(CODE_SIGNATURE_ENABLE)
318 APP_LOGI("begin to execute AOT");
319 {
320 std::lock_guard<std::mutex> lock(stateMutex_);
321 if (state_.running) {
322 APP_LOGI("AOT is running, ignore");
323 ret = ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
324 return;
325 }
326 }
327 AOTArgs completeArgs;
328 ret = PrepareArgs(aotArgs, completeArgs);
329 if (ret != ERR_OK) {
330 APP_LOGE("prepareArgs fail");
331 return;
332 }
333 {
334 std::lock_guard<std::mutex> lock(stateMutex_);
335 InitState(aotArgs);
336 }
337 APP_LOGI("begin to call aot compiler");
338 std::vector<uint8_t> signData;
339 ret = StartAOTCompiler(completeArgs, signData);
340 if (ret == ERR_OK) {
341 ret = EnforceCodeSign(completeArgs.anFileName, signData);
342 }
343 if (ret == ERR_APPEXECFWK_INSTALLD_SIGN_AOT_DISABLE) {
344 pendSignData = signData;
345 }
346 APP_LOGI("aot compiler finish");
347 {
348 std::lock_guard<std::mutex> lock(stateMutex_);
349 ResetState();
350 }
351 #else
352 APP_LOGI("code signature disable, ignore");
353 ret = ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
354 #endif
355 }
356
StopAOT()357 ErrCode AOTExecutor::StopAOT()
358 {
359 #if defined(CODE_SIGNATURE_ENABLE)
360 APP_LOGI("begin to stop AOT");
361 std::lock_guard<std::mutex> lock(stateMutex_);
362 if (!state_.running) {
363 APP_LOGI("AOT not running, return directly");
364 return ERR_OK;
365 }
366 int32_t ret = ArkCompiler::AotCompilerClient::GetInstance().StopAotCompiler();
367 if (ret != ERR_OK) {
368 APP_LOGE("stop aot compiler fail");
369 return ERR_APPEXECFWK_INSTALLD_STOP_AOT_FAILED;
370 }
371 (void)InstalldOperator::DeleteDir(state_.outputPath);
372 ResetState();
373 return ERR_OK;
374 #else
375 APP_LOGI("code signature disable, ignore");
376 return ERR_APPEXECFWK_INSTALLD_STOP_AOT_FAILED;
377 #endif
378 }
379
InitState(const AOTArgs & aotArgs)380 void AOTExecutor::InitState(const AOTArgs &aotArgs)
381 {
382 state_.running = true;
383 state_.outputPath = aotArgs.outputPath;
384 }
385
ResetState()386 void AOTExecutor::ResetState()
387 {
388 state_.running = false;
389 state_.outputPath.clear();
390 }
391 } // namespace AppExecFwk
392 } // namespace OHOS
393