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