1 /*
2 * Copyright (c) 2021-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 "installd/installd_operator.h"
17
18 #include <algorithm>
19 #if defined(CODE_SIGNATURE_ENABLE)
20 #include "code_sign_utils.h"
21 #endif
22 #if defined(CODE_ENCRYPTION_ENABLE)
23 #include "linux/code_decrypt.h"
24 #endif
25 #include <cerrno>
26 #include <cstdio>
27 #include <dirent.h>
28 #include <dlfcn.h>
29 #include <fcntl.h>
30 #include <filesystem>
31 #include <fstream>
32 #include <map>
33 #include <regex>
34 #include <sstream>
35 #include <string.h>
36 #include <sys/ioctl.h>
37 #include <sys/mman.h>
38 #include <sys/quota.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <unistd.h>
42
43 #include "app_log_tag_wrapper.h"
44 #include "bundle_constants.h"
45 #include "bundle_service_constants.h"
46 #include "bundle_util.h"
47 #include "directory_ex.h"
48 #include "el5_filekey_manager_error.h"
49 #include "el5_filekey_manager_kit.h"
50 #include "ffrt.h"
51 #include "parameters.h"
52 #include "securec.h"
53 #include "hnp_api.h"
54
55 namespace OHOS {
56 namespace AppExecFwk {
57 namespace {
58 constexpr const char* PREFIX_RESOURCE_PATH = "/resources/rawfile/";
59 constexpr const char* PREFIX_LIBS_PATH = "/libs/";
60 constexpr const char* PREFIX_TARGET_PATH = "/print_service/";
61 constexpr const char* HQF_DIR_PREFIX = "patch_";
62 #if defined(CODE_ENCRYPTION_ENABLE)
63 static const char LIB_CODE_CRYPTO_SO_PATH[] = "system/lib/libcode_crypto_metadata_process_utils.z.so";
64 static const char LIB64_CODE_CRYPTO_SO_PATH[] = "system/lib64/libcode_crypto_metadata_process_utils.z.so";
65 static const char CODE_CRYPTO_FUNCTION_NAME[] = "_ZN4OHOS8Security10CodeCrypto15CodeCryptoUtils28"
66 "EnforceMetadataProcessForAppERKNSt3__h13unordered_mapINS3_12basic_stringIcNS3_11char_traitsIcEENS3_"
67 "9allocatorIcEEEESA_NS3_4hashISA_EENS3_8equal_toISA_EENS8_INS3_4pairIKSA_SA_EEEEEEjRbNS2_17InstallBundleTypeERKb";
68 #endif
69 static constexpr int32_t INSTALLS_UID = 3060;
70 static constexpr int32_t MODE_BASE = 07777;
71 static constexpr int32_t KEY_ID_STEP = 2;
72 static constexpr int8_t STR_LIBS_LEN = 4;
73 constexpr const char* PROC_MOUNTS_PATH = "/proc/mounts";
74 constexpr const char* QUOTA_DEVICE_DATA_PATH = "/data";
75 constexpr const char* CACHE_DIR = "cache";
76 constexpr const char* BUNDLE_BASE_CODE_DIR = "/data/app/el1/bundle";
77 constexpr const char* AP_PATH = "ap/";
78 constexpr const char* AI_SUFFIX = ".ai";
79 constexpr const char* DIFF_SUFFIX = ".diff";
80 constexpr const char* BUNDLE_BACKUP_KEEP_DIR = "/.backup";
81 constexpr const char* ATOMIC_SERVICE_PATH = "+auid-";
82 #if defined(CODE_SIGNATURE_ENABLE)
83 using namespace OHOS::Security::CodeSign;
84 #endif
85 #if defined(CODE_ENCRYPTION_ENABLE)
86 static std::string CODE_DECRYPT = "/dev/code_decrypt";
87 static int32_t INVALID_RETURN_VALUE = -1;
88 static int32_t INVALID_FILE_DESCRIPTOR = -1;
89 #endif
90 std::recursive_mutex mMountsLock;
91 static std::map<std::string, std::string> mQuotaReverseMounts;
92 using ApplyPatch = int32_t (*)(const std::string, const std::string, const std::string);
93
HandleScanResult(const std::string & dir,const std::string & subName,ResultMode resultMode)94 static std::string HandleScanResult(
95 const std::string &dir, const std::string &subName, ResultMode resultMode)
96 {
97 if (resultMode == ResultMode::RELATIVE_PATH) {
98 return subName;
99 }
100
101 return dir + ServiceConstants::PATH_SEPARATOR + subName;
102 }
103
StartsWith(const std::string & sourceString,const std::string & targetPrefix)104 static bool StartsWith(const std::string &sourceString, const std::string &targetPrefix)
105 {
106 return sourceString.find(targetPrefix) == 0;
107 }
108
EndsWith(const std::string & sourceString,const std::string & targetSuffix)109 static bool EndsWith(const std::string &sourceString, const std::string &targetSuffix)
110 {
111 if (sourceString.length() < targetSuffix.length()) {
112 return false;
113 }
114 if (sourceString.rfind(targetSuffix) == (sourceString.length() - targetSuffix.length())) {
115 return true;
116 }
117 return false;
118 }
119 } // namespace
120
121 #define FSCRYPT_KEY_DESCRIPTOR_SIZE 8
122 #define HMFS_IOCTL_MAGIC 0xf5
123 #define HMFS_IOC_SET_ASDP_ENCRYPTION_POLICY _IOW(HMFS_IOCTL_MAGIC, 84, struct fscrypt_asdp_policy)
124 #define FORCE_PROTECT 0x0
125
126 struct fscrypt_asdp_policy {
127 char version;
128 char asdp_class;
129 char flags;
130 char reserved;
131 char app_key2_descriptor[FSCRYPT_KEY_DESCRIPTOR_SIZE];
132 } __attribute__((__packed__));
133
CheckAndDeleteLinkFile(const std::string & path)134 bool InstalldOperator::CheckAndDeleteLinkFile(const std::string &path)
135 {
136 struct stat path_stat;
137 if (lstat(path.c_str(), &path_stat) == 0) {
138 if (S_ISLNK(path_stat.st_mode)) {
139 if (unlink(path.c_str()) == 0) {
140 return true;
141 }
142 LOG_E(BMS_TAG_INSTALLD, "CheckAndDeleteLinkFile unlink %{public}s failed, error: %{public}d",
143 path.c_str(), errno);
144 }
145 }
146 LOG_E(BMS_TAG_INSTALLD, "CheckAndDeleteLinkFile lstat or S_ISLNK %{public}s failed, errno:%{public}d",
147 path.c_str(), errno);
148 return false;
149 }
150
IsExistFile(const std::string & path)151 bool InstalldOperator::IsExistFile(const std::string &path)
152 {
153 if (path.empty()) {
154 LOG_E(BMS_TAG_INSTALLD, "path is empty");
155 return false;
156 }
157
158 struct stat buf = {};
159 if (stat(path.c_str(), &buf) != 0) {
160 LOG_NOFUNC_E(BMS_TAG_INSTALLD, "stat fail %{public}d", errno);
161 return false;
162 }
163 return S_ISREG(buf.st_mode);
164 }
165
IsExistApFile(const std::string & path)166 bool InstalldOperator::IsExistApFile(const std::string &path)
167 {
168 std::string realPath;
169 std::filesystem::path apFilePath(path);
170 std::string apDir = apFilePath.parent_path().string();
171 if (path.empty() || !PathToRealPath(apDir, realPath)) {
172 return false;
173 }
174
175 std::error_code errorCode;
176 std::filesystem::directory_iterator iter(realPath, errorCode);
177
178 if (errorCode) {
179 LOG_E(BMS_TAG_INSTALLD, "Error occurred while opening apDir: %{public}s", errorCode.message().c_str());
180 return false;
181 }
182 for (const auto& entry : iter) {
183 if (entry.path().extension() == ServiceConstants::AP_SUFFIX) {
184 return true;
185 }
186 }
187 return false;
188 }
189
IsExistDir(const std::string & path)190 bool InstalldOperator::IsExistDir(const std::string &path)
191 {
192 if (path.empty()) {
193 LOG_E(BMS_TAG_INSTALLD, "path is empty");
194 return false;
195 }
196
197 struct stat buf = {};
198 if (stat(path.c_str(), &buf) != 0) {
199 return false;
200 }
201 return S_ISDIR(buf.st_mode);
202 }
203
IsDirEmpty(const std::string & dir)204 bool InstalldOperator::IsDirEmpty(const std::string &dir)
205 {
206 return OHOS::IsEmptyFolder(dir);
207 }
208
MkRecursiveDir(const std::string & path,bool isReadByOthers)209 bool InstalldOperator::MkRecursiveDir(const std::string &path, bool isReadByOthers)
210 {
211 if (!OHOS::ForceCreateDirectory(path)) {
212 LOG_E(BMS_TAG_INSTALLD, "mkdir failed");
213 return false;
214 }
215 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IXOTH;
216 mode |= (isReadByOthers ? S_IROTH : 0);
217 return OHOS::ChangeModeDirectory(path, mode);
218 }
219
DeleteDir(const std::string & path)220 bool InstalldOperator::DeleteDir(const std::string &path)
221 {
222 if (IsExistFile(path)) {
223 return OHOS::RemoveFile(path);
224 }
225 if (IsExistDir(path)) {
226 LOG_NOFUNC_I(BMS_TAG_COMMON, "del %{public}s", path.c_str());
227 return OHOS::ForceRemoveDirectory(path);
228 }
229 return true;
230 }
231
DeleteDirFast(const std::string & path)232 bool InstalldOperator::DeleteDirFast(const std::string &path)
233 {
234 std::string newPath = GetSameLevelTmpPath(path);
235 if (newPath.empty()) {
236 return DeleteDir(path);
237 }
238 if (rename(path.c_str(), newPath.c_str()) != 0) {
239 LOG_W(BMS_TAG_INSTALLD, "rename failed:%{public}s,%{public}s,%{public}s",
240 std::strerror(errno), path.c_str(), newPath.c_str());
241 return DeleteDir(path);
242 }
243 auto task = [newPath]() {
244 bool ret = InstalldOperator::DeleteDir(newPath);
245 if (!ret) {
246 LOG_E(BMS_TAG_INSTALLD, "async del failed,%{public}s", newPath.c_str());
247 }
248 };
249 ffrt::submit(task);
250 return true;
251 }
252
DeleteDirFlexible(const std::string & path,const bool async)253 bool InstalldOperator::DeleteDirFlexible(const std::string &path, const bool async)
254 {
255 if (async) {
256 return DeleteDirFast(path);
257 }
258 return DeleteDir(path);
259 }
260
DeleteUninstallTmpDir(const std::string & path)261 bool InstalldOperator::DeleteUninstallTmpDir(const std::string &path)
262 {
263 std::vector<std::string> deleteDirs;
264 std::error_code ec;
265 if (!std::filesystem::exists(path, ec) || !std::filesystem::is_directory(path, ec)) {
266 LOG_W(BMS_TAG_INSTALLD, "invalid path:%{public}s,err:%{public}s", path.c_str(), ec.message().c_str());
267 return false;
268 }
269 std::filesystem::directory_iterator dirIter(path, std::filesystem::directory_options::skip_permission_denied, ec);
270 std::filesystem::directory_iterator endIter;
271 if (ec) {
272 LOG_W(BMS_TAG_INSTALLD, "create iterator failed,%{public}s,err:%{public}s", path.c_str(), ec.message().c_str());
273 return false;
274 }
275 for (; dirIter != endIter; dirIter.increment(ec)) {
276 if (ec) {
277 LOG_W(BMS_TAG_INSTALLD, "iteration failed,%{public}s,err:%{public}s", path.c_str(), ec.message().c_str());
278 return false;
279 }
280 const std::filesystem::directory_entry &entry = *dirIter;
281 std::string fileName = entry.path().filename().string();
282 if (fileName.rfind(ServiceConstants::UNINSTALL_TMP_PREFIX, 0) == 0) {
283 deleteDirs.emplace_back(entry.path().string());
284 }
285 }
286 bool ret = true;
287 for (const std::string &dir : deleteDirs) {
288 LOG_W(BMS_TAG_INSTALLD, "begin to delete dir %{public}s", dir.c_str());
289 if (!DeleteDir(dir)) {
290 ret = false;
291 LOG_W(BMS_TAG_INSTALLD, "delete dir failed:%{public}s", dir.c_str());
292 }
293 }
294 return ret;
295 }
296
GetSameLevelTmpPath(const std::string & path)297 std::string InstalldOperator::GetSameLevelTmpPath(const std::string &path)
298 {
299 if (path.empty()) {
300 LOG_I(BMS_TAG_INSTALLD, "path empty");
301 return Constants::EMPTY_STRING;
302 }
303 std::filesystem::path parentPath = std::filesystem::path(path).parent_path();
304 if (parentPath.empty()) {
305 LOG_I(BMS_TAG_INSTALLD, "parentPath empty");
306 return Constants::EMPTY_STRING;
307 }
308 std::error_code ec;
309 std::filesystem::path canonicalParentPath = std::filesystem::canonical(parentPath, ec);
310 if (ec) {
311 LOG_I(BMS_TAG_INSTALLD, "canonical failed:%{public}s", ec.message().c_str());
312 return Constants::EMPTY_STRING;
313 }
314 uint32_t maxTry = 3;
315 for (uint32_t i = 1; i <= maxTry; ++i) {
316 std::string childPath = ServiceConstants::UNINSTALL_TMP_PREFIX + std::to_string(BundleUtil::GetCurrentTimeNs());
317 std::filesystem::path fullPath = canonicalParentPath / childPath;
318 if (std::filesystem::exists(fullPath, ec)) {
319 LOG_I(BMS_TAG_INSTALLD, "fullPath exists");
320 continue;
321 }
322 if (ec) {
323 LOG_I(BMS_TAG_INSTALLD, "exists failed:%{public}s", ec.message().c_str());
324 continue;
325 }
326 return fullPath.string();
327 }
328 LOG_I(BMS_TAG_INSTALLD, "GetSameLevelTmpPath failed");
329 return Constants::EMPTY_STRING;
330 }
331
ExtractFiles(const std::string & sourcePath,const std::string & targetSoPath,const std::string & cpuAbi)332 bool InstalldOperator::ExtractFiles(const std::string &sourcePath, const std::string &targetSoPath,
333 const std::string &cpuAbi)
334 {
335 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles start");
336 if (targetSoPath.empty()) {
337 LOG_D(BMS_TAG_INSTALLD, "targetSoPath is empty");
338 return true;
339 }
340
341 BundleExtractor extractor(sourcePath);
342 if (!extractor.Init()) {
343 return false;
344 }
345
346 std::vector<std::string> soEntryFiles;
347 if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
348 LOG_E(BMS_TAG_INSTALLD, "ExtractFiles obtain native so file entryName failed");
349 return false;
350 }
351
352 for_each(soEntryFiles.begin(), soEntryFiles.end(), [&extractor, &targetSoPath, &cpuAbi](const auto &entry) {
353 ExtractTargetFile(extractor, entry, targetSoPath, cpuAbi);
354 });
355
356 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles end");
357 return true;
358 }
359
ExtractFiles(const ExtractParam & extractParam)360 bool InstalldOperator::ExtractFiles(const ExtractParam &extractParam)
361 {
362 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles start");
363 BundleExtractor extractor(extractParam.srcPath);
364 if (!extractor.Init()) {
365 LOG_E(BMS_TAG_INSTALLD, "extractor init failed");
366 return false;
367 }
368
369 if (extractParam.extractFileType == ExtractFileType::RESOURCE) {
370 return ExtractResourceFiles(extractParam, extractor);
371 }
372
373 if ((extractParam.extractFileType == ExtractFileType::AP) &&
374 !extractor.IsDirExist(AP_PATH)) {
375 LOG_D(BMS_TAG_INSTALLD, "hap has no ap files and does not need to be extracted");
376 return true;
377 }
378
379 std::vector<std::string> entryNames;
380 if (!extractor.GetZipFileNames(entryNames) || entryNames.empty()) {
381 LOG_E(BMS_TAG_INSTALLD, "get entryNames failed");
382 return false;
383 }
384
385 for (const auto &entryName : entryNames) {
386 if (strcmp(entryName.c_str(), ".") == 0 ||
387 strcmp(entryName.c_str(), "..") == 0) {
388 continue;
389 }
390 if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
391 continue;
392 }
393 // handle native file
394 if (IsNativeFile(entryName, extractParam)) {
395 ExtractTargetFile(extractor, entryName, extractParam.targetPath,
396 extractParam.cpuAbi, extractParam.extractFileType);
397 continue;
398 }
399 }
400
401 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles end");
402 return true;
403 }
404
ExtractFiles(const std::string hnpPackageInfo,const ExtractParam & extractParam)405 bool InstalldOperator::ExtractFiles(const std::string hnpPackageInfo, const ExtractParam &extractParam)
406 {
407 std::map<std::string, std::string> hnpPackageInfoMap;
408 std::stringstream hnpPackageInfoString(hnpPackageInfo);
409 std::string keyValue;
410 while (getline(hnpPackageInfoString, keyValue, '}')) {
411 size_t pos = keyValue.find(":");
412 if (pos != std::string::npos) {
413 std::string key = keyValue.substr(1, pos - 1);
414 std::string value = keyValue.substr(pos + 1);
415 hnpPackageInfoMap[key] = value;
416 }
417 }
418
419 BundleExtractor extractor(extractParam.srcPath);
420 if (!extractor.Init()) {
421 LOG_E(BMS_TAG_INSTALLD, "extractor init failed");
422 return false;
423 }
424
425 std::vector<std::string> entryNames;
426 if (!extractor.GetZipFileNames(entryNames) || entryNames.empty()) {
427 LOG_E(BMS_TAG_INSTALLD, "get entryNames failed");
428 return false;
429 }
430 std::string targetPathAndName = "";
431 for (const auto &entryName : entryNames) {
432 if (strcmp(entryName.c_str(), ".") == 0 ||
433 strcmp(entryName.c_str(), "..") == 0) {
434 continue;
435 }
436 if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
437 continue;
438 }
439 // handle native file
440 if (IsNativeFile(entryName, extractParam)) {
441 std::string prefix;
442
443 if (!DeterminePrefix(extractParam.extractFileType, extractParam.cpuAbi, prefix)) {
444 LOG_E(BMS_TAG_INSTALLD, "determine prefix failed");
445 return false;
446 }
447
448 std::string targetName = entryName.substr(prefix.length());
449 if (hnpPackageInfoMap.find(targetName) == hnpPackageInfoMap.end()) {
450 LOG_E(BMS_TAG_INSTALLD, "illegal native bundle");
451 continue;
452 }
453 targetPathAndName = extractParam.targetPath + hnpPackageInfoMap[targetName]
454 + ServiceConstants::PATH_SEPARATOR + targetName;
455 ExtractTargetHnpFile(extractor, entryName, targetPathAndName, extractParam.extractFileType);
456 hnpPackageInfoMap.erase(targetName);
457 continue;
458 }
459 }
460
461 if (hnpPackageInfoMap.size() > 0) {
462 return false;
463 }
464 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::ExtractFiles end");
465 return true;
466 }
IsNativeFile(const std::string & entryName,const ExtractParam & extractParam)467 bool InstalldOperator::IsNativeFile(
468 const std::string &entryName, const ExtractParam &extractParam)
469 {
470 LOG_D(BMS_TAG_INSTALLD, "IsNativeFile, entryName : %{public}s", entryName.c_str());
471 if (extractParam.targetPath.empty()) {
472 LOG_D(BMS_TAG_INSTALLD, "current hap not include so");
473 return false;
474 }
475 std::string prefix;
476 std::vector<std::string> suffixes;
477 if (!DeterminePrefix(extractParam.extractFileType, extractParam.cpuAbi, prefix) ||
478 !DetermineSuffix(extractParam.extractFileType, suffixes)) {
479 LOG_E(BMS_TAG_INSTALLD, "determine prefix or suffix failed");
480 return false;
481 }
482
483 if (!StartsWith(entryName, prefix)) {
484 LOG_D(BMS_TAG_INSTALLD, "entryName not start with %{public}s", prefix.c_str());
485 return false;
486 }
487
488 bool checkSuffix = false;
489 for (const auto &suffix : suffixes) {
490 if (EndsWith(entryName, suffix)) {
491 checkSuffix = true;
492 break;
493 }
494 }
495
496 if (!checkSuffix && extractParam.extractFileType != ExtractFileType::RES_FILE
497 && extractParam.extractFileType != ExtractFileType::SO
498 && extractParam.extractFileType != ExtractFileType::HNPS_FILE) {
499 LOG_D(BMS_TAG_INSTALLD, "file type error");
500 return false;
501 }
502
503 LOG_D(BMS_TAG_INSTALLD, "find native file, prefix: %{public}s, entryName: %{public}s",
504 prefix.c_str(), entryName.c_str());
505 return true;
506 }
507
IsNativeSo(const std::string & entryName,const std::string & cpuAbi)508 bool InstalldOperator::IsNativeSo(const std::string &entryName, const std::string &cpuAbi)
509 {
510 LOG_D(BMS_TAG_INSTALLD, "IsNativeSo, entryName : %{public}s", entryName.c_str());
511 std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
512 if (!StartsWith(entryName, prefix)) {
513 LOG_D(BMS_TAG_INSTALLD, "entryName not start with %{public}s", prefix.c_str());
514 return false;
515 }
516 LOG_D(BMS_TAG_INSTALLD, "find native so, entryName : %{public}s", entryName.c_str());
517 return true;
518 }
519
IsDiffFiles(const std::string & entryName,const std::string & targetPath,const std::string & cpuAbi)520 bool InstalldOperator::IsDiffFiles(const std::string &entryName,
521 const std::string &targetPath, const std::string &cpuAbi)
522 {
523 LOG_D(BMS_TAG_INSTALLD, "IsDiffFiles, entryName : %{public}s", entryName.c_str());
524 if (targetPath.empty()) {
525 LOG_D(BMS_TAG_INSTALLD, "current hap not include diff");
526 return false;
527 }
528 std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
529 if (!StartsWith(entryName, prefix)) {
530 LOG_D(BMS_TAG_INSTALLD, "entryName not start with %{public}s", prefix.c_str());
531 return false;
532 }
533 if (!EndsWith(entryName, DIFF_SUFFIX)) {
534 LOG_D(BMS_TAG_INSTALLD, "file name not diff format");
535 return false;
536 }
537 LOG_D(BMS_TAG_INSTALLD, "find native diff, entryName : %{public}s", entryName.c_str());
538 return true;
539 }
540
ExtractTargetHnpFile(const BundleExtractor & extractor,const std::string & entryName,const std::string & targetPath,const ExtractFileType & extractFileType)541 void InstalldOperator::ExtractTargetHnpFile(const BundleExtractor &extractor, const std::string &entryName,
542 const std::string &targetPath, const ExtractFileType &extractFileType)
543 {
544 std::string path = targetPath;
545 std::string dir = GetPathDir(path);
546 if (!IsExistDir(dir) && !MkRecursiveDir(dir, true)) {
547 LOG_E(BMS_TAG_INSTALLD, "create dir %{public}s failed", dir.c_str());
548 return;
549 }
550 bool ret = extractor.ExtractFile(entryName, path);
551 if (!ret) {
552 LOG_E(BMS_TAG_INSTALLD, "extract file failed, entryName : %{public}s", entryName.c_str());
553 return;
554 }
555 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
556 if (extractFileType == ExtractFileType::AP) {
557 struct stat buf = {};
558 if (stat(targetPath.c_str(), &buf) != 0) {
559 LOG_E(BMS_TAG_INSTALLD, "fail to stat errno:%{public}d", errno);
560 return;
561 }
562 ChangeFileAttr(path, buf.st_uid, buf.st_gid);
563 mode = (buf.st_uid == buf.st_gid) ? (S_IRUSR | S_IWUSR) : (S_IRUSR | S_IWUSR | S_IRGRP);
564 }
565 if (!OHOS::ChangeModeFile(path, mode)) {
566 LOG_E(BMS_TAG_INSTALLD, "ChangeModeFile %{public}s failed, errno: %{public}d", path.c_str(), errno);
567 return;
568 }
569 LOG_D(BMS_TAG_INSTALLD, "extract file success, path : %{public}s", path.c_str());
570 }
571
ProcessBundleInstallNative(const std::string & userId,const std::string & hnpRootPath,const std::string & hapPath,const std::string & cpuAbi,const std::string & packageName)572 bool InstalldOperator::ProcessBundleInstallNative(const std::string &userId, const std::string &hnpRootPath,
573 const std::string &hapPath, const std::string &cpuAbi, const std::string &packageName)
574 {
575 struct HapInfo hapInfo;
576 int res = strcpy_s(hapInfo.packageName, packageName.length() + 1, packageName.c_str());
577 if (res != ERR_OK) {
578 LOG_E(BMS_TAG_INSTALLD, "failed to strcpy_s packageName");
579 }
580 res = strcpy_s(hapInfo.hapPath, hapPath.length() + 1, hapPath.c_str());
581 if (res != ERR_OK) {
582 LOG_E(BMS_TAG_INSTALLD, "failed to strcpy_s hapPath");
583 }
584 res = strcpy_s(hapInfo.abi, cpuAbi.length() + 1, cpuAbi.c_str());
585 if (res != ERR_OK) {
586 LOG_E(BMS_TAG_INSTALLD, "failed to strcpy_s cpuAbi");
587 }
588 int ret = NativeInstallHnp(userId.c_str(), hnpRootPath.c_str(), &hapInfo, 1);
589 LOG_D(BMS_TAG_INSTALLD, "NativeInstallHnp ret: %{public}d", ret);
590 if (ret != 0) {
591 LOG_E(BMS_TAG_INSTALLD, "Native package installation failed with error code: %{public}d", ret);
592 return false;
593 }
594 return true;
595 }
596
ProcessBundleUnInstallNative(const std::string & userId,const std::string & packageName)597 bool InstalldOperator::ProcessBundleUnInstallNative(const std::string &userId, const std::string &packageName)
598 {
599 int ret = NativeUnInstallHnp(userId.c_str(), packageName.c_str());
600 LOG_D(BMS_TAG_INSTALLD, "NativeUnInstallHnp ret: %{public}d", ret);
601 if (ret != 0) {
602 LOG_E(BMS_TAG_INSTALLD, "Native package uninstallation failed with error code: %{public}d", ret);
603 return false;
604 }
605 return true;
606 }
607
ExtractTargetFile(const BundleExtractor & extractor,const std::string & entryName,const std::string & targetPath,const std::string & cpuAbi,const ExtractFileType & extractFileType)608 void InstalldOperator::ExtractTargetFile(const BundleExtractor &extractor, const std::string &entryName,
609 const std::string &targetPath, const std::string &cpuAbi, const ExtractFileType &extractFileType)
610 {
611 // create dir if not exist
612 if (!IsExistDir(targetPath)) {
613 if (!MkRecursiveDir(targetPath, true)) {
614 LOG_E(BMS_TAG_INSTALLD, "create targetPath %{public}s failed", targetPath.c_str());
615 return;
616 }
617 }
618
619 std::string prefix;
620 if (!DeterminePrefix(extractFileType, cpuAbi, prefix)) {
621 LOG_E(BMS_TAG_INSTALLD, "determine prefix failed");
622 return;
623 }
624 std::string targetName = entryName.substr(prefix.length());
625 std::string path = targetPath;
626 if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
627 path += ServiceConstants::FILE_SEPARATOR_CHAR;
628 }
629 path += targetName;
630 if (targetName.find(ServiceConstants::PATH_SEPARATOR) != std::string::npos) {
631 std::string dir = GetPathDir(path);
632 if (!IsExistDir(dir) && !MkRecursiveDir(dir, true)) {
633 LOG_E(BMS_TAG_INSTALLD, "create dir %{public}s failed", dir.c_str());
634 return;
635 }
636 }
637 bool ret = extractor.ExtractFile(entryName, path);
638 if (!ret) {
639 LOG_E(BMS_TAG_INSTALLD, "extract file failed, entryName : %{public}s", entryName.c_str());
640 return;
641 }
642 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
643 if (extractFileType == ExtractFileType::AP) {
644 struct stat buf = {};
645 if (stat(targetPath.c_str(), &buf) != 0) {
646 LOG_E(BMS_TAG_INSTALLD, "fail to stat errno:%{public}d", errno);
647 return;
648 }
649 ChangeFileAttr(path, buf.st_uid, buf.st_gid);
650 mode = (buf.st_uid == buf.st_gid) ? (S_IRUSR | S_IWUSR) : (S_IRUSR | S_IWUSR | S_IRGRP);
651 }
652 if (!OHOS::ChangeModeFile(path, mode)) {
653 LOG_E(BMS_TAG_INSTALLD, "ChangeModeFile %{public}s failed, errno: %{public}d", path.c_str(), errno);
654 return;
655 }
656 FsyncFile(path);
657 LOG_D(BMS_TAG_INSTALLD, "extract file success, path : %{public}s", path.c_str());
658 }
659
FsyncFile(const std::string & path)660 void InstalldOperator::FsyncFile(const std::string &path)
661 {
662 int32_t fileFd = open(path.c_str(), O_RDONLY);
663 if (fileFd < 0) {
664 LOG_E(BMS_TAG_INSTALLER, "open %{public}s failed %{public}d", path.c_str(), errno);
665 return;
666 }
667 if (fsync(fileFd) != 0) {
668 LOG_E(BMS_TAG_INSTALLER, "fsync %{public}s failed %{public}d", path.c_str(), errno);
669 }
670 close(fileFd);
671 }
672
DeterminePrefix(const ExtractFileType & extractFileType,const std::string & cpuAbi,std::string & prefix)673 bool InstalldOperator::DeterminePrefix(const ExtractFileType &extractFileType, const std::string &cpuAbi,
674 std::string &prefix)
675 {
676 switch (extractFileType) {
677 case ExtractFileType::SO: {
678 prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
679 break;
680 }
681 case ExtractFileType::AN: {
682 prefix = ServiceConstants::AN + cpuAbi + ServiceConstants::PATH_SEPARATOR;
683 break;
684 }
685 case ExtractFileType::AP: {
686 prefix = AP_PATH;
687 break;
688 }
689 case ExtractFileType::RES_FILE: {
690 prefix = ServiceConstants::RES_FILE_PATH;
691 break;
692 }
693 case ExtractFileType::HNPS_FILE: {
694 prefix = ServiceConstants::HNPS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
695 break;
696 }
697 default: {
698 return false;
699 }
700 }
701 return true;
702 }
703
DetermineSuffix(const ExtractFileType & extractFileType,std::vector<std::string> & suffixes)704 bool InstalldOperator::DetermineSuffix(const ExtractFileType &extractFileType, std::vector<std::string> &suffixes)
705 {
706 switch (extractFileType) {
707 case ExtractFileType::SO: {
708 break;
709 }
710 case ExtractFileType::AN: {
711 suffixes.emplace_back(ServiceConstants::AN_SUFFIX);
712 suffixes.emplace_back(AI_SUFFIX);
713 break;
714 }
715 case ExtractFileType::AP: {
716 suffixes.emplace_back(ServiceConstants::AP_SUFFIX);
717 break;
718 }
719 case ExtractFileType::RES_FILE: {
720 break;
721 }
722 case ExtractFileType::HNPS_FILE: {
723 break;
724 }
725 default: {
726 return false;
727 }
728 }
729 return true;
730 }
731
RenameDir(const std::string & oldPath,const std::string & newPath)732 bool InstalldOperator::RenameDir(const std::string &oldPath, const std::string &newPath)
733 {
734 if (oldPath.empty() || oldPath.size() > PATH_MAX) {
735 LOG_E(BMS_TAG_INSTALLD, "oldpath error");
736 return false;
737 }
738 if (access(oldPath.c_str(), F_OK) != 0 && access(newPath.c_str(), F_OK) == 0) {
739 LOG_E(BMS_TAG_INSTALLD, "fail to access file errno:%{public}d", errno);
740 return true;
741 }
742 std::string realOldPath;
743 realOldPath.reserve(PATH_MAX);
744 realOldPath.resize(PATH_MAX - 1);
745 if (realpath(oldPath.c_str(), &(realOldPath[0])) == nullptr) {
746 LOG_NOFUNC_E(BMS_TAG_INSTALLD, "realOldPath:%{public}s errno:%{public}d", realOldPath.c_str(), errno);
747 return false;
748 }
749
750 if (!(IsValidCodePath(realOldPath) && IsValidCodePath(newPath))) {
751 LOG_E(BMS_TAG_INSTALLD, "IsValidCodePath failed");
752 return false;
753 }
754 return RenameFile(realOldPath, newPath);
755 }
756
GetPathDir(const std::string & path)757 std::string InstalldOperator::GetPathDir(const std::string &path)
758 {
759 std::size_t pos = path.rfind(ServiceConstants::PATH_SEPARATOR);
760 if (pos == std::string::npos) {
761 return std::string();
762 }
763 return path.substr(0, pos + 1);
764 }
765
ChangeDirOwnerRecursively(const std::string & path,const int uid,const int gid)766 bool InstalldOperator::ChangeDirOwnerRecursively(const std::string &path, const int uid, const int gid)
767 {
768 std::string subPath;
769 bool ret = true;
770 DIR *dir = opendir(path.c_str());
771 if (dir == nullptr) {
772 LOG_D(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", path.c_str(), errno);
773 return false;
774 }
775
776 while (true) {
777 struct dirent *ptr = readdir(dir);
778 if (ptr == nullptr) {
779 LOG_D(BMS_TAG_INSTALLD, "fail to readdir errno:%{public}d", errno);
780 break;
781 }
782
783 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
784 continue;
785 }
786
787 subPath = OHOS::IncludeTrailingPathDelimiter(path) + std::string(ptr->d_name);
788 if (ptr->d_type == DT_DIR) {
789 ret = ChangeDirOwnerRecursively(subPath, uid, gid);
790 continue;
791 }
792
793 if (access(subPath.c_str(), F_OK) == 0) {
794 if (!ChangeFileAttr(subPath, uid, gid)) {
795 LOG_D(BMS_TAG_INSTALLD, "Failed to ChangeFileAttr %{public}s, uid=%{public}d", subPath.c_str(), uid);
796 closedir(dir);
797 return false;
798 }
799 }
800 }
801
802 closedir(dir);
803 std::string currentPath = OHOS::ExcludeTrailingPathDelimiter(path);
804 if (access(currentPath.c_str(), F_OK) == 0) {
805 if (!ChangeFileAttr(currentPath, uid, gid)) {
806 LOG_D(BMS_TAG_INSTALLD, "Failed to ChangeFileAttr %{public}s, uid=%{public}d", currentPath.c_str(), uid);
807 return false;
808 }
809 }
810
811 return ret;
812 }
813
ChangeFileAttr(const std::string & filePath,const int uid,const int gid)814 bool InstalldOperator::ChangeFileAttr(const std::string &filePath, const int uid, const int gid)
815 {
816 LOG_D(BMS_TAG_INSTALLD, "begin to change %{public}s file attribute", filePath.c_str());
817 if (chown(filePath.c_str(), uid, gid) != 0) {
818 LOG_E(BMS_TAG_INSTALLD, "fail to change %{public}s ownership, uid=%{public}d, errno:%{public}d",
819 filePath.c_str(), uid, errno);
820 return false;
821 }
822 LOG_D(BMS_TAG_INSTALLD, "change %{public}s file attribute successfully", filePath.c_str());
823 return true;
824 }
825
RenameFile(const std::string & oldPath,const std::string & newPath)826 bool InstalldOperator::RenameFile(const std::string &oldPath, const std::string &newPath)
827 {
828 if (oldPath.empty() || newPath.empty()) {
829 LOG_E(BMS_TAG_INSTALLD, "old path or new path is empty");
830 return false;
831 }
832 if (!DeleteDir(newPath)) {
833 return false;
834 }
835 return rename(oldPath.c_str(), newPath.c_str()) == 0;
836 }
837
IsValidPath(const std::string & rootDir,const std::string & path)838 bool InstalldOperator::IsValidPath(const std::string &rootDir, const std::string &path)
839 {
840 if (rootDir.find(ServiceConstants::PATH_SEPARATOR) != 0 ||
841 rootDir.rfind(ServiceConstants::PATH_SEPARATOR) != (rootDir.size() - 1) ||
842 rootDir.find("..") != std::string::npos) {
843 return false;
844 }
845 if (path.find("..") != std::string::npos) {
846 return false;
847 }
848 return path.compare(0, rootDir.size(), rootDir) == 0;
849 }
850
IsValidCodePath(const std::string & codePath)851 bool InstalldOperator::IsValidCodePath(const std::string &codePath)
852 {
853 if (codePath.empty()) {
854 LOG_E(BMS_TAG_INSTALLD, "code path is empty");
855 return false;
856 }
857 return IsValidPath(BUNDLE_BASE_CODE_DIR + ServiceConstants::PATH_SEPARATOR, codePath);
858 }
859
DeleteFiles(const std::string & dataPath)860 bool InstalldOperator::DeleteFiles(const std::string &dataPath)
861 {
862 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::DeleteFiles start");
863 std::string subPath;
864 bool ret = true;
865 DIR *dir = opendir(dataPath.c_str());
866 if (dir == nullptr) {
867 LOG_D(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", dataPath.c_str(), errno);
868 return true;
869 }
870 while (true) {
871 struct dirent *ptr = readdir(dir);
872 if (ptr == nullptr) {
873 LOG_D(BMS_TAG_INSTALLD, "fail to readdir errno:%{public}d", errno);
874 break;
875 }
876 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
877 continue;
878 }
879 subPath = OHOS::IncludeTrailingPathDelimiter(dataPath) + std::string(ptr->d_name);
880 if (ptr->d_type == DT_DIR) {
881 if (!OHOS::ForceRemoveDirectory(subPath)) {
882 ret = false;
883 LOG_W(BMS_TAG_INSTALLD, "ForceRemoveDirectory %{public}s failed, error: %{public}d",
884 dataPath.c_str(), errno);
885 }
886 continue;
887 }
888 if (access(subPath.c_str(), F_OK) == 0) {
889 ret = OHOS::RemoveFile(subPath);
890 if (!ret) {
891 LOG_W(BMS_TAG_INSTALLD, "RemoveFile %{public}s failed, error: %{public}d", dataPath.c_str(), errno);
892 }
893 continue;
894 }
895 // maybe lnk_file
896 ret = CheckAndDeleteLinkFile(subPath);
897 }
898 closedir(dir);
899 return ret;
900 }
901
DeleteFilesExceptDirs(const std::string & dataPath,const std::vector<std::string> & dirsToKeep)902 bool InstalldOperator::DeleteFilesExceptDirs(const std::string &dataPath, const std::vector<std::string> &dirsToKeep)
903 {
904 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::DeleteFilesExceptBundleDataDirs start");
905 std::string filePath;
906 DIR *dir = opendir(dataPath.c_str());
907 if (dir == nullptr) {
908 LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", dataPath.c_str(), errno);
909 return false;
910 }
911 bool ret = true;
912 while (true) {
913 struct dirent *ptr = readdir(dir);
914 if (ptr == nullptr) {
915 LOG_E(BMS_TAG_INSTALLD, "fail to readdir errno:%{public}d", errno);
916 break;
917 }
918 std::string dirName = ServiceConstants::PATH_SEPARATOR + std::string(ptr->d_name);
919 if (std::find(dirsToKeep.begin(), dirsToKeep.end(), dirName) != dirsToKeep.end() ||
920 std::string(BUNDLE_BACKUP_KEEP_DIR) == dirName) {
921 continue;
922 }
923 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
924 continue;
925 }
926 filePath = OHOS::IncludeTrailingPathDelimiter(dataPath) + std::string(ptr->d_name);
927 if (ptr->d_type == DT_DIR) {
928 ret = OHOS::ForceRemoveDirectory(filePath);
929 } else {
930 if (access(filePath.c_str(), F_OK) == 0) {
931 ret = OHOS::RemoveFile(filePath);
932 }
933 }
934 }
935 closedir(dir);
936 return ret;
937 }
938
MkOwnerDir(const std::string & path,bool isReadByOthers,const int uid,const int gid)939 bool InstalldOperator::MkOwnerDir(const std::string &path, bool isReadByOthers, const int uid, const int gid)
940 {
941 if (!MkRecursiveDir(path, isReadByOthers)) {
942 return false;
943 }
944 return ChangeFileAttr(path, uid, gid);
945 }
946
CheckPathIsSame(const std::string & path,int32_t mode,const int32_t uid,const int32_t gid,bool & isPathExist)947 bool InstalldOperator::CheckPathIsSame(const std::string &path, int32_t mode, const int32_t uid, const int32_t gid,
948 bool &isPathExist)
949 {
950 struct stat s;
951 if (stat(path.c_str(), &s) != 0) {
952 LOG_D(BMS_TAG_INSTALLD, "path :%{public}s is not exist, need create, errno:%{public}d", path.c_str(), errno);
953 isPathExist = false;
954 return false;
955 }
956 isPathExist = true;
957 if (((s.st_mode & MODE_BASE) == mode) && (static_cast<int32_t>(s.st_uid) == uid)
958 && (static_cast<int32_t>(s.st_gid) == gid)) {
959 LOG_D(BMS_TAG_INSTALLD, "path :%{public}s mode uid and gid are same, no need to create again", path.c_str());
960 return true;
961 }
962 LOG_NOFUNC_W(BMS_TAG_INSTALLD, "path:%{public}s exist, but mode uid or gid are not same, need to create again",
963 path.c_str());
964 return false;
965 }
966
MkOwnerDir(const std::string & path,int mode,const int uid,const int gid)967 bool InstalldOperator::MkOwnerDir(const std::string &path, int mode, const int uid, const int gid)
968 {
969 bool isPathExist = false;
970 if (CheckPathIsSame(path, mode, uid, gid, isPathExist)) {
971 return true;
972 }
973 if (isPathExist) {
974 if (chown(path.c_str(), INSTALLS_UID, INSTALLS_UID) != 0) {
975 LOG_W(BMS_TAG_INSTALLD, "fail to change %{public}s ownership, errno:%{public}d", path.c_str(), errno);
976 }
977 }
978 if (!OHOS::ForceCreateDirectory(path)) {
979 LOG_E(BMS_TAG_INSTALLD, "mkdir failed, errno: %{public}d", errno);
980 return false;
981 }
982 // only modify parent dir mode
983 if (chmod(path.c_str(), mode) != 0) {
984 LOG_E(BMS_TAG_INSTALLD, "chmod path:%{public}s mode:%{public}d failed, errno:%{public}d",
985 path.c_str(), mode, errno);
986 return false;
987 }
988 if (!ChangeDirOwnerRecursively(path, uid, gid)) {
989 LOG_E(BMS_TAG_INSTALLD, "ChangeDirOwnerRecursively failed, errno: %{public}d", errno);
990 return false;
991 }
992 return true;
993 }
994
GetDiskUsage(const std::string & dir,bool isRealPath)995 int64_t InstalldOperator::GetDiskUsage(const std::string &dir, bool isRealPath)
996 {
997 if (dir.empty() || (dir.size() > ServiceConstants::PATH_MAX_SIZE)) {
998 LOG_E(BMS_TAG_INSTALLD, "GetDiskUsage dir path invalid");
999 return 0;
1000 }
1001 std::string filePath = dir;
1002 if (!isRealPath && !PathToRealPath(dir, filePath)) {
1003 LOG_D(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", dir.c_str());
1004 return 0;
1005 }
1006 DIR *dirPtr = opendir(filePath.c_str());
1007 if (dirPtr == nullptr) {
1008 LOG_E(BMS_TAG_INSTALLD, "GetDiskUsage open file dir:%{public}s is failure, errno:%{public}d",
1009 filePath.c_str(), errno);
1010 return 0;
1011 }
1012 if (filePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1013 filePath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1014 }
1015 struct dirent *entry = nullptr;
1016 int64_t size = 0;
1017 while ((entry = readdir(dirPtr)) != nullptr) {
1018 if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) {
1019 continue;
1020 }
1021 std::string path = filePath + entry->d_name;
1022 if (entry->d_type == DT_DIR) {
1023 size += GetDiskUsage(path, true);
1024 continue;
1025 }
1026 struct stat fileInfo = {0};
1027 if (stat(path.c_str(), &fileInfo) != 0) {
1028 LOG_E(BMS_TAG_INSTALLD, "call stat error %{public}s, errno:%{public}d", path.c_str(), errno);
1029 fileInfo.st_size = 0;
1030 }
1031 size += fileInfo.st_size;
1032 }
1033 closedir(dirPtr);
1034 return size;
1035 }
1036
TraverseCacheDirectory(const std::string & currentPath,std::vector<std::string> & cacheDirs)1037 void InstalldOperator::TraverseCacheDirectory(const std::string ¤tPath, std::vector<std::string> &cacheDirs)
1038 {
1039 if (currentPath.empty() || (currentPath.size() > ServiceConstants::PATH_MAX_SIZE)) {
1040 LOG_E(BMS_TAG_INSTALLD, "TraverseCacheDirectory current path invaild");
1041 return;
1042 }
1043 std::string filePath = "";
1044 if (!PathToRealPath(currentPath, filePath)) {
1045 LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", currentPath.c_str());
1046 return;
1047 }
1048 DIR* dir = opendir(filePath.c_str());
1049 if (dir == nullptr) {
1050 LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", filePath.c_str(), errno);
1051 return;
1052 }
1053 if (filePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1054 filePath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1055 }
1056 struct dirent *ptr = nullptr;
1057 while ((ptr = readdir(dir)) != nullptr) {
1058 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
1059 continue;
1060 }
1061 if (ptr->d_type == DT_DIR && strcmp(ptr->d_name, CACHE_DIR) == 0) {
1062 std::string currentDir = filePath + std::string(ptr->d_name);
1063 cacheDirs.emplace_back(currentDir);
1064 continue;
1065 }
1066 if (ptr->d_type == DT_DIR) {
1067 std::string currentDir = filePath + std::string(ptr->d_name);
1068 TraverseCacheDirectory(currentDir, cacheDirs);
1069 }
1070 }
1071 closedir(dir);
1072 }
1073
GetDiskUsageFromPath(const std::vector<std::string> & path)1074 int64_t InstalldOperator::GetDiskUsageFromPath(const std::vector<std::string> &path)
1075 {
1076 int64_t fileSize = 0;
1077 for (auto &st : path) {
1078 fileSize += GetDiskUsage(st);
1079 LOG_D(BMS_TAG_INSTALLD, "GetBundleStats get cache size from: %{public}s", st.c_str());
1080 }
1081 return fileSize;
1082 }
1083
InitialiseQuotaMounts()1084 bool InstalldOperator::InitialiseQuotaMounts()
1085 {
1086 mQuotaReverseMounts.clear();
1087 std::ifstream mountsFile(PROC_MOUNTS_PATH);
1088
1089 if (!mountsFile.is_open()) {
1090 LOG_E(BMS_TAG_INSTALLD, "Failed to open mounts file errno:%{public}d", errno);
1091 return false;
1092 }
1093 std::string line;
1094
1095 while (std::getline(mountsFile, line)) {
1096 std::string device;
1097 std::string mountPoint;
1098 std::string fsType;
1099 std::istringstream lineStream(line);
1100
1101 if (!(lineStream >> device >> mountPoint >> fsType)) {
1102 LOG_W(BMS_TAG_INSTALLD, "Failed to parse mounts file line: %{public}s", line.c_str());
1103 continue;
1104 }
1105
1106 if (mountPoint == QUOTA_DEVICE_DATA_PATH) {
1107 struct dqblk dq;
1108 if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), 0, reinterpret_cast<char*>(&dq)) == 0) {
1109 mQuotaReverseMounts[mountPoint] = device;
1110 LOG_D(BMS_TAG_INSTALLD, "InitialiseQuotaMounts, mountPoint: %{public}s, device: %{public}s",
1111 mountPoint.c_str(), device.c_str());
1112 } else {
1113 LOG_W(BMS_TAG_INSTALLD, "InitialiseQuotaMounts, Failed to get quotactl, errno: %{public}d", errno);
1114 }
1115 }
1116 }
1117 return true;
1118 }
1119
GetDiskUsageFromQuota(const int32_t uid)1120 int64_t InstalldOperator::GetDiskUsageFromQuota(const int32_t uid)
1121 {
1122 std::lock_guard<std::recursive_mutex> lock(mMountsLock);
1123 std::string device = "";
1124 if (mQuotaReverseMounts.find(QUOTA_DEVICE_DATA_PATH) == mQuotaReverseMounts.end()) {
1125 if (!InitialiseQuotaMounts()) {
1126 LOG_E(BMS_TAG_INSTALLD, "Failed to initialise quota mounts");
1127 return 0;
1128 }
1129 }
1130 device = mQuotaReverseMounts[QUOTA_DEVICE_DATA_PATH];
1131 if (device.empty()) {
1132 LOG_W(BMS_TAG_INSTALLD, "skip when device no quotas present");
1133 return 0;
1134 }
1135 struct dqblk dq;
1136 if (quotactl(QCMD(Q_GETQUOTA, USRQUOTA), device.c_str(), uid, reinterpret_cast<char*>(&dq)) != 0) {
1137 LOG_E(BMS_TAG_INSTALLD, "Failed to get quotactl, errno: %{public}d", errno);
1138 return 0;
1139 }
1140 LOG_D(BMS_TAG_INSTALLD, "get disk usage from quota, uid: %{public}d, usage: %{public}llu",
1141 uid, static_cast<unsigned long long>(dq.dqb_curspace));
1142 return dq.dqb_curspace;
1143 }
1144
ScanDir(const std::string & dirPath,ScanMode scanMode,ResultMode resultMode,std::vector<std::string> & paths)1145 bool InstalldOperator::ScanDir(
1146 const std::string &dirPath, ScanMode scanMode, ResultMode resultMode, std::vector<std::string> &paths)
1147 {
1148 if (dirPath.empty() || (dirPath.size() > ServiceConstants::PATH_MAX_SIZE)) {
1149 LOG_E(BMS_TAG_INSTALLD, "Scan dir path invaild");
1150 return false;
1151 }
1152
1153 std::string realPath = "";
1154 if (!PathToRealPath(dirPath, realPath)) {
1155 LOG_E(BMS_TAG_INSTALLD, "file(%{public}s) is not real path", dirPath.c_str());
1156 return false;
1157 }
1158
1159 DIR* dir = opendir(realPath.c_str());
1160 if (dir == nullptr) {
1161 LOG_E(BMS_TAG_INSTALLD, "Scan open dir(%{public}s) fail, errno:%{public}d", realPath.c_str(), errno);
1162 return false;
1163 }
1164
1165 struct dirent *ptr = nullptr;
1166 while ((ptr = readdir(dir)) != nullptr) {
1167 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
1168 continue;
1169 }
1170
1171 std::string subName(ptr->d_name);
1172 if (scanMode == ScanMode::SUB_FILE_DIR) {
1173 if (ptr->d_type == DT_DIR) {
1174 paths.emplace_back(HandleScanResult(dirPath, subName, resultMode));
1175 }
1176
1177 continue;
1178 }
1179
1180 if (scanMode == ScanMode::SUB_FILE_FILE) {
1181 if (ptr->d_type == DT_REG) {
1182 paths.emplace_back(HandleScanResult(dirPath, subName, resultMode));
1183 }
1184
1185 continue;
1186 }
1187
1188 paths.emplace_back(HandleScanResult(dirPath, subName, resultMode));
1189 }
1190
1191 closedir(dir);
1192 return true;
1193 }
1194
ScanSoFiles(const std::string & newSoPath,const std::string & originPath,const std::string & currentPath,std::vector<std::string> & paths)1195 bool InstalldOperator::ScanSoFiles(const std::string &newSoPath, const std::string &originPath,
1196 const std::string ¤tPath, std::vector<std::string> &paths)
1197 {
1198 if (currentPath.empty() || (currentPath.size() > ServiceConstants::PATH_MAX_SIZE)) {
1199 LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles current path invalid");
1200 return false;
1201 }
1202 std::string filePath = "";
1203 if (!PathToRealPath(currentPath, filePath)) {
1204 LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", currentPath.c_str());
1205 return false;
1206 }
1207 DIR* dir = opendir(filePath.c_str());
1208 if (dir == nullptr) {
1209 LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles open dir(%{public}s) fail, errno:%{public}d", filePath.c_str(), errno);
1210 return false;
1211 }
1212 if (filePath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1213 filePath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1214 }
1215 struct dirent *ptr = nullptr;
1216 while ((ptr = readdir(dir)) != nullptr) {
1217 if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
1218 continue;
1219 }
1220 if (ptr->d_type == DT_DIR) {
1221 std::string currentDir = filePath + std::string(ptr->d_name);
1222 if (!ScanSoFiles(newSoPath, originPath, currentDir, paths)) {
1223 closedir(dir);
1224 return false;
1225 }
1226 }
1227 if (ptr->d_type == DT_REG) {
1228 std::string currentFile = filePath + std::string(ptr->d_name);
1229 std::string prefixPath = originPath;
1230 if (prefixPath.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1231 prefixPath.push_back(ServiceConstants::FILE_SEPARATOR_CHAR);
1232 }
1233 std::string relativePath = currentFile.substr(prefixPath.size());
1234 paths.emplace_back(relativePath);
1235 std::string subNewSoPath = GetPathDir(newSoPath + ServiceConstants::PATH_SEPARATOR + relativePath);
1236 if (!IsExistDir(subNewSoPath) && !MkRecursiveDir(subNewSoPath, true)) {
1237 LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles create subNewSoPath (%{public}s) failed", filePath.c_str());
1238 closedir(dir);
1239 return false;
1240 }
1241 }
1242 }
1243 closedir(dir);
1244 return true;
1245 }
1246
CopyFile(const std::string & sourceFile,const std::string & destinationFile)1247 bool InstalldOperator::CopyFile(
1248 const std::string &sourceFile, const std::string &destinationFile)
1249 {
1250 if (sourceFile.empty() || destinationFile.empty()) {
1251 LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to sourceFile or destinationFile is empty");
1252 return false;
1253 }
1254
1255 std::ifstream in(sourceFile);
1256 if (!in.is_open()) {
1257 LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to open sourceFile failed errno:%{public}d", errno);
1258 return false;
1259 }
1260
1261 std::ofstream out(destinationFile);
1262 if (!out.is_open()) {
1263 LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to open destinationFile failed errno:%{public}d", errno);
1264 in.close();
1265 return false;
1266 }
1267
1268 out << in.rdbuf();
1269 in.close();
1270 out.close();
1271 return true;
1272 }
1273
CopyFileFast(const std::string & sourcePath,const std::string & destPath)1274 bool InstalldOperator::CopyFileFast(const std::string &sourcePath, const std::string &destPath)
1275 {
1276 LOG_D(BMS_TAG_INSTALLD, "begin");
1277 return BundleUtil::CopyFileFast(sourcePath, destPath);
1278 }
1279
ExtractDiffFiles(const std::string & filePath,const std::string & targetPath,const std::string & cpuAbi)1280 bool InstalldOperator::ExtractDiffFiles(const std::string &filePath, const std::string &targetPath,
1281 const std::string &cpuAbi)
1282 {
1283 BundleExtractor extractor(filePath);
1284 if (!extractor.Init()) {
1285 return false;
1286 }
1287 std::vector<std::string> entryNames;
1288 if (!extractor.GetZipFileNames(entryNames)) {
1289 return false;
1290 }
1291 for (const auto &entryName : entryNames) {
1292 if (strcmp(entryName.c_str(), ".") == 0 ||
1293 strcmp(entryName.c_str(), "..") == 0) {
1294 continue;
1295 }
1296 if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
1297 continue;
1298 }
1299 // handle diff file
1300 if (IsDiffFiles(entryName, targetPath, cpuAbi)) {
1301 ExtractTargetFile(extractor, entryName, targetPath, cpuAbi);
1302 }
1303 }
1304 return true;
1305 }
1306
ProcessApplyDiffPatchPath(const std::string & oldSoPath,const std::string & diffFilePath,const std::string & newSoPath,std::vector<std::string> & oldSoFileNames,std::vector<std::string> & diffFileNames)1307 bool InstalldOperator::ProcessApplyDiffPatchPath(
1308 const std::string &oldSoPath, const std::string &diffFilePath,
1309 const std::string &newSoPath, std::vector<std::string> &oldSoFileNames, std::vector<std::string> &diffFileNames)
1310 {
1311 LOG_I(BMS_TAG_INSTALLD, "oldSoPath: %{public}s, diffFilePath: %{public}s, newSoPath: %{public}s",
1312 oldSoPath.c_str(), diffFilePath.c_str(), newSoPath.c_str());
1313 if (oldSoPath.empty() || diffFilePath.empty() || newSoPath.empty()) {
1314 return false;
1315 }
1316 if (!IsExistDir(oldSoPath) || !IsExistDir(diffFilePath)) {
1317 LOG_E(BMS_TAG_INSTALLD, "oldSoPath or diffFilePath not exist");
1318 return false;
1319 }
1320
1321 if (!ScanSoFiles(newSoPath, oldSoPath, oldSoPath, oldSoFileNames)) {
1322 LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles oldSoPath failed");
1323 return false;
1324 }
1325
1326 if (!ScanSoFiles(newSoPath, diffFilePath, diffFilePath, diffFileNames)) {
1327 LOG_E(BMS_TAG_INSTALLD, "ScanSoFiles diffFilePath failed");
1328 return false;
1329 }
1330
1331 if (oldSoFileNames.empty() || diffFileNames.empty()) {
1332 LOG_E(BMS_TAG_INSTALLD, "so or diff files empty");
1333 return false;
1334 }
1335
1336 if (!IsExistDir(newSoPath)) {
1337 LOG_D(BMS_TAG_INSTALLD, "ProcessApplyDiffPatchPath create newSoPath");
1338 if (!MkRecursiveDir(newSoPath, true)) {
1339 LOG_E(BMS_TAG_INSTALLD, "ProcessApplyDiffPatchPath create newSo dir (%{public}s) failed",
1340 newSoPath.c_str());
1341 return false;
1342 }
1343 }
1344 LOG_I(BMS_TAG_INSTALLD, "ProcessApplyDiffPatchPath end");
1345 return true;
1346 }
1347
ApplyDiffPatch(const std::string & oldSoPath,const std::string & diffFilePath,const std::string & newSoPath,int32_t uid)1348 bool InstalldOperator::ApplyDiffPatch(const std::string &oldSoPath, const std::string &diffFilePath,
1349 const std::string &newSoPath, int32_t uid)
1350 {
1351 LOG_I(BMS_TAG_INSTALLD, "ApplyDiffPatch no need to process");
1352 return true;
1353 }
1354
ObtainQuickFixFileDir(const std::string & dir,std::vector<std::string> & fileVec)1355 bool InstalldOperator::ObtainQuickFixFileDir(const std::string &dir, std::vector<std::string> &fileVec)
1356 {
1357 if (dir.empty()) {
1358 LOG_E(BMS_TAG_INSTALLD, "ObtainQuickFixFileDir dir path invaild");
1359 return false;
1360 }
1361
1362 std::string realPath = "";
1363 if (!PathToRealPath(dir, realPath)) {
1364 LOG_E(BMS_TAG_INSTALLD, "dir(%{public}s) is not real path", dir.c_str());
1365 return false;
1366 }
1367
1368 DIR* directory = opendir(realPath.c_str());
1369 if (directory == nullptr) {
1370 LOG_E(BMS_TAG_INSTALLD, "ObtainQuickFixFileDir open dir(%{public}s) fail, errno:%{public}d",
1371 realPath.c_str(), errno);
1372 return false;
1373 }
1374
1375 struct dirent *ptr = nullptr;
1376 bool isBundleCodeDir = dir.compare(Constants::BUNDLE_CODE_DIR) == 0;
1377 while ((ptr = readdir(directory)) != nullptr) {
1378 std::string currentName(ptr->d_name);
1379 if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
1380 continue;
1381 }
1382
1383 std::string curPath = dir + ServiceConstants::PATH_SEPARATOR + currentName;
1384 struct stat s;
1385 if (stat(curPath.c_str(), &s) == 0) {
1386 // directory
1387 if ((s.st_mode & S_IFDIR) && (isBundleCodeDir || BundleUtil::StartWith(currentName, HQF_DIR_PREFIX))) {
1388 ObtainQuickFixFileDir(curPath, fileVec);
1389 }
1390
1391 // file
1392 if ((s.st_mode & S_IFREG) &&
1393 (currentName.find(ServiceConstants::QUICK_FIX_FILE_SUFFIX) != std::string::npos)) {
1394 fileVec.emplace_back(dir);
1395 }
1396 }
1397 }
1398 closedir(directory);
1399 return true;
1400 }
1401
CopyFiles(const std::string & sourceDir,const std::string & destinationDir)1402 bool InstalldOperator::CopyFiles(const std::string &sourceDir, const std::string &destinationDir)
1403 {
1404 LOG_D(BMS_TAG_INSTALLD, "sourceDir is %{public}s, destinationDir is %{public}s",
1405 sourceDir.c_str(), destinationDir.c_str());
1406 if (sourceDir.empty() || destinationDir.empty()) {
1407 LOG_E(BMS_TAG_INSTALLD, "Copy file failed due to sourceDir or destinationDir is empty");
1408 return false;
1409 }
1410
1411 std::string realPath = "";
1412 if (!PathToRealPath(sourceDir, realPath)) {
1413 LOG_E(BMS_TAG_INSTALLD, "sourceDir(%{public}s) is not real path", sourceDir.c_str());
1414 return false;
1415 }
1416
1417 DIR* directory = opendir(realPath.c_str());
1418 if (directory == nullptr) {
1419 LOG_E(BMS_TAG_INSTALLD, "CopyFiles open dir(%{public}s) fail, errno:%{public}d", realPath.c_str(), errno);
1420 return false;
1421 }
1422
1423 struct dirent *ptr = nullptr;
1424 while ((ptr = readdir(directory)) != nullptr) {
1425 std::string currentName(ptr->d_name);
1426 if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
1427 continue;
1428 }
1429
1430 std::string curPath = sourceDir + ServiceConstants::PATH_SEPARATOR + currentName;
1431 struct stat s;
1432 if ((stat(curPath.c_str(), &s) == 0) && (s.st_mode & S_IFREG)) {
1433 std::string innerDesStr = destinationDir + ServiceConstants::PATH_SEPARATOR + currentName;
1434 if (CopyFile(curPath, innerDesStr)) {
1435 ChangeFileAttr(innerDesStr, Constants::FOUNDATION_UID, ServiceConstants::BMS_GID);
1436 }
1437 }
1438 }
1439 closedir(directory);
1440 return true;
1441 }
1442
GetNativeLibraryFileNames(const std::string & filePath,const std::string & cpuAbi,std::vector<std::string> & fileNames)1443 bool InstalldOperator::GetNativeLibraryFileNames(const std::string &filePath, const std::string &cpuAbi,
1444 std::vector<std::string> &fileNames)
1445 {
1446 BundleExtractor extractor(filePath);
1447 if (!extractor.Init()) {
1448 return false;
1449 }
1450 std::vector<std::string> entryNames;
1451 if (!extractor.GetZipFileNames(entryNames)) {
1452 return false;
1453 }
1454 std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
1455 for (const auto &entryName : entryNames) {
1456 if (StartsWith(entryName, prefix)) {
1457 fileNames.push_back(entryName.substr(prefix.length(), entryName.length()));
1458 }
1459 }
1460 LOG_D(BMS_TAG_INSTALLD, "InstalldOperator::GetNativeLibraryFileNames end");
1461 return true;
1462 }
1463
1464 #if defined(CODE_SIGNATURE_ENABLE)
PrepareEntryMap(const CodeSignatureParam & codeSignatureParam,const std::vector<std::string> & soEntryFiles,Security::CodeSign::EntryMap & entryMap)1465 bool InstalldOperator::PrepareEntryMap(const CodeSignatureParam &codeSignatureParam,
1466 const std::vector<std::string> &soEntryFiles, Security::CodeSign::EntryMap &entryMap)
1467 {
1468 if (codeSignatureParam.targetSoPath.empty()) {
1469 return false;
1470 }
1471 const std::string prefix = ServiceConstants::LIBS + codeSignatureParam.cpuAbi + ServiceConstants::PATH_SEPARATOR;
1472 for_each(soEntryFiles.begin(), soEntryFiles.end(),
1473 [&entryMap, &prefix, &codeSignatureParam](const auto &entry) {
1474 std::string fileName = entry.substr(prefix.length());
1475 std::string path = codeSignatureParam.targetSoPath;
1476 if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1477 path += ServiceConstants::FILE_SEPARATOR_CHAR;
1478 }
1479 entryMap.emplace(entry, path + fileName);
1480 LOG_D(BMS_TAG_INSTALLD, "VerifyCode the targetSoPath is %{public}s", (path + fileName).c_str());
1481 });
1482 return true;
1483 }
1484
PerformCodeSignatureCheck(const CodeSignatureParam & codeSignatureParam,const Security::CodeSign::EntryMap & entryMap)1485 ErrCode InstalldOperator::PerformCodeSignatureCheck(const CodeSignatureParam &codeSignatureParam,
1486 const Security::CodeSign::EntryMap &entryMap)
1487 {
1488 ErrCode ret = ERR_OK;
1489 if (codeSignatureParam.isCompileSdkOpenHarmony &&
1490 !Security::CodeSign::CodeSignUtils::IsSupportOHCodeSign()) {
1491 LOG_D(BMS_TAG_INSTALLD, "code signature is not supported");
1492 return ret;
1493 }
1494 if (codeSignatureParam.signatureFileDir.empty()) {
1495 std::shared_ptr<CodeSignHelper> codeSignHelper = std::make_shared<CodeSignHelper>();
1496 Security::CodeSign::FileType fileType = codeSignatureParam.isPreInstalledBundle ?
1497 FILE_ENTRY_ONLY : FILE_ENTRY_ADD;
1498 if (codeSignatureParam.isEnterpriseBundle) {
1499 LOG_D(BMS_TAG_INSTALLD, "Verify code signature for enterprise bundle");
1500 ret = codeSignHelper->EnforceCodeSignForAppWithOwnerId(codeSignatureParam.appIdentifier,
1501 codeSignatureParam.modulePath, entryMap, fileType);
1502 } else {
1503 LOG_D(BMS_TAG_INSTALLD, "Verify code signature for non-enterprise bundle");
1504 ret = codeSignHelper->EnforceCodeSignForApp(codeSignatureParam.modulePath, entryMap, fileType);
1505 }
1506 LOG_I(BMS_TAG_INSTALLD, "Verify code signature %{public}s", codeSignatureParam.modulePath.c_str());
1507 } else {
1508 ret = CodeSignUtils::EnforceCodeSignForApp(entryMap, codeSignatureParam.signatureFileDir);
1509 }
1510 return ret;
1511 }
1512 #endif
1513
VerifyCodeSignature(const CodeSignatureParam & codeSignatureParam)1514 bool InstalldOperator::VerifyCodeSignature(const CodeSignatureParam &codeSignatureParam)
1515 {
1516 BundleExtractor extractor(codeSignatureParam.modulePath);
1517 if (!extractor.Init()) {
1518 return false;
1519 }
1520
1521 std::vector<std::string> soEntryFiles;
1522 if (!ObtainNativeSoFile(extractor, codeSignatureParam.cpuAbi, soEntryFiles)) {
1523 return false;
1524 }
1525
1526 if (soEntryFiles.empty()) {
1527 LOG_D(BMS_TAG_INSTALLD, "soEntryFiles is empty");
1528 return true;
1529 }
1530
1531 #if defined(CODE_SIGNATURE_ENABLE)
1532 Security::CodeSign::EntryMap entryMap;
1533 if (!PrepareEntryMap(codeSignatureParam, soEntryFiles, entryMap)) {
1534 return false;
1535 }
1536
1537 ErrCode ret = PerformCodeSignatureCheck(codeSignatureParam, entryMap);
1538 if (ret != ERR_OK) {
1539 LOG_E(BMS_TAG_INSTALLD, "VerifyCode failed due to %{public}d", ret);
1540 return false;
1541 }
1542 #endif
1543 return true;
1544 }
1545
CheckEncryption(const CheckEncryptionParam & checkEncryptionParam,bool & isEncryption)1546 bool InstalldOperator::CheckEncryption(const CheckEncryptionParam &checkEncryptionParam, bool &isEncryption)
1547 {
1548 if (checkEncryptionParam.cpuAbi.empty() && checkEncryptionParam.targetSoPath.empty()) {
1549 return CheckHapEncryption(checkEncryptionParam, isEncryption);
1550 }
1551 const std::string cpuAbi = checkEncryptionParam.cpuAbi;
1552 const int32_t bundleId = checkEncryptionParam.bundleId;
1553 InstallBundleType installBundleType = checkEncryptionParam.installBundleType;
1554 const bool isCompressNativeLibrary = checkEncryptionParam.isCompressNativeLibrary;
1555 LOG_D(BMS_TAG_INSTALLD,
1556 "bundleId %{public}d, installBundleType %{public}d, isCompressNativeLibrary %{public}d, path %{public}s",
1557 bundleId, installBundleType, isCompressNativeLibrary, checkEncryptionParam.modulePath.c_str());
1558
1559 BundleExtractor extractor(checkEncryptionParam.modulePath);
1560 if (!extractor.Init()) {
1561 return false;
1562 }
1563
1564 std::vector<std::string> soEntryFiles;
1565 if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
1566 LOG_E(BMS_TAG_INSTALLD, "ObtainNativeSoFile failed");
1567 return false;
1568 }
1569
1570 if (soEntryFiles.empty()) {
1571 LOG_D(BMS_TAG_INSTALLD, "no so file in installation file %{public}s", checkEncryptionParam.modulePath.c_str());
1572 return true;
1573 }
1574
1575 #if defined(CODE_ENCRYPTION_ENABLE)
1576 const std::string targetSoPath = checkEncryptionParam.targetSoPath;
1577 std::unordered_map<std::string, std::string> entryMap;
1578 entryMap.emplace(ServiceConstants::CODE_SIGNATURE_HAP, checkEncryptionParam.modulePath);
1579 if (!targetSoPath.empty()) {
1580 const std::string prefix = ServiceConstants::LIBS + cpuAbi + ServiceConstants::PATH_SEPARATOR;
1581 std::for_each(soEntryFiles.begin(), soEntryFiles.end(), [&entryMap, &prefix, &targetSoPath](const auto &entry) {
1582 std::string fileName = entry.substr(prefix.length());
1583 std::string path = targetSoPath;
1584 if (path.back() != ServiceConstants::FILE_SEPARATOR_CHAR) {
1585 path += ServiceConstants::FILE_SEPARATOR_CHAR;
1586 }
1587 entryMap.emplace(entry, path + fileName);
1588 LOG_D(BMS_TAG_INSTALLD, "CheckEncryption the targetSoPath is %{public}s", (path + fileName).c_str());
1589 });
1590 }
1591 if (!EnforceEncryption(entryMap, bundleId, isEncryption, installBundleType, isCompressNativeLibrary)) {
1592 return false;
1593 }
1594 #endif
1595 return true;
1596 }
1597
CheckHapEncryption(const CheckEncryptionParam & checkEncryptionParam,bool & isEncryption)1598 bool InstalldOperator::CheckHapEncryption(const CheckEncryptionParam &checkEncryptionParam, bool &isEncryption)
1599 {
1600 const std::string hapPath = checkEncryptionParam.modulePath;
1601 const int32_t bundleId = checkEncryptionParam.bundleId;
1602 InstallBundleType installBundleType = checkEncryptionParam.installBundleType;
1603 const bool isCompressNativeLibrary = checkEncryptionParam.isCompressNativeLibrary;
1604 LOG_D(BMS_TAG_INSTALLD, "CheckHapEncryption the hapPath is %{public}s, installBundleType is %{public}d, "
1605 "bundleId is %{public}d, isCompressNativeLibrary is %{public}d", hapPath.c_str(),
1606 installBundleType, bundleId, isCompressNativeLibrary);
1607 #if defined(CODE_ENCRYPTION_ENABLE)
1608 std::unordered_map<std::string, std::string> entryMap;
1609 entryMap.emplace(ServiceConstants::CODE_SIGNATURE_HAP, hapPath);
1610 if (!EnforceEncryption(entryMap, bundleId, isEncryption, installBundleType, isCompressNativeLibrary)) {
1611 return false;
1612 }
1613 #endif
1614 return true;
1615 }
1616
ObtainNativeSoFile(const BundleExtractor & extractor,const std::string & cpuAbi,std::vector<std::string> & soEntryFiles)1617 bool InstalldOperator::ObtainNativeSoFile(const BundleExtractor &extractor, const std::string &cpuAbi,
1618 std::vector<std::string> &soEntryFiles)
1619 {
1620 std::vector<std::string> entryNames;
1621 if (!extractor.GetZipFileNames(entryNames)) {
1622 LOG_E(BMS_TAG_INSTALLD, "GetZipFileNames failed");
1623 return false;
1624 }
1625 if (entryNames.empty()) {
1626 LOG_E(BMS_TAG_INSTALLD, "entryNames is empty");
1627 return false;
1628 }
1629
1630 for (const auto &entryName : entryNames) {
1631 if (strcmp(entryName.c_str(), ".") == 0 ||
1632 strcmp(entryName.c_str(), "..") == 0) {
1633 continue;
1634 }
1635 if (entryName.back() == ServiceConstants::PATH_SEPARATOR[0]) {
1636 continue;
1637 }
1638 // save native so file entryName in the hap
1639 if (IsNativeSo(entryName, cpuAbi)) {
1640 soEntryFiles.emplace_back(entryName);
1641 continue;
1642 }
1643 }
1644
1645 if (soEntryFiles.empty()) {
1646 LOG_D(BMS_TAG_INSTALLD, "no so file in installation file");
1647 }
1648 return true;
1649 }
1650
MoveFiles(const std::string & srcDir,const std::string & desDir,bool isDesDirNeedCreated)1651 bool InstalldOperator::MoveFiles(const std::string &srcDir, const std::string &desDir, bool isDesDirNeedCreated)
1652 {
1653 LOG_D(BMS_TAG_INSTALLD, "srcDir is %{public}s, desDir is %{public}s", srcDir.c_str(), desDir.c_str());
1654 if (isDesDirNeedCreated && !MkRecursiveDir(desDir, true)) {
1655 LOG_E(BMS_TAG_INSTALLD, "create desDir failed");
1656 return false;
1657 }
1658
1659 if (srcDir.empty() || desDir.empty()) {
1660 LOG_E(BMS_TAG_INSTALLD, "move file failed due to srcDir or desDir is empty");
1661 return false;
1662 }
1663
1664 std::string realPath = "";
1665 if (!PathToRealPath(srcDir, realPath)) {
1666 LOG_E(BMS_TAG_INSTALLD, "srcDir(%{public}s) is not real path", srcDir.c_str());
1667 return false;
1668 }
1669
1670 std::string realDesDir = "";
1671 if (!PathToRealPath(desDir, realDesDir)) {
1672 LOG_E(BMS_TAG_INSTALLD, "desDir(%{public}s) is not real path", desDir.c_str());
1673 return false;
1674 }
1675
1676 DIR* directory = opendir(realPath.c_str());
1677 if (directory == nullptr) {
1678 LOG_E(BMS_TAG_INSTALLD, "MoveFiles open dir(%{public}s) fail, errno:%{public}d", realPath.c_str(), errno);
1679 return false;
1680 }
1681
1682 struct dirent *ptr = nullptr;
1683 while ((ptr = readdir(directory)) != nullptr) {
1684 std::string currentName(ptr->d_name);
1685 if (currentName.compare(".") == 0 || currentName.compare("..") == 0) {
1686 continue;
1687 }
1688
1689 std::string curPath = realPath + ServiceConstants::PATH_SEPARATOR + currentName;
1690 std::string innerDesStr = realDesDir + ServiceConstants::PATH_SEPARATOR + currentName;
1691 struct stat s;
1692 if (stat(curPath.c_str(), &s) != 0) {
1693 LOG_D(BMS_TAG_INSTALLD, "MoveFiles stat %{public}s failed, errno:%{public}d", curPath.c_str(), errno);
1694 continue;
1695 }
1696 if (!MoveFileOrDir(curPath, innerDesStr, s.st_mode)) {
1697 closedir(directory);
1698 return false;
1699 }
1700 }
1701 closedir(directory);
1702 return true;
1703 }
1704
MoveFileOrDir(const std::string & srcPath,const std::string & destPath,mode_t mode)1705 bool InstalldOperator::MoveFileOrDir(const std::string &srcPath, const std::string &destPath, mode_t mode)
1706 {
1707 if (mode & S_IFREG) {
1708 LOG_D(BMS_TAG_INSTALLD, "srcPath(%{public}s) is a file", srcPath.c_str());
1709 return MoveFile(srcPath, destPath);
1710 } else if (mode & S_IFDIR) {
1711 LOG_D(BMS_TAG_INSTALLD, "srcPath(%{public}s) is a dir", srcPath.c_str());
1712 return MoveFiles(srcPath, destPath, true);
1713 }
1714 return true;
1715 }
1716
MoveFile(const std::string & srcPath,const std::string & destPath)1717 bool InstalldOperator::MoveFile(const std::string &srcPath, const std::string &destPath)
1718 {
1719 LOG_D(BMS_TAG_INSTALLD, "srcPath is %{public}s, destPath is %{public}s", srcPath.c_str(), destPath.c_str());
1720 if (!RenameFile(srcPath, destPath)) {
1721 LOG_E(BMS_TAG_INSTALLD, "move file from srcPath(%{public}s) to destPath(%{public}s) failed", srcPath.c_str(),
1722 destPath.c_str());
1723 return false;
1724 }
1725 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1726 if (!OHOS::ChangeModeFile(destPath, mode)) {
1727 LOG_E(BMS_TAG_INSTALLD, "change mode failed");
1728 return false;
1729 }
1730 return true;
1731 }
1732
ExtractResourceFiles(const ExtractParam & extractParam,const BundleExtractor & extractor)1733 bool InstalldOperator::ExtractResourceFiles(const ExtractParam &extractParam, const BundleExtractor &extractor)
1734 {
1735 LOG_D(BMS_TAG_INSTALLD, "ExtractResourceFiles begin");
1736 std::string targetDir = extractParam.targetPath;
1737 if (!MkRecursiveDir(targetDir, true)) {
1738 LOG_E(BMS_TAG_INSTALLD, "create targetDir failed");
1739 return false;
1740 }
1741 std::vector<std::string> entryNames;
1742 if (!extractor.GetZipFileNames(entryNames)) {
1743 LOG_E(BMS_TAG_INSTALLD, "GetZipFileNames failed");
1744 return false;
1745 }
1746 for (const auto &entryName : entryNames) {
1747 if (StartsWith(entryName, ServiceConstants::LIBS)
1748 || StartsWith(entryName, ServiceConstants::AN)
1749 || StartsWith(entryName, AP_PATH)) {
1750 continue;
1751 }
1752 const std::string relativeDir = GetPathDir(entryName);
1753 if (!relativeDir.empty()) {
1754 if (!MkRecursiveDir(targetDir + relativeDir, true)) {
1755 LOG_E(BMS_TAG_INSTALLD, "MkRecursiveDir failed");
1756 return false;
1757 }
1758 }
1759 std::string filePath = targetDir + entryName;
1760 if (!extractor.ExtractFile(entryName, filePath)) {
1761 LOG_E(BMS_TAG_INSTALLD, "ExtractFile failed");
1762 continue;
1763 }
1764 mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
1765 if (!OHOS::ChangeModeFile(filePath, mode)) {
1766 LOG_E(BMS_TAG_INSTALLD, "change mode failed");
1767 return false;
1768 }
1769 }
1770 LOG_D(BMS_TAG_INSTALLD, "ExtractResourceFiles success");
1771 return true;
1772 }
1773
ExtractDriverSoFiles(const std::string & srcPath,const std::unordered_multimap<std::string,std::string> & dirMap)1774 bool InstalldOperator::ExtractDriverSoFiles(const std::string &srcPath,
1775 const std::unordered_multimap<std::string, std::string> &dirMap)
1776 {
1777 LOG_D(BMS_TAG_INSTALLD, "ExtractDriverSoFiles start with src(%{public}s)", srcPath.c_str());
1778 if (srcPath.empty() || dirMap.empty()) {
1779 LOG_E(BMS_TAG_INSTALLD, "ExtractDriverSoFiles parameters are invalid");
1780 return false;
1781 }
1782
1783 for (auto &[originalDir, destinedDir] : dirMap) {
1784 if ((originalDir.compare(".") == 0) || (originalDir.compare("..") == 0)) {
1785 LOG_E(BMS_TAG_INSTALLD, "the originalDir %{public}s is not existed in the hap", originalDir.c_str());
1786 return false;
1787 }
1788 if ((!BundleUtil::StartWith(originalDir, PREFIX_RESOURCE_PATH) &&
1789 !BundleUtil::StartWith(originalDir, PREFIX_LIBS_PATH)) ||
1790 !BundleUtil::StartWith(destinedDir, PREFIX_TARGET_PATH)) {
1791 LOG_E(BMS_TAG_INSTALLD, "the originalDir %{public}s and destined dir %{public}s are invalid",
1792 originalDir.c_str(), destinedDir.c_str());
1793 return false;
1794 }
1795 std::string fileName = originalDir;
1796 if (fileName.front() == ServiceConstants::PATH_SEPARATOR[0]) {
1797 fileName = fileName.substr(1);
1798 }
1799 int fileNamePos = 0;
1800 fileNamePos = fileName.find(ServiceConstants::PATH_SEPARATOR[0], STR_LIBS_LEN + 1);
1801 fileName.erase(0, fileNamePos);
1802 LOG_D(BMS_TAG_INSTALLD, "ExtractDriverSoFiles fileName is %{public}s", fileName.c_str());
1803 std::string systemServiceDir = ServiceConstants::SYSTEM_SERVICE_DIR;
1804 if (!CopyDriverSoFiles(srcPath + fileName, systemServiceDir + destinedDir)) {
1805 LOG_E(BMS_TAG_INSTALLD, "CopyDriverSoFiles failed");
1806 return false;
1807 }
1808 }
1809 LOG_D(BMS_TAG_INSTALLD, "ExtractDriverSoFiles end");
1810 return true;
1811 }
1812
CopyDriverSoFiles(const std::string & originalDir,const std::string & destinedDir)1813 bool InstalldOperator::CopyDriverSoFiles(const std::string &originalDir, const std::string &destinedDir)
1814 {
1815 LOG_D(BMS_TAG_INSTALLD, "CopyDriverSoFiles beign");
1816 auto pos = destinedDir.rfind(ServiceConstants::PATH_SEPARATOR);
1817 if ((pos == std::string::npos) || (pos == destinedDir.length() -1)) {
1818 LOG_E(BMS_TAG_INSTALLD, "destinedDir(%{public}s) is invalid path", destinedDir.c_str());
1819 return false;
1820 }
1821 std::string desDir = destinedDir.substr(0, pos);
1822 std::string realDesDir;
1823 if (!PathToRealPath(desDir, realDesDir)) {
1824 LOG_E(BMS_TAG_INSTALLD, "desDir(%{public}s) is not real path", desDir.c_str());
1825 return false;
1826 }
1827 std::string realDestinedDir = realDesDir + destinedDir.substr(pos);
1828 LOG_D(BMS_TAG_INSTALLD, "realDestinedDir is %{public}s", realDestinedDir.c_str());
1829 MoveFile(originalDir, realDestinedDir);
1830
1831 struct stat buf = {};
1832 if (stat(realDesDir.c_str(), &buf) != 0) {
1833 LOG_E(BMS_TAG_INSTALLD, "failed to obtain the stat status of realDesDir %{public}s, errno:%{public}d",
1834 realDesDir.c_str(), errno);
1835 return false;
1836 }
1837 ChangeFileAttr(realDestinedDir, buf.st_uid, buf.st_gid);
1838 mode_t mode = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH;
1839 if (!OHOS::ChangeModeFile(realDestinedDir, mode)) {
1840 LOG_E(BMS_TAG_INSTALLD, "ChangeModeFile %{public}s failed, errno: %{public}d", realDestinedDir.c_str(),
1841 errno);
1842 return false;
1843 }
1844 LOG_D(BMS_TAG_INSTALLD, "CopyDriverSoFiles end");
1845 return true;
1846 }
1847
1848 #if defined(CODE_ENCRYPTION_ENABLE)
ExtractSoFilesToTmpHapPath(const std::string & hapPath,const std::string & cpuAbi,const std::string & tmpSoPath,int32_t uid)1849 ErrCode InstalldOperator::ExtractSoFilesToTmpHapPath(const std::string &hapPath, const std::string &cpuAbi,
1850 const std::string &tmpSoPath, int32_t uid)
1851 {
1852 LOG_D(BMS_TAG_INSTALLD, "start to obtain decoded so files from hapPath %{public}s", hapPath.c_str());
1853 BundleExtractor extractor(hapPath);
1854 if (!extractor.Init()) {
1855 LOG_E(BMS_TAG_INSTALLD, "init bundle extractor failed");
1856 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1857 }
1858
1859 /* obtain the so list in the hap */
1860 std::vector<std::string> soEntryFiles;
1861 if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
1862 LOG_E(BMS_TAG_INSTALLD, "ExtractFiles obtain native so file entryName failed");
1863 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1864 }
1865
1866 std::string innerTmpSoPath = tmpSoPath;
1867 if (innerTmpSoPath.back() != ServiceConstants::PATH_SEPARATOR[0]) {
1868 innerTmpSoPath += ServiceConstants::PATH_SEPARATOR;
1869 }
1870
1871 /* create innerTmpSoPath */
1872 if (!IsExistDir(innerTmpSoPath)) {
1873 if (!MkRecursiveDir(innerTmpSoPath, true)) {
1874 LOG_E(BMS_TAG_INSTALLD, "create innerTmpSoPath %{public}s failed", innerTmpSoPath.c_str());
1875 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1876 }
1877 }
1878
1879 for (const auto &entry : soEntryFiles) {
1880 LOG_D(BMS_TAG_INSTALLD, "entryName is %{public}s", entry.c_str());
1881 auto pos = entry.rfind(ServiceConstants::PATH_SEPARATOR[0]);
1882 if (pos == std::string::npos) {
1883 LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1884 continue;
1885 }
1886 std::string soFileName = entry.substr(pos + 1);
1887 if (soFileName.empty()) {
1888 LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1889 continue;
1890 }
1891 LOG_D(BMS_TAG_INSTALLD, "so file is %{public}s", soFileName.c_str());
1892 uint32_t offset = 0;
1893 uint32_t length = 0;
1894 if (!extractor.GetFileInfo(entry, offset, length) || length == 0) {
1895 LOG_W(BMS_TAG_INSTALLD, "GetFileInfo failed or invalid so file");
1896 continue;
1897 }
1898 LOG_D(BMS_TAG_INSTALLD, "so file %{public}s has offset %{public}d and file size %{public}d",
1899 entry.c_str(), offset, length);
1900
1901 /* mmap so to ram and write so file to temp path */
1902 ErrCode res = ERR_OK;
1903 if ((res = DecryptSoFile(hapPath, innerTmpSoPath + soFileName, uid, length, offset)) != ERR_OK) {
1904 LOG_E(BMS_TAG_INSTALLD, "decrypt file failed, srcPath is %{public}s and destPath is %{public}s",
1905 hapPath.c_str(), (innerTmpSoPath + soFileName).c_str());
1906 return res;
1907 }
1908 }
1909
1910 return ERR_OK;
1911 }
1912
ExtractSoFilesToTmpSoPath(const std::string & hapPath,const std::string & realSoFilesPath,const std::string & cpuAbi,const std::string & tmpSoPath,int32_t uid)1913 ErrCode InstalldOperator::ExtractSoFilesToTmpSoPath(const std::string &hapPath, const std::string &realSoFilesPath,
1914 const std::string &cpuAbi, const std::string &tmpSoPath, int32_t uid)
1915 {
1916 LOG_D(BMS_TAG_INSTALLD, "start to obtain decoded so files from so path");
1917 if (realSoFilesPath.empty()) {
1918 LOG_E(BMS_TAG_INSTALLD, "real so file path is empty");
1919 return ERR_BUNDLEMANAGER_QUICK_FIX_INVALID_PATH;
1920 }
1921 BundleExtractor extractor(hapPath);
1922 if (!extractor.Init()) {
1923 LOG_E(BMS_TAG_INSTALLD, "init bundle extractor failed");
1924 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1925 }
1926 /* obtain the so list in the hap */
1927 std::vector<std::string> soEntryFiles;
1928 if (!ObtainNativeSoFile(extractor, cpuAbi, soEntryFiles)) {
1929 LOG_E(BMS_TAG_INSTALLD, "ExtractFiles obtain native so file entryName failed");
1930 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1931 }
1932
1933 std::string innerTmpSoPath = tmpSoPath;
1934 if (innerTmpSoPath.back() != ServiceConstants::PATH_SEPARATOR[0]) {
1935 innerTmpSoPath += ServiceConstants::PATH_SEPARATOR;
1936 }
1937 // create innerTmpSoPath
1938 if (!IsExistDir(innerTmpSoPath)) {
1939 if (!MkRecursiveDir(innerTmpSoPath, true)) {
1940 LOG_E(BMS_TAG_INSTALLD, "create innerTmpSoPath %{public}s failed", innerTmpSoPath.c_str());
1941 return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR;
1942 }
1943 }
1944
1945 for (const auto &entry : soEntryFiles) {
1946 auto pos = entry.rfind(ServiceConstants::PATH_SEPARATOR[0]);
1947 if (pos == std::string::npos) {
1948 LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1949 continue;
1950 }
1951 std::string soFileName = entry.substr(pos + 1);
1952 if (soFileName.empty()) {
1953 LOG_W(BMS_TAG_INSTALLD, "invalid so entry %{public}s", entry.c_str());
1954 continue;
1955 }
1956
1957 std::string soPath = realSoFilesPath + soFileName;
1958 LOG_D(BMS_TAG_INSTALLD, "real path of the so file %{public}s is %{public}s",
1959 soFileName.c_str(), soPath.c_str());
1960
1961 if (IsExistFile(soPath)) {
1962 /* mmap so file to ram and write to innerTmpSoPath */
1963 ErrCode res = ERR_OK;
1964 LOG_D(BMS_TAG_INSTALLD, "tmp so path is %{public}s", (innerTmpSoPath + soFileName).c_str());
1965 if ((res = DecryptSoFile(soPath, innerTmpSoPath + soFileName, uid, 0, 0)) != ERR_OK) {
1966 LOG_E(BMS_TAG_INSTALLD, "decrypt file failed, srcPath is %{public}s and destPath is %{public}s",
1967 soPath.c_str(), (innerTmpSoPath + soFileName).c_str());
1968 return res;
1969 }
1970 } else {
1971 LOG_W(BMS_TAG_INSTALLD, "so file %{public}s is not existed", soPath.c_str());
1972 }
1973 }
1974 return ERR_OK;
1975 }
1976
DecryptSoFile(const std::string & filePath,const std::string & tmpPath,int32_t uid,uint32_t fileSize,uint32_t offset)1977 ErrCode InstalldOperator::DecryptSoFile(const std::string &filePath, const std::string &tmpPath, int32_t uid,
1978 uint32_t fileSize, uint32_t offset)
1979 {
1980 LOG_D(BMS_TAG_INSTALLD, "src file is %{public}s, temp path is %{public}s, bundle uid is %{public}d",
1981 filePath.c_str(), tmpPath.c_str(), uid);
1982 ErrCode result = ERR_BUNDLEMANAGER_QUICK_FIX_DECRYPTO_SO_FAILED;
1983
1984 /* call CallIoctl */
1985 int32_t dev_fd = INVALID_FILE_DESCRIPTOR;
1986 auto ret = CallIoctl(CODE_DECRYPT_CMD_SET_KEY, CODE_DECRYPT_CMD_SET_ASSOCIATE_KEY, uid, dev_fd);
1987 if (ret != 0) {
1988 LOG_E(BMS_TAG_INSTALLD, "CallIoctl failed");
1989 return result;
1990 }
1991
1992 /* mmap hap or so file to ram */
1993 std::string newfilePath;
1994 if (!PathToRealPath(filePath, newfilePath)) {
1995 LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", filePath.c_str());
1996 return result;
1997 }
1998 auto fd = open(newfilePath.c_str(), O_RDONLY);
1999 if (fd < 0) {
2000 LOG_E(BMS_TAG_INSTALLD, "open hap failed errno:%{public}d", errno);
2001 close(dev_fd);
2002 return result;
2003 }
2004 struct stat st;
2005 if (fstat(fd, &st) == INVALID_RETURN_VALUE) {
2006 LOG_E(BMS_TAG_INSTALLD, "obtain hap file status faield errno:%{public}d", errno);
2007 close(dev_fd);
2008 close(fd);
2009 return result;
2010 }
2011 off_t innerFileSize = fileSize;
2012 if (fileSize == 0) {
2013 innerFileSize = st.st_size;
2014 }
2015 void *addr = mmap(NULL, innerFileSize, PROT_READ, MAP_PRIVATE, fd, offset);
2016 if (addr == MAP_FAILED) {
2017 LOG_E(BMS_TAG_INSTALLD, "mmap hap file status faield errno:%{public}d", errno);
2018 close(dev_fd);
2019 close(fd);
2020 return result;
2021 }
2022
2023 /* write hap file to the temp path */
2024 auto outPutFd = BundleUtil::CreateFileDescriptor(tmpPath, 0);
2025 if (outPutFd < 0) {
2026 LOG_E(BMS_TAG_INSTALLD, "create fd for tmp hap file failed");
2027 close(dev_fd);
2028 close(fd);
2029 munmap(addr, innerFileSize);
2030 return result;
2031 }
2032 if (write(outPutFd, addr, innerFileSize) != INVALID_RETURN_VALUE) {
2033 result = ERR_OK;
2034 LOG_D(BMS_TAG_INSTALLD, "write hap to temp path successfully");
2035 }
2036 close(dev_fd);
2037 close(fd);
2038 close(outPutFd);
2039 munmap(addr, innerFileSize);
2040 return result;
2041 }
2042
RemoveEncryptedKey(int32_t uid,const std::vector<std::string> & soList)2043 ErrCode InstalldOperator::RemoveEncryptedKey(int32_t uid, const std::vector<std::string> &soList)
2044 {
2045 if (uid == Constants::INVALID_UID) {
2046 LOG_D(BMS_TAG_INSTALLD, "invalid uid and no need to remove encrypted key");
2047 return ERR_OK;
2048 }
2049 if (soList.empty()) {
2050 LOG_D(BMS_TAG_INSTALLD, "no new so generated and no need to remove encrypted key");
2051 return ERR_OK;
2052 }
2053 ErrCode result = ERR_BUNDLEMANAGER_QUICK_FIX_DECRYPTO_SO_FAILED;
2054
2055 /* call CallIoctl */
2056 int32_t dev_fd = INVALID_FILE_DESCRIPTOR;
2057 auto ret = CallIoctl(CODE_DECRYPT_CMD_REMOVE_KEY, CODE_DECRYPT_CMD_REMOVE_KEY, uid, dev_fd);
2058 if (ret == 0) {
2059 LOG_D(BMS_TAG_INSTALLD, "ioctl successfully");
2060 result = ERR_OK;
2061 }
2062 close(dev_fd);
2063 return result;
2064 }
2065
CallIoctl(int32_t flag,int32_t associatedFlag,int32_t uid,int32_t & fd)2066 int32_t InstalldOperator::CallIoctl(int32_t flag, int32_t associatedFlag, int32_t uid, int32_t &fd)
2067 {
2068 int32_t installdUid = static_cast<int32_t>(getuid());
2069 int32_t bundleUid = uid;
2070 LOG_D(BMS_TAG_INSTALLD, "current process uid is %{public}d and bundle uid is %{public}d", installdUid, bundleUid);
2071
2072 /* open CODE_DECRYPT */
2073 std::string newCodeDecrypt;
2074 if (!PathToRealPath(CODE_DECRYPT, newCodeDecrypt)) {
2075 LOG_E(BMS_TAG_INSTALLD, "file is not real path, file path: %{public}s", CODE_DECRYPT.c_str());
2076 return INVALID_RETURN_VALUE;
2077 }
2078 fd = open(newCodeDecrypt.c_str(), O_RDONLY);
2079 if (fd < 0) {
2080 LOG_E(BMS_TAG_INSTALLD, "call open failed errno:%{public}d", errno);
2081 return INVALID_RETURN_VALUE;
2082 }
2083
2084 /* build ioctl args to set key or remove key*/
2085 struct code_decrypt_arg firstArg;
2086 firstArg.arg1_len = sizeof(bundleUid);
2087 firstArg.arg1 = reinterpret_cast<void *>(&bundleUid);
2088 auto ret = ioctl(fd, flag, &firstArg);
2089 if (ret != 0) {
2090 LOG_E(BMS_TAG_INSTALLD, "call ioctl failed errno:%{public}d", errno);
2091 close(fd);
2092 }
2093
2094 struct code_decrypt_arg secondArg;
2095 secondArg.arg1_len = sizeof(installdUid);
2096 secondArg.arg1 = reinterpret_cast<void *>(&installdUid);
2097 if (associatedFlag == CODE_DECRYPT_CMD_SET_ASSOCIATE_KEY) {
2098 secondArg.arg2_len = sizeof(bundleUid);
2099 secondArg.arg2 = reinterpret_cast<void *>(&bundleUid);
2100 }
2101 ret = ioctl(fd, associatedFlag, &secondArg);
2102 if (ret != 0) {
2103 LOG_E(BMS_TAG_INSTALLD, "call ioctl failed errno:%{public}d", errno);
2104 close(fd);
2105 }
2106 return ret;
2107 }
2108 #endif
2109
GenerateKeyIdAndSetPolicy(int32_t uid,const std::string & bundleName,const int32_t userId,std::string & keyId)2110 bool InstalldOperator::GenerateKeyIdAndSetPolicy(int32_t uid, const std::string &bundleName,
2111 const int32_t userId, std::string &keyId)
2112 {
2113 LOG_D(BMS_TAG_INSTALLD, "GenerateKeyId uid is %{public}d, bundleName is %{public}s, userId is %{public}d",
2114 uid, bundleName.c_str(), userId);
2115 auto ret = Security::AccessToken::El5FilekeyManagerKit::GenerateAppKey(
2116 static_cast<uint32_t>(uid), bundleName, keyId);
2117 if (ret == Security::AccessToken::EFM_ERR_KEYID_EXISTED) {
2118 LOG_I(BMS_TAG_INSTALLD, "key id is existed");
2119 } else if (ret != 0) {
2120 LOG_E(BMS_TAG_INSTALLD, "Call GenerateAppKey failed ret = %{public}d", ret);
2121 return false;
2122 }
2123 if (keyId.empty()) {
2124 LOG_E(BMS_TAG_INSTALLD, "keyId is empty");
2125 return false;
2126 }
2127 struct fscrypt_asdp_policy policy;
2128 policy.version = 0;
2129 policy.asdp_class = FORCE_PROTECT;
2130 // keyId length = KEY_ID_STEP * FSCRYPT_KEY_DESCRIPTOR_SIZE
2131 for (uint32_t i = 0; i < keyId.size(); i += KEY_ID_STEP) {
2132 if (i / KEY_ID_STEP >= FSCRYPT_KEY_DESCRIPTOR_SIZE) {
2133 break;
2134 }
2135 std::string byteString = keyId.substr(i, KEY_ID_STEP);
2136 char byte = (char)strtol(byteString.c_str(), NULL, 16);
2137 policy.app_key2_descriptor[i / KEY_ID_STEP] = byte;
2138 }
2139
2140 std::vector<std::string> dirs;
2141 dirs.emplace_back(ServiceConstants::SCREEN_LOCK_FILE_DATA_PATH + ServiceConstants::PATH_SEPARATOR +
2142 std::to_string(userId) + ServiceConstants::BASE + bundleName);
2143 dirs.emplace_back(ServiceConstants::SCREEN_LOCK_FILE_DATA_PATH + ServiceConstants::PATH_SEPARATOR +
2144 std::to_string(userId) + ServiceConstants::DATABASE + bundleName);
2145 for (const auto &dir : dirs) {
2146 auto fd = open(dir.c_str(), O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
2147 if (fd < 0) {
2148 LOG_E(BMS_TAG_INSTALLD, "open filePath failed");
2149 return false;
2150 }
2151 // call ioctl to set e policy
2152 auto result = ioctl(fd, HMFS_IOC_SET_ASDP_ENCRYPTION_POLICY, &policy);
2153 if (result != 0) {
2154 LOG_E(BMS_TAG_INSTALLD, "ioctl failed result:%{public}d %{public}d", result, errno);
2155 close(fd);
2156 return false;
2157 }
2158 close(fd);
2159 }
2160 LOG_I(BMS_TAG_INSTALLD, "GenerateKeyIdAndSetPolicy success for %{public}s", bundleName.c_str());
2161 return true;
2162 }
2163
DeleteKeyId(const std::string & bundleName,const int32_t userId)2164 bool InstalldOperator::DeleteKeyId(const std::string &bundleName, const int32_t userId)
2165 {
2166 LOG_D(BMS_TAG_INSTALLD, "DeleteKeyId bundleName is %{public}s", bundleName.c_str());
2167 auto ret = Security::AccessToken::El5FilekeyManagerKit::DeleteAppKey(bundleName, userId);
2168 if (ret != 0) {
2169 LOG_E(BMS_TAG_INSTALLD, "Call DeleteAppKey failed ret = %{public}d", ret);
2170 return false;
2171 }
2172 return true;
2173 }
2174
GetAtomicServiceBundleDataDir(const std::string & bundleName,const int32_t userId,std::vector<std::string> & allPathNames)2175 bool InstalldOperator::GetAtomicServiceBundleDataDir(const std::string &bundleName,
2176 const int32_t userId, std::vector<std::string> &allPathNames)
2177 {
2178 std::string baseDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[0] +
2179 ServiceConstants::PATH_SEPARATOR + std::to_string(userId) + ServiceConstants::BASE;
2180 DIR *dir = opendir(baseDir.c_str());
2181 if (dir == nullptr) {
2182 LOG_E(BMS_TAG_INSTALLD, "fail to opendir:%{public}s, errno:%{public}d", baseDir.c_str(), errno);
2183 return false;
2184 }
2185 struct dirent *ptr = nullptr;
2186 while ((ptr = readdir(dir)) != nullptr) {
2187 if (ptr->d_type == DT_DIR) {
2188 std::string pathName(ptr->d_name);
2189 if (pathName.find(ATOMIC_SERVICE_PATH) != 0) {
2190 continue;
2191 }
2192 auto pos = pathName.rfind(bundleName);
2193 if ((pos != std::string::npos) && (pos == (pathName.size() - bundleName.size()))) {
2194 allPathNames.emplace_back(pathName);
2195 }
2196 }
2197 }
2198 closedir(dir);
2199 return !allPathNames.empty();
2200 }
2201
2202 #if defined(CODE_ENCRYPTION_ENABLE)
2203 std::mutex InstalldOperator::encryptionMutex_;
2204 void *InstalldOperator::encryptionHandle_ = nullptr;
2205 EnforceMetadataProcessForApp InstalldOperator::enforceMetadataProcessForApp_ = nullptr;
2206
OpenEncryptionHandle()2207 bool InstalldOperator::OpenEncryptionHandle()
2208 {
2209 std::lock_guard<std::mutex> lock(encryptionMutex_);
2210 if (encryptionHandle_ != nullptr && enforceMetadataProcessForApp_ != nullptr) {
2211 LOG_NOFUNC_I(BMS_TAG_INSTALLD, "encrypt handle opened");
2212 return true;
2213 }
2214 LOG_NOFUNC_I(BMS_TAG_INSTALLD, "OpenEncryption start");
2215 encryptionHandle_ = dlopen(LIB64_CODE_CRYPTO_SO_PATH, RTLD_NOW | RTLD_GLOBAL);
2216 if (encryptionHandle_ == nullptr) {
2217 LOG_W(BMS_TAG_INSTALLD, "open encrypt lib64 failed %{public}s", dlerror());
2218 encryptionHandle_ = dlopen(LIB_CODE_CRYPTO_SO_PATH, RTLD_NOW | RTLD_GLOBAL);
2219 }
2220 if (encryptionHandle_ == nullptr) {
2221 LOG_E(BMS_TAG_INSTALLD, "open encrypt lib failed %{public}s", dlerror());
2222 return false;
2223 }
2224 enforceMetadataProcessForApp_ =
2225 reinterpret_cast<EnforceMetadataProcessForApp>(dlsym(encryptionHandle_, CODE_CRYPTO_FUNCTION_NAME));
2226 if (enforceMetadataProcessForApp_ == nullptr) {
2227 LOG_E(BMS_TAG_INSTALLD, "dlsym encrypt err:%{public}s", dlerror());
2228 dlclose(encryptionHandle_);
2229 encryptionHandle_ = nullptr;
2230 return false;
2231 }
2232 return true;
2233 }
2234
EnforceEncryption(std::unordered_map<std::string,std::string> & entryMap,int32_t bundleId,bool & isEncryption,InstallBundleType installBundleType,bool isCompressNativeLibrary)2235 bool InstalldOperator::EnforceEncryption(std::unordered_map<std::string, std::string> &entryMap, int32_t bundleId,
2236 bool &isEncryption, InstallBundleType installBundleType, bool isCompressNativeLibrary)
2237 {
2238 if (!OpenEncryptionHandle()) {
2239 return false;
2240 }
2241 ErrCode ret = enforceMetadataProcessForApp_(entryMap, bundleId,
2242 isEncryption, static_cast<int32_t>(installBundleType), isCompressNativeLibrary);
2243 if (ret != ERR_OK) {
2244 LOG_E(BMS_TAG_INSTALLD, "CheckEncryption failed due to %{public}d", ret);
2245 return false;
2246 }
2247 return true;
2248 }
2249 #endif
2250 } // namespace AppExecFwk
2251 } // namespace OHOS
2252