1 /*
2 * Copyright (c) 2023-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 "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_wrapper.h"
33 #include "bundle_constants.h"
34 #include "bundle_extractor.h"
35 #include "bundle_service_constants.h"
36 #if defined(CODE_SIGNATURE_ENABLE)
37 #include "aot_compiler_client.h"
38 #include "code_sign_utils.h"
39 #endif
40 #include "installd/installd_operator.h"
41 #include "installd/installd_host_impl.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* HEX_PREFIX = "0x";
49 constexpr const char* BUNDLE_NAME = "bundleName";
50 constexpr const char* MODULE_NAME = "moduleName";
51 constexpr const char* PKG_PATH = "pkgPath";
52 constexpr const char* ABC_NAME = "abcName";
53 constexpr const char* ABC_OFFSET = "abcOffset";
54 constexpr const char* ABC_SIZE = "abcSize";
55 constexpr const char* PROCESS_UID = "processUid";
56 constexpr const char* BUNDLE_UID = "bundleUid";
57 constexpr const char* APP_IDENTIFIER = "appIdentifier";
58 constexpr const char* IS_ENCRYPTED_BUNDLE = "isEncryptedBundle";
59 constexpr const char* IS_SCREEN_OFF = "isScreenOff";
60 constexpr const char* PGO_DIR = "pgoDir";
61 #if defined(CODE_SIGNATURE_ENABLE)
62 const int32_t ERR_AOT_COMPILER_SIGN_FAILED = 10004;
63 const int32_t ERR_AOT_COMPILER_CALL_CRASH = 10008;
64 const int32_t ERR_AOT_COMPILER_CALL_CANCELLED = 10009;
65 #endif
66 }
67
GetInstance()68 AOTExecutor& AOTExecutor::GetInstance()
69 {
70 static AOTExecutor executor;
71 return executor;
72 }
73
DecToHex(uint32_t decimal) const74 std::string AOTExecutor::DecToHex(uint32_t decimal) const
75 {
76 APP_LOGD("DecToHex begin, decimal : %{public}u", decimal);
77 std::stringstream ss;
78 ss << std::hex << decimal;
79 std::string hexString = HEX_PREFIX + ss.str();
80 APP_LOGD("hex : %{public}s", hexString.c_str());
81 return hexString;
82 }
83
CheckArgs(const AOTArgs & aotArgs) const84 bool AOTExecutor::CheckArgs(const AOTArgs &aotArgs) const
85 {
86 if (aotArgs.compileMode.empty() || aotArgs.hapPath.empty() || aotArgs.outputPath.empty()) {
87 APP_LOGE("aotArgs check failed");
88 return false;
89 }
90 if (aotArgs.compileMode == ServiceConstants::COMPILE_PARTIAL && aotArgs.arkProfilePath.empty()) {
91 APP_LOGE("partial mode, arkProfilePath can't be empty");
92 return false;
93 }
94 return true;
95 }
96
GetAbcFileInfo(const std::string & hapPath,uint32_t & offset,uint32_t & length) const97 bool AOTExecutor::GetAbcFileInfo(const std::string &hapPath, uint32_t &offset, uint32_t &length) const
98 {
99 BundleExtractor extractor(hapPath);
100 if (!extractor.Init()) {
101 APP_LOGE("init BundleExtractor failed");
102 return false;
103 }
104 if (!extractor.GetFileInfo(ABC_RELATIVE_PATH, offset, length)) {
105 APP_LOGE("GetFileInfo failed");
106 return false;
107 }
108 APP_LOGD("GetFileInfo success, offset : %{public}u, length : %{public}u", offset, length);
109 return true;
110 }
111
PrepareArgs(const AOTArgs & aotArgs,AOTArgs & completeArgs) const112 ErrCode AOTExecutor::PrepareArgs(const AOTArgs &aotArgs, AOTArgs &completeArgs) const
113 {
114 APP_LOGD("PrepareArgs begin");
115 if (!CheckArgs(aotArgs)) {
116 APP_LOGE("param check failed");
117 return ERR_APPEXECFWK_INSTALLD_PARAM_ERROR;
118 }
119 completeArgs = aotArgs;
120 if (!GetAbcFileInfo(completeArgs.hapPath, completeArgs.offset, completeArgs.length)) {
121 APP_LOGE("GetAbcFileInfo failed");
122 return ERR_APPEXECFWK_INSTALLD_AOT_ABC_NOT_EXIST;
123 }
124 // handle hsp
125 for (auto &hspInfo : completeArgs.hspVector) {
126 (void)GetAbcFileInfo(hspInfo.hapPath, hspInfo.offset, hspInfo.length);
127 }
128 APP_LOGD("PrepareArgs success");
129 return ERR_OK;
130 }
131
GetSubjectInfo(const AOTArgs & aotArgs) const132 nlohmann::json AOTExecutor::GetSubjectInfo(const AOTArgs &aotArgs) const
133 {
134 /* obtain the uid of current process */
135 int32_t currentProcessUid = static_cast<int32_t>(getuid());
136
137 std::filesystem::path filePath(aotArgs.arkProfilePath);
138 nlohmann::json subject;
139 subject[BUNDLE_NAME] = aotArgs.bundleName;
140 subject[MODULE_NAME] = aotArgs.moduleName;
141 subject[PKG_PATH] = aotArgs.hapPath;
142 subject[ABC_NAME] = ABC_RELATIVE_PATH;
143 subject[ABC_OFFSET] = DecToHex(aotArgs.offset);
144 subject[ABC_SIZE] = DecToHex(aotArgs.length);
145 subject[PROCESS_UID] = DecToHex(currentProcessUid);
146 subject[BUNDLE_UID] = DecToHex(aotArgs.bundleUid);
147 subject[APP_IDENTIFIER] = aotArgs.appIdentifier;
148 subject[IS_ENCRYPTED_BUNDLE] = DecToHex(aotArgs.isEncryptedBundle);
149 subject[IS_SCREEN_OFF] = DecToHex(aotArgs.isScreenOff);
150 subject[PGO_DIR] = filePath.parent_path().string();
151 return subject;
152 }
153
MapArgs(const AOTArgs & aotArgs,std::unordered_map<std::string,std::string> & argsMap)154 void AOTExecutor::MapArgs(const AOTArgs &aotArgs, std::unordered_map<std::string, std::string> &argsMap)
155 {
156 APP_LOGI("ExecuteInCompilerServiceProcess, args %{public}s", aotArgs.ToString().c_str());
157 nlohmann::json subject = GetSubjectInfo(aotArgs);
158
159 nlohmann::json objectArray = nlohmann::json::array();
160 for (const auto &hspInfo : aotArgs.hspVector) {
161 nlohmann::json object;
162 object[BUNDLE_NAME] = hspInfo.bundleName;
163 object[MODULE_NAME] = hspInfo.moduleName;
164 object[PKG_PATH] = hspInfo.hapPath;
165 object[ABC_NAME] = ABC_RELATIVE_PATH;
166 object[ABC_OFFSET] = DecToHex(hspInfo.offset);
167 object[ABC_SIZE] = DecToHex(hspInfo.length);
168 objectArray.push_back(object);
169 }
170 argsMap.emplace("target-compiler-mode", aotArgs.compileMode);
171 argsMap.emplace("aot-file", aotArgs.outputPath + ServiceConstants::PATH_SEPARATOR + aotArgs.moduleName);
172 argsMap.emplace("compiler-pkg-info", subject.dump());
173 argsMap.emplace("compiler-external-pkg-info", objectArray.dump());
174 argsMap.emplace("compiler-opt-bc-range", aotArgs.optBCRangeList);
175 argsMap.emplace("compiler-device-state", std::to_string(aotArgs.isScreenOff));
176 argsMap.emplace("compiler-baseline-pgo", std::to_string(aotArgs.isEnableBaselinePgo));
177 argsMap.emplace("ABC-Path", aotArgs.hapPath + ServiceConstants::PATH_SEPARATOR + ABC_RELATIVE_PATH);
178 argsMap.emplace("BundleUid", std::to_string(aotArgs.bundleUid));
179 argsMap.emplace("BundleGid", std::to_string(aotArgs.bundleGid));
180 argsMap.emplace("anFileName", aotArgs.anFileName);
181 argsMap.emplace("appIdentifier", aotArgs.appIdentifier);
182
183 for (const auto &arg : argsMap) {
184 APP_LOGI("%{public}s: %{public}s", arg.first.c_str(), arg.second.c_str());
185 }
186 }
187
PendSignAOT(const std::string & anFileName,const std::vector<uint8_t> & signData) const188 ErrCode AOTExecutor::PendSignAOT(const std::string &anFileName, const std::vector<uint8_t> &signData) const
189 {
190 return EnforceCodeSign(anFileName, signData);
191 }
192
EnforceCodeSign(const std::string & anFileName,const std::vector<uint8_t> & signData) const193 ErrCode AOTExecutor::EnforceCodeSign(const std::string &anFileName, const std::vector<uint8_t> &signData) const
194 {
195 #if defined(CODE_SIGNATURE_ENABLE)
196 if (signData.empty()) {
197 APP_LOGI("not enforce code sign if no aot file save");
198 return ERR_OK;
199 }
200 uint32_t dataSize = static_cast<uint32_t>(signData.size());
201 auto retCS =
202 Security::CodeSign::CodeSignUtils::EnforceCodeSignForFile(anFileName, signData.data(), dataSize);
203 if (retCS == VerifyErrCode::CS_ERR_ENABLE) {
204 APP_LOGI("pending enforce code sign as screen not first unlock after reboot");
205 return ERR_APPEXECFWK_INSTALLD_SIGN_AOT_DISABLE;
206 }
207 if (retCS != CommonErrCode::CS_SUCCESS) {
208 APP_LOGE("fail to enable code signature for the aot file");
209 return ERR_APPEXECFWK_INSTALLD_SIGN_AOT_FAILED;
210 }
211 APP_LOGI("sign aot file success");
212 return ERR_OK;
213 #else
214 APP_LOGI("code signature disable, ignore");
215 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
216 #endif
217 }
218
StartAOTCompiler(const AOTArgs & aotArgs,std::vector<uint8_t> & signData)219 ErrCode AOTExecutor::StartAOTCompiler(const AOTArgs &aotArgs, std::vector<uint8_t> &signData)
220 {
221 #if defined(CODE_SIGNATURE_ENABLE)
222 std::unordered_map<std::string, std::string> argsMap;
223 MapArgs(aotArgs, argsMap);
224 std::string aotFilePath = ServiceConstants::ARK_CACHE_PATH + aotArgs.bundleName;
225 int32_t ret = InstalldHostImpl().Mkdir(aotFilePath, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH,
226 aotArgs.bundleUid, aotArgs.bundleGid);
227 if (ret != ERR_OK) {
228 APP_LOGE("make aot file output directory fail");
229 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
230 }
231 APP_LOGI("start to aot compiler");
232 std::vector<int16_t> fileData;
233 ret = ArkCompiler::AotCompilerClient::GetInstance().AotCompiler(argsMap, fileData);
234 if (ret == ERR_AOT_COMPILER_SIGN_FAILED) {
235 APP_LOGE("aot compiler local signature fail");
236 return ERR_APPEXECFWK_INSTALLD_SIGN_AOT_FAILED;
237 } else if (ret == ERR_AOT_COMPILER_CALL_CRASH) {
238 APP_LOGE("aot compiler crash");
239 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_CRASH;
240 } else if (ret == ERR_AOT_COMPILER_CALL_CANCELLED) {
241 APP_LOGE("aot compiler cancel");
242 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_CANCELLED;
243 } else if (ret != ERR_OK) {
244 APP_LOGE("aot compiler fail");
245 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
246 }
247 uint32_t byteSize = static_cast<uint32_t>(fileData.size());
248 for (uint32_t i = 0; i < byteSize; ++i) {
249 signData.emplace_back(static_cast<uint8_t>(fileData[i]));
250 }
251 APP_LOGI("aot compiler success");
252 return ERR_OK;
253 #else
254 APP_LOGI("code signature disable, ignore");
255 return ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
256 #endif
257 }
258
ExecuteAOT(const AOTArgs & aotArgs,ErrCode & ret,std::vector<uint8_t> & pendSignData)259 void AOTExecutor::ExecuteAOT(const AOTArgs &aotArgs, ErrCode &ret, std::vector<uint8_t> &pendSignData)
260 {
261 #if defined(CODE_SIGNATURE_ENABLE)
262 APP_LOGI("begin to execute AOT");
263 {
264 std::lock_guard<std::mutex> lock(stateMutex_);
265 if (state_.running) {
266 APP_LOGI("AOT is running, ignore");
267 ret = ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
268 return;
269 }
270 }
271 AOTArgs completeArgs;
272 ret = PrepareArgs(aotArgs, completeArgs);
273 if (ret != ERR_OK) {
274 APP_LOGE("prepareArgs fail");
275 return;
276 }
277 {
278 std::lock_guard<std::mutex> lock(stateMutex_);
279 InitState(aotArgs);
280 }
281 APP_LOGI("begin to call aot compiler");
282 std::vector<uint8_t> signData;
283 ret = StartAOTCompiler(completeArgs, signData);
284 if (ret == ERR_OK) {
285 ret = EnforceCodeSign(completeArgs.anFileName, signData);
286 }
287 if (ret == ERR_APPEXECFWK_INSTALLD_SIGN_AOT_DISABLE) {
288 pendSignData = signData;
289 }
290 APP_LOGI("aot compiler finish");
291 {
292 std::lock_guard<std::mutex> lock(stateMutex_);
293 ResetState();
294 }
295 #else
296 APP_LOGI("code signature disable, ignore");
297 ret = ERR_APPEXECFWK_INSTALLD_AOT_EXECUTE_FAILED;
298 #endif
299 }
300
StopAOT()301 ErrCode AOTExecutor::StopAOT()
302 {
303 #if defined(CODE_SIGNATURE_ENABLE)
304 APP_LOGI("begin to stop AOT");
305 std::lock_guard<std::mutex> lock(stateMutex_);
306 if (!state_.running) {
307 APP_LOGI("AOT not running, return directly");
308 return ERR_OK;
309 }
310 int32_t ret = ArkCompiler::AotCompilerClient::GetInstance().StopAotCompiler();
311 if (ret != ERR_OK) {
312 APP_LOGE("stop aot compiler fail");
313 return ERR_APPEXECFWK_INSTALLD_STOP_AOT_FAILED;
314 }
315 (void)InstalldOperator::DeleteDir(state_.outputPath);
316 ResetState();
317 return ERR_OK;
318 #else
319 APP_LOGI("code signature disable, ignore");
320 return ERR_APPEXECFWK_INSTALLD_STOP_AOT_FAILED;
321 #endif
322 }
323
InitState(const AOTArgs & aotArgs)324 void AOTExecutor::InitState(const AOTArgs &aotArgs)
325 {
326 state_.running = true;
327 state_.outputPath = aotArgs.outputPath;
328 }
329
ResetState()330 void AOTExecutor::ResetState()
331 {
332 state_.running = false;
333 state_.outputPath.clear();
334 }
335 } // namespace AppExecFwk
336 } // namespace OHOS
337