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