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