/* * Copyright (c) 2021-2024 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "base_bundle_installer.h" #include <fcntl.h> #include <sys/stat.h> #include <sstream> #include "account_helper.h" #ifdef BUNDLE_FRAMEWORK_FREE_INSTALL #include "aging/bundle_aging_mgr.h" #endif #include "aot/aot_handler.h" #include "app_control_constants.h" #include "app_mgr_client.h" #ifdef BUNDLE_FRAMEWORK_DEFAULT_APP #include "default_app_mgr.h" #endif #ifdef BUNDLE_FRAMEWORK_QUICK_FIX #include "quick_fix/app_quick_fix.h" #include "quick_fix/inner_app_quick_fix.h" #include "quick_fix/quick_fix_data_mgr.h" #include "quick_fix/quick_fix_switcher.h" #include "quick_fix/quick_fix_deleter.h" #endif #include "ability_manager_helper.h" #include "app_log_tag_wrapper.h" #include "app_provision_info_manager.h" #include "bms_extension_data_mgr.h" #include "bundle_clone_installer.h" #include "bundle_permission_mgr.h" #include "bundle_resource_helper.h" #include "datetime_ex.h" #include "driver_installer.h" #include "hitrace_meter.h" #include "installd_client.h" #include "parameter.h" #include "parameters.h" #include "perf_profile.h" #include "scope_guard.h" #include "utd_handler.h" #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION #include "bundle_overlay_data_manager.h" #include "bundle_overlay_install_checker.h" #endif #ifdef WEBVIEW_ENABLE #include "app_fwk_update_client.h" #endif #ifdef STORAGE_SERVICE_ENABLE #include "storage_manager_proxy.h" #endif #include "iservice_registry.h" #include "inner_bundle_clone_common.h" namespace OHOS { namespace AppExecFwk { using namespace OHOS::Security; namespace { constexpr const char* ARK_CACHE_PATH = "/data/local/ark-cache/"; constexpr const char* ARK_PROFILE_PATH = "/data/local/ark-profile/"; constexpr const char* COMPILE_SDK_TYPE_OPEN_HARMONY = "OpenHarmony"; constexpr const char* LOG = "log"; constexpr const char* HSP_VERSION_PREFIX = "v"; constexpr const char* PRE_INSTALL_HSP_PATH = "/shared_bundles/"; constexpr const char* APP_INSTALL_PATH = "/data/app/el1/bundle"; constexpr const char* APP_INSTALL_SANDBOX_PATH = "/data/bms_app_install/"; const int64_t FIVE_MB = 1024 * 1024 * 5; // 5MB constexpr const char* DEBUG_APP_IDENTIFIER = "DEBUG_LIB_ID"; constexpr const char* SKILL_URI_SCHEME_HTTPS = "https"; constexpr const char* PERMISSION_PROTECT_SCREEN_LOCK_DATA = "ohos.permission.PROTECT_SCREEN_LOCK_DATA"; #ifdef STORAGE_SERVICE_ENABLE #ifdef QUOTA_PARAM_SET_ENABLE constexpr const char* SYSTEM_PARAM_ATOMICSERVICE_DATASIZE_THRESHOLD = "persist.sys.bms.aging.policy.atomicservice.datasize.threshold"; const int32_t THRESHOLD_VAL_LEN = 20; #endif // QUOTA_PARAM_SET_ENABLE const int32_t STORAGE_MANAGER_MANAGER_ID = 5003; #endif // STORAGE_SERVICE_ENABLE const int32_t ATOMIC_SERVICE_DATASIZE_THRESHOLD_MB_PRESET = 200; const int32_t SINGLE_HSP_VERSION = 1; const int32_t USER_MODE = 0; const int32_t ROOT_MODE = 1; const char* BMS_KEY_SHELL_UID = "const.product.shell.uid"; const char* IS_ROOT_MODE_PARAM = "const.debuggable"; constexpr const char* BMS_ACTIVATION_LOCK = "persist.bms.activation-lock"; constexpr const char* BMS_TRUE = "true"; const int32_t BMS_ACTIVATION_LOCK_VAL_LEN = 20; const std::set<std::string> SINGLETON_WHITE_LIST = { "com.ohos.formrenderservice", "com.ohos.sceneboard", "com.ohos.callui", "com.ohos.mms", "com.ohos.FusionSearch" }; constexpr const char* DATA_EXTENSION_PATH = "/extension/"; const std::string INSTALL_SOURCE_PREINSTALL = "pre-installed"; const std::string INSTALL_SOURCE_UNKNOWN = "unknown"; const std::string ARK_WEB_BUNDLE_NAME_PARAM = "persist.arkwebcore.package_name"; const char* OLD_ARK_WEB_BUNDLE_NAME = "com.ohos.nweb"; const char* NEW_ARK_WEB_BUNDLE_NAME = "com.ohos.arkwebcore"; std::string GetHapPath(const InnerBundleInfo &info, const std::string &moduleName) { std::string fileSuffix = ServiceConstants::INSTALL_FILE_SUFFIX; auto moduleInfo = info.GetInnerModuleInfoByModuleName(moduleName); if (moduleInfo && moduleInfo->distro.moduleType == Profile::MODULE_TYPE_SHARED) { LOG_D(BMS_TAG_INSTALLER, "The module(%{public}s) is shared", moduleName.c_str()); fileSuffix = ServiceConstants::HSP_FILE_SUFFIX; } return info.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + moduleName + fileSuffix; } std::string GetHapPath(const InnerBundleInfo &info) { return GetHapPath(info, info.GetModuleName(info.GetCurrentModulePackage())); } std::string BuildTempNativeLibraryPath(const std::string &nativeLibraryPath) { auto position = nativeLibraryPath.find(ServiceConstants::PATH_SEPARATOR); if (position == std::string::npos) { return nativeLibraryPath; } auto prefixPath = nativeLibraryPath.substr(0, position); auto suffixPath = nativeLibraryPath.substr(position); return prefixPath + ServiceConstants::TMP_SUFFIX + suffixPath; } } // namespace BaseBundleInstaller::BaseBundleInstaller() : bundleInstallChecker_(std::make_unique<BundleInstallChecker>()) {} BaseBundleInstaller::~BaseBundleInstaller() { bundlePaths_.clear(); BundleUtil::DeleteTempDirs(toDeleteTempHapPath_); toDeleteTempHapPath_.clear(); signatureFileTmpMap_.clear(); } ErrCode BaseBundleInstaller::InstallBundle( const std::string &bundlePath, const InstallParam &installParam, const Constants::AppType appType) { std::vector<std::string> bundlePaths { bundlePath }; return InstallBundle(bundlePaths, installParam, appType); } void BaseBundleInstaller::SendStartInstallNotify(const InstallParam &installParam, const std::unordered_map<std::string, InnerBundleInfo> &infos) { if (!installParam.needSendEvent) { LOG_W(BMS_TAG_INSTALLER, "SendStartInstallNotify needSendEvent is false"); return; } if (bundleName_.empty()) { LOG_W(BMS_TAG_INSTALLER, "SendStartInstallNotify bundleName is empty"); return; } for (const auto &item : infos) { LOG_D(BMS_TAG_INSTALLER, "SendStartInstallNotify %{public}s %{public}s %{public}s %{public}s", bundleName_.c_str(), item.second.GetCurModuleName().c_str(), item.second.GetAppId().c_str(), item.second.GetAppIdentifier().c_str()); NotifyBundleEvents installRes = { .bundleName = bundleName_, .modulePackage = item.second.GetCurModuleName(), .type = NotifyType::START_INSTALL, .appId = item.second.GetAppId(), .appIdentifier = item.second.GetAppIdentifier() }; if (NotifyBundleStatus(installRes) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "notify status failed for start install"); } } } ErrCode BaseBundleInstaller::InstallBundle( const std::vector<std::string> &bundlePaths, const InstallParam &installParam, const Constants::AppType appType) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); LOG_I(BMS_TAG_INSTALLER, "begin to process bundle install"); PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount()); int32_t uid = Constants::INVALID_UID; ErrCode result = ProcessBundleInstall(bundlePaths, installParam, appType, uid); if (installParam.needSendEvent && dataMgr_ && !bundleName_.empty()) { NotifyBundleEvents installRes = { .bundleName = bundleName_, .modulePackage = moduleName_, .abilityName = mainAbility_, .resultCode = result, .type = GetNotifyType(), .uid = uid, .accessTokenId = accessTokenId_, .isModuleUpdate = isModuleUpdate_, .appDistributionType = appDistributionType_, .bundleType = static_cast<int32_t>(bundleType_), .atomicServiceModuleUpgrade = atomicServiceModuleUpgrade_ }; if (installParam.allUser) { AddBundleStatus(installRes); } else if (NotifyBundleStatus(installRes) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "notify status failed for installation"); } } if (result == ERR_OK) { OnSingletonChange(installParam.GetKillProcess()); } else { RestoreHaps(bundlePaths, installParam); } if (!bundlePaths.empty()) { SendBundleSystemEvent( bundleName_.empty() ? bundlePaths[0] : bundleName_, ((isAppExist_ && hasInstalledInUser_) ? BundleEventType::UPDATE : BundleEventType::INSTALL), installParam, sysEventInfo_.preBundleScene, result); } PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount()); LOG_D(BMS_TAG_INSTALLER, "finish to process bundle install"); return result; } ErrCode BaseBundleInstaller::InstallBundleByBundleName( const std::string &bundleName, const InstallParam &installParam) { LOG_I(BMS_TAG_INSTALLER, "begin to process bundle install by bundleName, which is %{public}s", bundleName.c_str()); PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount()); int32_t uid = Constants::INVALID_UID; ErrCode result = ProcessInstallBundleByBundleName(bundleName, installParam, uid); if (installParam.needSendEvent && dataMgr_ && !bundleName.empty()) { NotifyBundleEvents installRes = { .bundleName = bundleName, .resultCode = result, .type = NotifyType::INSTALL, .uid = uid, .accessTokenId = accessTokenId_, .appDistributionType = appDistributionType_, .bundleType = static_cast<int32_t>(bundleType_), .atomicServiceModuleUpgrade = atomicServiceModuleUpgrade_ }; if (installParam.concentrateSendEvent) { AddNotifyBundleEvents(installRes); } else if (NotifyBundleStatus(installRes) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "notify status failed for installation"); } } SendBundleSystemEvent( bundleName, BundleEventType::INSTALL, installParam, InstallScene::CREATE_USER, result); PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount()); LOG_I(BMS_TAG_INSTALLER, "finish install %{public}s resultCode: %{public}d", bundleName.c_str(), result); return result; } ErrCode BaseBundleInstaller::Recover( const std::string &bundleName, const InstallParam &installParam) { LOG_I(BMS_TAG_INSTALLER, "begin to process bundle recover by bundleName, which is %{public}s", bundleName.c_str()); PerfProfile::GetInstance().SetBundleInstallStartTime(GetTickCount()); int32_t userId = GetUserId(installParam.userId); if (IsAppInBlocklist(bundleName, userId)) { return ERR_APPEXECFWK_INSTALL_APP_IN_BLOCKLIST; } int32_t uid = Constants::INVALID_UID; ErrCode result = ProcessRecover(bundleName, installParam, uid); if (installParam.needSendEvent && dataMgr_) { NotifyBundleEvents installRes = { .bundleName = bundleName, .resultCode = result, .type = NotifyType::INSTALL, .uid = uid, .accessTokenId = accessTokenId_, .appDistributionType = appDistributionType_, .bundleType = static_cast<int32_t>(bundleType_) }; if (NotifyBundleStatus(installRes) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "notify status failed for installation"); } } auto recoverInstallParam = installParam; recoverInstallParam.isPreInstallApp = true; SendBundleSystemEvent( bundleName, BundleEventType::RECOVER, recoverInstallParam, sysEventInfo_.preBundleScene, result); PerfProfile::GetInstance().SetBundleInstallEndTime(GetTickCount()); LOG_D(BMS_TAG_INSTALLER, "finish to process %{public}s bundle recover", bundleName.c_str()); return result; } ErrCode BaseBundleInstaller::UninstallBundle(const std::string &bundleName, const InstallParam &installParam) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); LOG_I(BMS_TAG_INSTALLER, "begin to process %{public}s bundle uninstall", bundleName.c_str()); PerfProfile::GetInstance().SetBundleUninstallStartTime(GetTickCount()); // uninstall all sandbox app before UninstallAllSandboxApps(bundleName, installParam.userId); int32_t uid = Constants::INVALID_UID; bool isUninstalledFromBmsExtension = false; ErrCode result = ProcessBundleUninstall(bundleName, installParam, uid); if (result == ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL) { CheckBundleNameAndStratAbility(bundleName, appIdentifier_); } if ((result == ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE) && (UninstallBundleFromBmsExtension(bundleName) == ERR_OK)) { isUninstalledFromBmsExtension = true; result = ERR_OK; } if (result == ERR_OK) { UtdHandler::UninstallUtdAsync(bundleName, userId_); #ifdef BUNDLE_FRAMEWORK_DEFAULT_APP DefaultAppMgr::GetInstance().HandleUninstallBundle(userId_, bundleName); #endif } if (installParam.needSendEvent && dataMgr_) { NotifyBundleEvents installRes = { .bundleName = bundleName, .resultCode = result, .type = NotifyType::UNINSTALL_BUNDLE, .uid = uid, .accessTokenId = accessTokenId_, .isAgingUninstall = installParam.isAgingUninstall, .isBmsExtensionUninstalled = isUninstalledFromBmsExtension, .appId = uninstallBundleAppId_, .bundleType = static_cast<int32_t>(bundleType_) }; if (installParam.concentrateSendEvent) { AddNotifyBundleEvents(installRes); } else if (NotifyBundleStatus(installRes) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "notify status failed for installation"); } } SendBundleSystemEvent( bundleName, BundleEventType::UNINSTALL, installParam, sysEventInfo_.preBundleScene, result); PerfProfile::GetInstance().SetBundleUninstallEndTime(GetTickCount()); LOG_D(BMS_TAG_INSTALLER, "finish to process %{public}s bundle uninstall", bundleName.c_str()); return result; } ErrCode BaseBundleInstaller::CheckUninstallInnerBundleInfo(const InnerBundleInfo &info, const std::string &bundleName) { if (!info.IsRemovable()) { LOG_NOFUNC_E(BMS_TAG_INSTALLER, "uninstall system app"); return ERR_APPEXECFWK_UNINSTALL_SYSTEM_APP_ERROR; } if (!info.GetUninstallState()) { LOG_E(BMS_TAG_INSTALLER, "bundle : %{public}s can not be uninstalled, uninstallState : %{public}d", bundleName.c_str(), info.GetUninstallState()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL; } if (info.GetApplicationBundleType() != BundleType::SHARED) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle is not shared library"); return ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_NOT_EXIST; } return ERR_OK; } ErrCode BaseBundleInstaller::UninstallBundleByUninstallParam(const UninstallParam &uninstallParam) { LOG_NOFUNC_I(BMS_TAG_INSTALLER, "begin to process cross-app %{public}s uninstall", uninstallParam.bundleName.c_str()); const std::string &bundleName = uninstallParam.bundleName; int32_t versionCode = uninstallParam.versionCode; if (bundleName.empty()) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle name or module name empty"); return ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_NOT_EXIST; } if (!InitDataMgr()) { return ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR; } auto &mtx = dataMgr_->GetBundleMutex(bundleName); std::lock_guard lock {mtx}; InnerBundleInfo info; if (!dataMgr_->GetInnerBundleInfo(bundleName, info)) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle info missing"); return ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_NOT_EXIST; } ScopeGuard enableGuard([&] { dataMgr_->EnableBundle(bundleName); }); ErrCode ret = CheckUninstallInnerBundleInfo(info, bundleName); if (ret != ERR_OK) { LOG_NOFUNC_W(BMS_TAG_INSTALLER, "CheckUninstallInnerBundleInfo failed, errcode: %{public}d", ret); return ret; } if (dataMgr_->CheckHspVersionIsRelied(versionCode, info)) { LOG_E(BMS_TAG_INSTALLER, "uninstall shared library is relied"); return ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_RELIED; } // if uninstallParam do not contain versionCode, versionCode is ALL_VERSIONCODE std::vector<uint32_t> versionCodes = info.GetAllHspVersion(); if (versionCode != Constants::ALL_VERSIONCODE && std::find(versionCodes.begin(), versionCodes.end(), versionCode) == versionCodes.end()) { LOG_E(BMS_TAG_INSTALLER, "input versionCode is not exist"); return ERR_APPEXECFWK_UNINSTALL_SHARE_APP_LIBRARY_IS_NOT_EXIST; } std::string uninstallDir = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName; if ((versionCodes.size() > SINGLE_HSP_VERSION && versionCode == Constants::ALL_VERSIONCODE) || versionCodes.size() == SINGLE_HSP_VERSION) { return UninstallHspBundle(uninstallDir, info.GetBundleName()); } else { uninstallDir += ServiceConstants::PATH_SEPARATOR + HSP_VERSION_PREFIX + std::to_string(versionCode); return UninstallHspVersion(uninstallDir, versionCode, info); } } ErrCode BaseBundleInstaller::UninstallHspBundle(std::string &uninstallDir, const std::string &bundleName) { LOG_D(BMS_TAG_INSTALLER, "begin to process hsp bundle %{public}s uninstall", bundleName.c_str()); // remove bundle dir first, then delete data in bundle data manager ErrCode errCode; if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } // delete bundle bunlde in data if (!dataMgr_->UpdateBundleInstallState(bundleName, InstallState::UNINSTALL_START)) { LOG_E(BMS_TAG_INSTALLER, "uninstall start failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if ((errCode = InstalldClient::GetInstance()->RemoveDir(uninstallDir)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "delete dir %{public}s failed", uninstallDir.c_str()); return errCode; } if (!dataMgr_->UpdateBundleInstallState(bundleName, InstallState::UNINSTALL_SUCCESS)) { LOG_E(BMS_TAG_INSTALLER, "update uninstall success failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->DeleteAppProvisionInfo(bundleName)) { LOG_W(BMS_TAG_INSTALLER, "bundleName: %{public}s delete appProvisionInfo failed", bundleName.c_str()); } InstallParam installParam; versionCode_ = Constants::ALL_VERSIONCODE; userId_ = Constants::ALL_USERID; SendBundleSystemEvent( bundleName, BundleEventType::UNINSTALL, installParam, sysEventInfo_.preBundleScene, errCode); PerfProfile::GetInstance().SetBundleUninstallEndTime(GetTickCount()); /* remove sign profile from code signature for cross-app hsp */ RemoveProfileFromCodeSign(bundleName); return ERR_OK; } ErrCode BaseBundleInstaller::UninstallHspVersion(std::string &uninstallDir, int32_t versionCode, InnerBundleInfo &info) { LOG_D(BMS_TAG_INSTALLER, "begin to process hsp bundle %{public}s uninstall", info.GetBundleName().c_str()); // remove bundle dir first, then delete data in innerBundleInfo ErrCode errCode; if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!dataMgr_->UpdateBundleInstallState(info.GetBundleName(), InstallState::UNINSTALL_START)) { LOG_E(BMS_TAG_INSTALLER, "uninstall start failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if ((errCode = InstalldClient::GetInstance()->RemoveDir(uninstallDir)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "delete dir %{public}s failed", uninstallDir.c_str()); return errCode; } if (!dataMgr_->RemoveHspModuleByVersionCode(versionCode, info)) { LOG_E(BMS_TAG_INSTALLER, "remove hsp module by versionCode failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!dataMgr_->UpdateBundleInstallState(info.GetBundleName(), InstallState::INSTALL_SUCCESS)) { LOG_E(BMS_TAG_INSTALLER, "update install success failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } InstallParam installParam; versionCode_ = Constants::ALL_VERSIONCODE; userId_ = Constants::ALL_USERID; std::string bundleName = info.GetBundleName(); SendBundleSystemEvent( bundleName, BundleEventType::UNINSTALL, installParam, sysEventInfo_.preBundleScene, errCode); PerfProfile::GetInstance().SetBundleUninstallEndTime(GetTickCount()); return ERR_OK; } ErrCode BaseBundleInstaller::UninstallBundle( const std::string &bundleName, const std::string &modulePackage, const InstallParam &installParam) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); LOG_I(BMS_TAG_INSTALLER, "begin to process %{public}s module in %{public}s uninstall", modulePackage.c_str(), bundleName.c_str()); PerfProfile::GetInstance().SetBundleUninstallStartTime(GetTickCount()); // uninstall all sandbox app before UninstallAllSandboxApps(bundleName, installParam.userId); int32_t uid = Constants::INVALID_UID; bool isUninstalledFromBmsExtension = false; ErrCode result = ProcessBundleUninstall(bundleName, modulePackage, installParam, uid); if ((result == ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE) && (UninstallBundleFromBmsExtension(bundleName) == ERR_OK)) { isUninstalledFromBmsExtension = true; result = ERR_OK; } if (installParam.needSendEvent && dataMgr_) { NotifyBundleEvents installRes = { .bundleName = bundleName, .modulePackage = modulePackage, .resultCode = result, .type = NotifyType::UNINSTALL_MODULE, .uid = uid, .accessTokenId = accessTokenId_, .isAgingUninstall = installParam.isAgingUninstall, .isBmsExtensionUninstalled = isUninstalledFromBmsExtension, .appId = uninstallBundleAppId_, .bundleType = static_cast<int32_t>(bundleType_) }; if (NotifyBundleStatus(installRes) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "notify status failed for installation"); } } SendBundleSystemEvent( bundleName, BundleEventType::UNINSTALL, installParam, sysEventInfo_.preBundleScene, result); PerfProfile::GetInstance().SetBundleUninstallEndTime(GetTickCount()); LOG_D(BMS_TAG_INSTALLER, "finish uninstall %{public}s in %{public}s", modulePackage.c_str(), bundleName.c_str()); return result; } bool BaseBundleInstaller::UninstallAppControl(const std::string &appId, int32_t userId) { #ifdef BUNDLE_FRAMEWORK_APP_CONTROL std::vector<std::string> appIds; ErrCode ret = DelayedSingleton<AppControlManager>::GetInstance()->GetAppInstallControlRule( AppControlConstants::EDM_CALLING, AppControlConstants::APP_DISALLOWED_UNINSTALL, userId, appIds); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "GetAppInstallControlRule failed code:%{public}d", ret); return true; } if (std::find(appIds.begin(), appIds.end(), appId) == appIds.end()) { return true; } LOG_W(BMS_TAG_INSTALLER, "appId is not removable"); return false; #else LOG_W(BMS_TAG_INSTALLER, "app control is disable"); return true; #endif } ErrCode BaseBundleInstaller::InstallNormalAppControl( const std::string &installAppId, int32_t userId, bool isPreInstallApp) { LOG_D(BMS_TAG_INSTALLER, "InstallNormalAppControl start "); #ifdef BUNDLE_FRAMEWORK_APP_CONTROL if (isPreInstallApp) { LOG_D(BMS_TAG_INSTALLER, "the preInstalled app does not support app control feature"); return ERR_OK; } std::vector<std::string> allowedAppIds; ErrCode ret = DelayedSingleton<AppControlManager>::GetInstance()->GetAppInstallControlRule( AppControlConstants::EDM_CALLING, AppControlConstants::APP_ALLOWED_INSTALL, userId, allowedAppIds); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "GetAppInstallControlRule allowedInstall failed code:%{public}d", ret); return ret; } std::vector<std::string> disallowedAppIds; ret = DelayedSingleton<AppControlManager>::GetInstance()->GetAppInstallControlRule( AppControlConstants::EDM_CALLING, AppControlConstants::APP_DISALLOWED_INSTALL, userId, disallowedAppIds); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "GetAppInstallControlRule disallowedInstall failed code:%{public}d", ret); return ret; } // disallowed list and allowed list all empty. if (disallowedAppIds.empty() && allowedAppIds.empty()) { return ERR_OK; } // only allowed list empty. if (allowedAppIds.empty()) { if (std::find(disallowedAppIds.begin(), disallowedAppIds.end(), installAppId) != disallowedAppIds.end()) { LOG_E(BMS_TAG_INSTALLER, "disallowedAppIds:%{public}s is disallow install", installAppId.c_str()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_INSTALL; } return ERR_OK; } // only disallowed list empty. if (disallowedAppIds.empty()) { if (std::find(allowedAppIds.begin(), allowedAppIds.end(), installAppId) == allowedAppIds.end()) { LOG_E(BMS_TAG_INSTALLER, "allowedAppIds:%{public}s is disallow install", installAppId.c_str()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_INSTALL; } return ERR_OK; } // disallowed list and allowed list all not empty. if (std::find(allowedAppIds.begin(), allowedAppIds.end(), installAppId) == allowedAppIds.end()) { LOG_E(BMS_TAG_INSTALLER, "allowedAppIds:%{public}s is disallow install", installAppId.c_str()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_INSTALL; } else if (std::find(disallowedAppIds.begin(), disallowedAppIds.end(), installAppId) != disallowedAppIds.end()) { LOG_E(BMS_TAG_INSTALLER, "disallowedAppIds:%{public}s is disallow install", installAppId.c_str()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_INSTALL; } return ERR_OK; #else LOG_W(BMS_TAG_INSTALLER, "app control is disable"); return ERR_OK; #endif } void BaseBundleInstaller::UpdateInstallerState(const InstallerState state) { LOG_D(BMS_TAG_INSTALLER, "UpdateInstallerState in BaseBundleInstaller state %{public}d", state); SetInstallerState(state); } void BaseBundleInstaller::SaveOldRemovableInfo( InnerModuleInfo &newModuleInfo, InnerBundleInfo &oldInfo, bool existModule) { if (existModule) { // save old module useId isRemovable info to new module auto oldModule = oldInfo.FetchInnerModuleInfos().find(newModuleInfo.modulePackage); if (oldModule == oldInfo.FetchInnerModuleInfos().end()) { LOG_E(BMS_TAG_INSTALLER, "can not find module %{public}s in oldInfo", newModuleInfo.modulePackage.c_str()); return; } for (const auto &remove : oldModule->second.isRemovable) { auto result = newModuleInfo.isRemovable.try_emplace(remove.first, remove.second); if (!result.second) { LOG_E(BMS_TAG_INSTALLER, "%{public}s removable add %{public}s from old:%{public}d failed", newModuleInfo.modulePackage.c_str(), remove.first.c_str(), remove.second); } LOG_D(BMS_TAG_INSTALLER, "%{public}s removable add %{public}s from old:%{public}d", newModuleInfo.modulePackage.c_str(), remove.first.c_str(), remove.second); } } } void BaseBundleInstaller::CheckEnableRemovable(std::unordered_map<std::string, InnerBundleInfo> &newInfos, InnerBundleInfo &oldInfo, int32_t &userId, bool isFreeInstallFlag, bool isAppExist) { for (auto &item : newInfos) { std::map<std::string, InnerModuleInfo> &moduleInfo = item.second.FetchInnerModuleInfos(); bool hasInstalledInUser = oldInfo.HasInnerBundleUserInfo(userId); // now there are three cases for set haps isRemovable true: // 1. FREE_INSTALL flag // 2. bundle not exist in current user // 3. bundle exist, hap not exist // 4. hap exist not in current userId for (auto &iter : moduleInfo) { LOG_D(BMS_TAG_INSTALLER, "%{public}s, %{public}d, %{public}d, %{public}d", iter.second.modulePackage.c_str(), userId, isFreeInstallFlag, isAppExist); bool existModule = oldInfo.FindModule(iter.second.modulePackage); bool hasModuleInUser = item.second.IsUserExistModule(iter.second.moduleName, userId); LOG_D(BMS_TAG_INSTALLER, "%{public}d, (%{public}d), (%{public}d)", hasInstalledInUser, existModule, hasModuleInUser); if (isFreeInstallFlag && (!isAppExist || !hasInstalledInUser || !existModule || !hasModuleInUser)) { LOG_D(BMS_TAG_INSTALLER, "%{public}d, %{public}d (%{public}d)", hasInstalledInUser, isAppExist, existModule); item.second.SetModuleRemovable(iter.second.moduleName, true, userId); SaveOldRemovableInfo(iter.second, oldInfo, existModule); } } } } bool BaseBundleInstaller::CheckDuplicateProxyData(const InnerBundleInfo &newInfo, const InnerBundleInfo &oldInfo) { std::vector<ProxyData> proxyDatas; oldInfo.GetAllProxyDataInfos(proxyDatas); newInfo.GetAllProxyDataInfos(proxyDatas); return CheckDuplicateProxyData(proxyDatas); } bool BaseBundleInstaller::CheckDuplicateProxyData(const std::unordered_map<std::string, InnerBundleInfo> &newInfos) { std::vector<ProxyData> proxyDatas; for (const auto &innerBundleInfo : newInfos) { innerBundleInfo.second.GetAllProxyDataInfos(proxyDatas); } return CheckDuplicateProxyData(proxyDatas); } bool BaseBundleInstaller::CheckDuplicateProxyData(const std::vector<ProxyData> &proxyDatas) { std::set<std::string> uriSet; for (const auto &proxyData : proxyDatas) { if (!uriSet.insert(proxyData.uri).second) { LOG_E(BMS_TAG_INSTALLER, "uri %{public}s in proxyData is duplicated", proxyData.uri.c_str()); return false; } } return true; } ErrCode BaseBundleInstaller::InnerProcessBundleInstall(std::unordered_map<std::string, InnerBundleInfo> &newInfos, InnerBundleInfo &oldInfo, const InstallParam &installParam, int32_t &uid) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); LOG_I(BMS_TAG_INSTALLER, "bundleName %{public}s, userId is %{public}d", bundleName_.c_str(), userId_); LOG_I(BMS_TAG_INSTALLER, "flag:%{public}hhd, userId:%{public}d, isAppExist:%{public}d", installParam.installFlag, userId_, isAppExist_); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } KillRelatedProcessIfArkWeb(bundleName_, isAppExist_, installParam.isOTA); ErrCode result = ERR_OK; result = CheckAppService(newInfos.begin()->second, oldInfo, isAppExist_); CHECK_RESULT(result, "Check appService failed %{public}d"); if (installParam.needSavePreInstallInfo) { PreInstallBundleInfo preInstallBundleInfo; preInstallBundleInfo.SetBundleName(bundleName_); dataMgr_->GetPreInstallBundleInfo(bundleName_, preInstallBundleInfo); preInstallBundleInfo.SetAppType(newInfos.begin()->second.GetAppType()); preInstallBundleInfo.SetVersionCode(newInfos.begin()->second.GetVersionCode()); preInstallBundleInfo.SetIsUninstalled(false); for (const auto &item : newInfos) { preInstallBundleInfo.AddBundlePath(item.first); } #ifdef USE_PRE_BUNDLE_PROFILE preInstallBundleInfo.SetRemovable(installParam.removable); #else preInstallBundleInfo.SetRemovable(newInfos.begin()->second.IsRemovable()); #endif for (const auto &innerBundleInfo : newInfos) { auto applicationInfo = innerBundleInfo.second.GetBaseApplicationInfo(); innerBundleInfo.second.AdaptMainLauncherResourceInfo(applicationInfo); preInstallBundleInfo.SetLabelId(applicationInfo.labelResource.id); preInstallBundleInfo.SetIconId(applicationInfo.iconResource.id); preInstallBundleInfo.SetModuleName(applicationInfo.labelResource.moduleName); preInstallBundleInfo.SetSystemApp(applicationInfo.isSystemApp); auto bundleInfo = innerBundleInfo.second.GetBaseBundleInfo(); if (bundleInfo.isNewVersion) { preInstallBundleInfo.SetBundleType(applicationInfo.bundleType); } else if (!bundleInfo.hapModuleInfos.empty() && bundleInfo.hapModuleInfos[0].installationFree) { preInstallBundleInfo.SetBundleType(BundleType::ATOMIC_SERVICE); } if (!bundleInfo.hapModuleInfos.empty() && bundleInfo.hapModuleInfos[0].moduleType == ModuleType::ENTRY) { break; } } dataMgr_->SavePreInstallBundleInfo(bundleName_, preInstallBundleInfo); } result = CheckSingleton(newInfos.begin()->second, userId_); CHECK_RESULT(result, "Check singleton failed %{public}d"); bool isFreeInstallFlag = (installParam.installFlag == InstallFlag::FREE_INSTALL); CheckEnableRemovable(newInfos, oldInfo, userId_, isFreeInstallFlag, isAppExist_); // check MDM self update result = CheckMDMUpdateBundleForSelf(installParam, oldInfo, newInfos, isAppExist_); CHECK_RESULT(result, "update MDM app failed %{public}d"); GetExtensionDirsChange(newInfos, oldInfo); if (isAppExist_) { (void)InstalldClient::GetInstance()->RemoveDir(ARK_CACHE_PATH + oldInfo.GetBundleName()); SetAtomicServiceModuleUpgrade(oldInfo); if (oldInfo.GetApplicationBundleType() == BundleType::SHARED) { LOG_E(BMS_TAG_INSTALLER, "old bundle info is shared package"); return ERR_APPEXECFWK_INSTALL_COMPATIBLE_POLICY_NOT_SAME; } result = CheckInstallationFree(oldInfo, newInfos); CHECK_RESULT(result, "CheckInstallationFree failed %{public}d"); // to guarantee that the hap version can be compatible. result = CheckVersionCompatibility(oldInfo); CHECK_RESULT(result, "The app has been installed and update lower version bundle %{public}d"); // to check native file between oldInfo and newInfos. result = CheckNativeFileWithOldInfo(oldInfo, newInfos); CHECK_RESULT(result, "Check native so between oldInfo and newInfos failed %{public}d"); for (auto &info : newInfos) { std::string packageName = info.second.GetCurrentModulePackage(); if (oldInfo.FindModule(packageName)) { installedModules_[packageName] = true; } } hasInstalledInUser_ = oldInfo.HasInnerBundleUserInfo(userId_); if (!hasInstalledInUser_) { LOG_D(BMS_TAG_INSTALLER, "new userInfo with bundleName %{public}s and userId %{public}d", bundleName_.c_str(), userId_); InnerBundleUserInfo newInnerBundleUserInfo; newInnerBundleUserInfo.bundleUserInfo.userId = userId_; newInnerBundleUserInfo.bundleName = bundleName_; oldInfo.AddInnerBundleUserInfo(newInnerBundleUserInfo); ScopeGuard userGuard([&] { RemoveBundleUserData(oldInfo, false); }); Security::AccessToken::AccessTokenIDEx accessTokenIdEx; if (BundlePermissionMgr::InitHapToken(oldInfo, userId_, 0, accessTokenIdEx) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "bundleName:%{public}s InitHapToken failed", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED; } accessTokenId_ = accessTokenIdEx.tokenIdExStruct.tokenID; oldInfo.SetAccessTokenIdEx(accessTokenIdEx, userId_); result = CreateBundleUserData(oldInfo); CHECK_RESULT(result, "CreateBundleUserData failed %{public}d"); if (!isFeatureNeedUninstall_) { // extract ap file in old haps result = ExtractAllArkProfileFile(oldInfo, true); CHECK_RESULT(result, "ExtractAllArkProfileFile failed %{public}d"); } userGuard.Dismiss(); } ErrCode res = CleanShaderCache(bundleName_); if (res != ERR_OK) { LOG_NOFUNC_I(BMS_TAG_INSTALLER, "%{public}s clean shader fail %{public}d", bundleName_.c_str(), res); } } auto it = newInfos.begin(); if (!isAppExist_) { LOG_I(BMS_TAG_INSTALLER, "app is not exist"); if (!CheckInstallOnKeepData(bundleName_, installParam.isOTA, newInfos)) { LOG_E(BMS_TAG_INSTALLER, "check failed"); return ERR_APPEXECFWK_INSTALL_FAILED_INCONSISTENT_SIGNATURE; } InnerBundleInfo &newInfo = it->second; modulePath_ = it->first; InnerBundleUserInfo newInnerBundleUserInfo; newInnerBundleUserInfo.bundleUserInfo.userId = userId_; newInnerBundleUserInfo.bundleName = bundleName_; newInfo.AddInnerBundleUserInfo(newInnerBundleUserInfo); LOG_I(BMS_TAG_INSTALLER, "SetIsFreeInstallApp(%{public}d)", InstallFlag::FREE_INSTALL == installParam.installFlag); newInfo.SetIsFreeInstallApp(InstallFlag::FREE_INSTALL == installParam.installFlag); SetApplicationFlagsForPreinstallSource(newInfos, installParam); result = ProcessBundleInstallStatus(newInfo, uid); CHECK_RESULT(result, "ProcessBundleInstallStatus failed %{public}d"); it++; hasInstalledInUser_ = true; } InnerBundleInfo bundleInfo; bool isBundleExist = false; if (!GetInnerBundleInfo(bundleInfo, isBundleExist) || !isBundleExist) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } bool isOldSystemApp = bundleInfo.IsSystemApp(); InnerBundleUserInfo innerBundleUserInfo; if (!bundleInfo.GetInnerBundleUserInfo(userId_, innerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "oldInfo do not have user"); return ERR_APPEXECFWK_USER_NOT_EXIST; } CreateExtensionDataDir(bundleInfo); ScopeGuard userGuard([&] { if (!hasInstalledInUser_ || (!isAppExist_)) { RemoveBundleUserData(oldInfo, false); } }); // update haps for (; it != newInfos.end(); ++it) { // install entry module firstly LOG_D(BMS_TAG_INSTALLER, "update module %{public}s, entry module packageName is %{public}s", it->second.GetCurrentModulePackage().c_str(), entryModuleName_.c_str()); if ((result = InstallEntryMoudleFirst(newInfos, bundleInfo, innerBundleUserInfo, installParam)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "install entry module failed due to error %{public}d", result); break; } if (it->second.GetCurrentModulePackage().compare(entryModuleName_) == 0) { LOG_D(BMS_TAG_INSTALLER, "enrty has been installed"); continue; } modulePath_ = it->first; InnerBundleInfo &newInfo = it->second; newInfo.AddInnerBundleUserInfo(innerBundleUserInfo); bool isReplace = (installParam.installFlag == InstallFlag::REPLACE_EXISTING || installParam.installFlag == InstallFlag::FREE_INSTALL); // app exist, but module may not if ((result = ProcessBundleUpdateStatus( bundleInfo, newInfo, isReplace, installParam.GetKillProcess())) != ERR_OK) { break; } } if (result == ERR_OK) { result = InnerProcessUpdateHapToken(isOldSystemApp); CHECK_RESULT(result, "InnerProcessUpdateHapToken failed %{public}d"); } if (result == ERR_OK) { userGuard.Dismiss(); } uid = bundleInfo.GetUid(userId_); mainAbility_ = bundleInfo.GetMainAbility(); return result; } ErrCode BaseBundleInstaller::InnerProcessUpdateHapToken(const bool isOldSystemApp) { InnerBundleInfo newBundleInfo; bool isBundleExist = false; if (!GetInnerBundleInfo(newBundleInfo, isBundleExist) || !isBundleExist) { APP_LOGE("bundleName:%{public}s not exist", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } std::vector<std::string> moduleVec = newBundleInfo.GetModuleNameVec(); if (!isAppExist_ && (moduleVec.size() == 1)) { APP_LOGD("bundleName:%{public}s only has one module, no need update", bundleName_.c_str()); return ERR_OK; } if (!uninstallModuleVec_.empty()) { for (const auto &package : moduleVec) { if (std::find(uninstallModuleVec_.begin(), uninstallModuleVec_.end(), package) == uninstallModuleVec_.end()) { newBundleInfo.SetInnerModuleNeedDelete(package, true); } } } ErrCode result = UpdateHapToken(isOldSystemApp != newBundleInfo.IsSystemApp(), newBundleInfo); if (result != ERR_OK) { APP_LOGE("bundleName:%{public}s update hapToken failed, errCode:%{public}d", bundleName_.c_str(), result); return result; } if (isAppExist_ && isModuleUpdate_) { result = SetDirApl(newBundleInfo); if (result != ERR_OK) { APP_LOGE("bundleName:%{public}s setDirApl failed:%{public}d", bundleName_.c_str(), result); return result; } } return ERR_OK; } void BaseBundleInstaller::SetAtomicServiceModuleUpgrade(const InnerBundleInfo &oldInfo) { std::vector<std::string> moduleNames; oldInfo.GetModuleNames(moduleNames); for (const std::string &moduleName : moduleNames) { int32_t flag = static_cast<int32_t>(oldInfo.GetModuleUpgradeFlag(moduleName)); if (flag) { atomicServiceModuleUpgrade_ = flag; return; } } } bool BaseBundleInstaller::IsArkWeb(const std::string &bundleName) const { std::string arkWebName = OHOS::system::GetParameter(ARK_WEB_BUNDLE_NAME_PARAM, ""); if (bundleName != arkWebName) { LOG_D(BMS_TAG_INSTALLER, "Bundle(%{public}s) is not arkweb", bundleName.c_str()); return false; } LOG_I(BMS_TAG_INSTALLER, "%{public}s is arkweb", bundleName.c_str()); return true; } #ifdef WEBVIEW_ENABLE ErrCode BaseBundleInstaller::VerifyArkWebInstall(const std::string &bundleName) { if (!IsArkWeb(bundleName)) { return ERR_OK; } if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } InnerBundleInfo info; if (!dataMgr_->FetchInnerBundleInfo(bundleName, info)) { LOG_W(BMS_TAG_INSTALLER, "bundle info missing"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } std::string hapPath = info.GetModuleHapPath(info.GetEntryModuleName()); LOG_I(BMS_TAG_INSTALLER, "arkweb hapPath is %{public}s", hapPath.c_str()); if (NWeb::AppFwkUpdateClient::GetInstance().VerifyPackageInstall(bundleName, hapPath) != ERR_OK) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } return ERR_OK; } #endif void BaseBundleInstaller::KillRelatedProcessIfArkWeb(const std::string &bundleName, bool isAppExist, bool isOta) { if (!isAppExist || isOta || !IsArkWeb(bundleName)) { return; } std::string arkWebName = OHOS::system::GetParameter(ARK_WEB_BUNDLE_NAME_PARAM, ""); if (!arkWebName.empty()) { if (bundleName != arkWebName) { LOG_I(BMS_TAG_INSTALLER, "Bundle(%{public}s) is not arkweb", bundleName.c_str()); return; } } else { if (bundleName != NEW_ARK_WEB_BUNDLE_NAME && bundleName != OLD_ARK_WEB_BUNDLE_NAME) { LOG_I(BMS_TAG_INSTALLER, "Failed to get arkweb name and bundle name is %{public}s", bundleName.c_str()); return; } } auto appMgrClient = DelayedSingleton<AppMgrClient>::GetInstance(); if (appMgrClient == nullptr) { LOG_E(BMS_TAG_INSTALLER, "AppMgrClient is nullptr, kill ark web process failed"); return; } LOG_I(BMS_TAG_INSTALLER, "start to kill ark web related process"); appMgrClient->KillProcessDependedOnWeb(); } ErrCode BaseBundleInstaller::CheckAppService( const InnerBundleInfo &newInfo, const InnerBundleInfo &oldInfo, bool isAppExist) { if ((newInfo.GetApplicationBundleType() == BundleType::APP_SERVICE_FWK) && !isAppExist) { LOG_W(BMS_TAG_INSTALLER, "Not alloweded instal appService hap(%{public}s) due to the hsp does not exist", newInfo.GetBundleName().c_str()); return ERR_APP_SERVICE_FWK_INSTALL_TYPE_FAILED; } if (isAppExist) { isAppService_ = oldInfo.GetApplicationBundleType() == BundleType::APP_SERVICE_FWK; if (isAppService_ && oldInfo.GetApplicationBundleType() != newInfo.GetApplicationBundleType()) { LOG_W(BMS_TAG_INSTALLER, "Bundle(%{public}s) type is not same", newInfo.GetBundleName().c_str()); return ERR_APPEXECFWK_BUNDLE_TYPE_NOT_SAME; } } return ERR_OK; } ErrCode BaseBundleInstaller::CheckSingleton(const InnerBundleInfo &info, const int32_t userId) { if (isAppService_) { if (userId != Constants::DEFAULT_USERID) { LOG_W(BMS_TAG_INSTALLER, "appService(%{public}s) only install U0", info.GetBundleName().c_str()); return ERR_APPEXECFWK_INSTALL_ZERO_USER_WITH_NO_SINGLETON; } return ERR_OK; } // singleton app can only be installed in U0 and U0 can only install singleton app. bool isSingleton = info.IsSingleton(); if ((isSingleton && (userId != Constants::DEFAULT_USERID)) || (!isSingleton && (userId == Constants::DEFAULT_USERID))) { LOG_W(BMS_TAG_INSTALLER, "singleton(%{public}d) app(%{public}s) and user(%{public}d) are not matched", isSingleton, info.GetBundleName().c_str(), userId); return ERR_APPEXECFWK_INSTALL_ZERO_USER_WITH_NO_SINGLETON; } return ERR_OK; } ErrCode BaseBundleInstaller::ProcessBundleInstall(const std::vector<std::string> &inBundlePaths, const InstallParam &installParam, const Constants::AppType appType, int32_t &uid) { LOG_D(BMS_TAG_INSTALLER, "ProcessBundleInstall bundlePath install paths=%{private}s, hspPaths=%{private}s", GetJsonStrFromInfo(inBundlePaths).c_str(), GetJsonStrFromInfo(installParam.sharedBundleDirPaths).c_str()); if (!InitDataMgr()) { return ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR; } SharedBundleInstaller sharedBundleInstaller(installParam, appType); ErrCode result = sharedBundleInstaller.ParseFiles(); CHECK_RESULT(result, "parse cross-app shared bundles failed %{public}d"); if (inBundlePaths.empty() && sharedBundleInstaller.NeedToInstall()) { result = sharedBundleInstaller.Install(sysEventInfo_); bundleType_ = BundleType::SHARED; LOG_I(BMS_TAG_INSTALLER, "install cross-app shared bundles only, result : %{public}d", result); return result; } userId_ = GetUserId(installParam.userId); result = CheckUserId(userId_); CHECK_RESULT(result, "userId check failed %{public}d"); std::vector<std::string> parsedPaths; result = ParseHapPaths(installParam, inBundlePaths, parsedPaths); CHECK_RESULT(result, "hap file parse failed %{public}d"); std::vector<std::string> bundlePaths; // check hap paths result = BundleUtil::CheckFilePath(parsedPaths, bundlePaths); CHECK_RESULT(result, "hap file check failed %{public}d"); UpdateInstallerState(InstallerState::INSTALL_BUNDLE_CHECKED); // ---- 5% // copy the haps to the dir which cannot be accessed from caller result = CopyHapsToSecurityDir(installParam, bundlePaths); CHECK_RESULT(result, "copy file failed %{public}d"); // check syscap result = CheckSysCap(bundlePaths); CHECK_RESULT(result, "hap syscap check failed %{public}d"); UpdateInstallerState(InstallerState::INSTALL_SYSCAP_CHECKED); // ---- 10% // verify signature info for all haps std::vector<Security::Verify::HapVerifyResult> hapVerifyResults; result = CheckMultipleHapsSignInfo(bundlePaths, installParam, hapVerifyResults); CHECK_RESULT(result, "hap files check signature info failed %{public}d"); UpdateInstallerState(InstallerState::INSTALL_SIGNATURE_CHECKED); // ---- 15% result = CheckShellInstall(hapVerifyResults); CHECK_RESULT(result, "check shell install failed %{public}d"); // parse the bundle infos for all haps // key is bundlePath , value is innerBundleInfo std::unordered_map<std::string, InnerBundleInfo> newInfos; result = ParseHapFiles(bundlePaths, installParam, appType, hapVerifyResults, newInfos); CHECK_RESULT(result, "parse haps file failed %{public}d"); // washing machine judge if (!installParam.isPreInstallApp && !newInfos.empty()) { auto &firstBundleInfo = newInfos.begin()->second; if (!firstBundleInfo.IsSystemApp()) { bool isBundleExist = dataMgr_->IsBundleExist(firstBundleInfo.GetBundleName()); if (!isBundleExist && !VerifyActivationLock()) { result = ERR_APPEXECFWK_INSTALL_FAILED_CONTROLLED; } } } CHECK_RESULT(result, "check install verifyActivation failed %{public}d"); result = CheckShellCanInstallPreApp(newInfos); CHECK_RESULT(result, "check shell can install pre app failed %{public}d"); result = CheckInstallPermission(installParam, hapVerifyResults); CHECK_RESULT(result, "check install permission failed %{public}d"); result = CheckInstallCondition(hapVerifyResults, newInfos); CHECK_RESULT(result, "check install condition failed %{public}d"); // check the dependencies whether or not exists result = CheckDependency(newInfos, sharedBundleInstaller); CHECK_RESULT(result, "check dependency failed %{public}d"); // hapVerifyResults at here will not be empty verifyRes_ = hapVerifyResults[0]; Security::Verify::ProvisionInfo provisionInfo = verifyRes_.GetProvisionInfo(); if (provisionInfo.distributionType == Security::Verify::AppDistType::INTERNALTESTING) { result = DeliveryProfileToCodeSign(); CHECK_RESULT(result, "delivery profile failed %{public}d"); } UpdateInstallerState(InstallerState::INSTALL_PARSED); // ---- 20% userId_ = GetConfirmUserId(userId_, newInfos); if (!installParam.isPreInstallApp && IsAppInBlocklist((newInfos.begin()->second).GetBundleName(), userId_)) { result = ERR_APPEXECFWK_INSTALL_APP_IN_BLOCKLIST; CHECK_RESULT(result, "app is in block list %{public}d"); } // check hap hash param result = CheckHapHashParams(newInfos, installParam.hashParams); CHECK_RESULT(result, "check hap hash param failed %{public}d"); UpdateInstallerState(InstallerState::INSTALL_HAP_HASH_PARAM_CHECKED); // ---- 25% // check overlay installation result = CheckOverlayInstallation(newInfos, userId_); CHECK_RESULT(result, "overlay hap check failed %{public}d"); UpdateInstallerState(InstallerState::INSTALL_OVERLAY_CHECKED); // ---- 30% // check app props in the configuration file result = CheckAppLabelInfo(newInfos); CHECK_RESULT(result, "verisoncode or bundleName is different in all haps %{public}d"); UpdateInstallerState(InstallerState::INSTALL_VERSION_AND_BUNDLENAME_CHECKED); // ---- 35% // to send notify of start install application SendStartInstallNotify(installParam, newInfos); // check if bundle exists in extension result = CheckBundleInBmsExtension(bundleName_, userId_); CHECK_RESULT(result, "bundle is already existed in bms extension %{public}d"); // check native file result = CheckMultiNativeFile(newInfos); CHECK_RESULT(result, "native so is incompatible in all haps %{public}d"); UpdateInstallerState(InstallerState::INSTALL_NATIVE_SO_CHECKED); // ---- 40% // check proxy data result = CheckProxyDatas(newInfos); CHECK_RESULT(result, "proxy data check failed %{public}d"); UpdateInstallerState(InstallerState::INSTALL_PROXY_DATA_CHECKED); // ---- 45% // check hap is allow install by app control result = InstallNormalAppControl((newInfos.begin()->second).GetAppId(), userId_, installParam.isPreInstallApp); CHECK_RESULT(result, "install app control failed %{public}d"); auto &mtx = dataMgr_->GetBundleMutex(bundleName_); std::lock_guard lock {mtx}; // uninstall all sandbox app before UninstallAllSandboxApps(bundleName_); UpdateInstallerState(InstallerState::INSTALL_REMOVE_SANDBOX_APP); // ---- 50% // this state should always be set when return ScopeGuard stateGuard([&] { dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_SUCCESS); dataMgr_->EnableBundle(bundleName_); }); InnerBundleInfo oldInfo; verifyCodeParams_ = installParam.verifyCodeParams; pgoParams_ = installParam.pgoParams; copyHapToInstallPath_ = installParam.copyHapToInstallPath; ScopeGuard extensionDirGuard([&] { RemoveCreatedExtensionDirsForException(); }); // try to get the bundle info to decide use install or update. Always keep other exceptions below this line. if (!GetInnerBundleInfo(oldInfo, isAppExist_)) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } // when bundle update start, bms need set disposed rule to forbidden app running. SetDisposedRuleWhenBundleUpdateStart(newInfos, oldInfo, installParam.isPreInstallApp); // when bundle update end, bms need delete disposed rule. ScopeGuard deleteDisposedRuleGuard([&] { DeleteDisposedRuleWhenBundleUpdateEnd(oldInfo); }); result = InnerProcessBundleInstall(newInfos, oldInfo, installParam, uid); CHECK_RESULT_WITH_ROLLBACK(result, "internal processing failed with result %{public}d", newInfos, oldInfo); UpdateInstallerState(InstallerState::INSTALL_INFO_SAVED); // ---- 80% // copy hap or hsp to real install dir SaveHapPathToRecords(installParam.isPreInstallApp, newInfos); if (installParam.copyHapToInstallPath) { LOG_D(BMS_TAG_INSTALLER, "begin to copy hap to install path"); result = SaveHapToInstallPath(newInfos, oldInfo); CHECK_RESULT_WITH_ROLLBACK(result, "copy hap to install path failed %{public}d", newInfos, oldInfo); } else { ClearEncryptionStatus(); } // delete old native library path if (NeedDeleteOldNativeLib(newInfos, oldInfo)) { LOG_I(BMS_TAG_INSTALLER, "Delete old library"); DeleteOldNativeLibraryPath(); } // move so file to real installation dir result = MoveSoFileToRealInstallationDir(newInfos); CHECK_RESULT_WITH_ROLLBACK(result, "move so file to install path failed %{public}d", newInfos, oldInfo); #ifdef WEBVIEW_ENABLE result = VerifyArkWebInstall(bundleName_); CHECK_RESULT_WITH_ROLLBACK(result, "web verify failed %{public}d", newInfos, oldInfo); #endif // attention pls, rename operation shoule be almost the last operation to guarantee the rollback operation // when someone failure occurs in the installation flow result = RenameAllTempDir(newInfos); CHECK_RESULT_WITH_ROLLBACK(result, "rename temp dirs failed with result %{public}d", newInfos, oldInfo); UpdateInstallerState(InstallerState::INSTALL_RENAMED); // ---- 90% // delete low-version hap or hsp when higher-version hap or hsp installed if (!uninstallModuleVec_.empty()) { UninstallLowerVersionFeature(uninstallModuleVec_, installParam.GetKillProcess()); } // create data group dir ScopeGuard groupDirGuard([&] { DeleteGroupDirsForException(oldInfo); }); CreateDataGroupDirs(hapVerifyResults, oldInfo); // create Screen Lock File Protection Dir CreateScreenLockProtectionDir(); ScopeGuard ScreenLockFileProtectionDirGuard([&] { DeleteScreenLockProtectionDir(bundleName_); }); // install cross-app hsp which has rollback operation in sharedBundleInstaller when some one failure occurs result = sharedBundleInstaller.Install(sysEventInfo_); CHECK_RESULT_WITH_ROLLBACK(result, "install cross-app shared bundles failed %{public}d", newInfos, oldInfo); std::shared_ptr driverInstaller = std::make_shared<DriverInstaller>(); result = driverInstaller->CopyAllDriverFile(newInfos, oldInfo); CHECK_RESULT_WITH_ROLLBACK(result, "copy driver files failed due to error %{public}d", newInfos, oldInfo); UpdateInstallerState(InstallerState::INSTALL_SUCCESS); // ---- 100% LOG_D(BMS_TAG_INSTALLER, "finish ProcessBundleInstall bundlePath install touch off aging"); moduleName_ = GetModuleNames(newInfos); #ifdef BUNDLE_FRAMEWORK_FREE_INSTALL if (installParam.installFlag == InstallFlag::FREE_INSTALL) { DelayedSingleton<BundleMgrService>::GetInstance()->GetAgingMgr()->Start( BundleAgingMgr::AgingTriggertype::FREE_INSTALL); } #endif #ifdef BUNDLE_FRAMEWORK_QUICK_FIX if (needDeleteQuickFixInfo_) { LOG_D(BMS_TAG_INSTALLER, "module update, quick fix old patch need to delete:%{public}s", bundleName_.c_str()); if (!oldInfo.GetAppQuickFix().deployedAppqfInfo.hqfInfos.empty()) { LOG_D(BMS_TAG_INSTALLER, "quickFixInfo need disable, bundleName:%{public}s", bundleName_.c_str()); auto quickFixSwitcher = std::make_unique<QuickFixSwitcher>(bundleName_, false); quickFixSwitcher->Execute(); } auto quickFixDeleter = std::make_unique<QuickFixDeleter>(bundleName_); quickFixDeleter->Execute(); } #endif DeleteUninstallBundleInfo(bundleName_); GetInstallEventInfo(sysEventInfo_); AddAppProvisionInfo(bundleName_, hapVerifyResults[0].GetProvisionInfo(), installParam); ProcessOldNativeLibraryPath(newInfos, oldInfo.GetVersionCode(), oldInfo.GetNativeLibraryPath()); ProcessAOT(installParam.isOTA, newInfos); RemoveOldHapIfOTA(installParam, newInfos, oldInfo); UpdateAppInstallControlled(userId_); groupDirGuard.Dismiss(); extensionDirGuard.Dismiss(); ScreenLockFileProtectionDirGuard.Dismiss(); RemoveOldGroupDirs(oldInfo); RemoveOldExtensionDirs(); /* process quick fix when install new moudle */ ProcessQuickFixWhenInstallNewModule(installParam, newInfos); ProcessAddResourceInfo(installParam, bundleName_, userId_); VerifyDomain(); // check mark install finish result = MarkInstallFinish(); CHECK_RESULT_WITH_ROLLBACK(result, "mark install finish failed %{public}d", newInfos, oldInfo); UtdHandler::InstallUtdAsync(bundleName_, userId_); return result; } void BaseBundleInstaller::RollBack(const std::unordered_map<std::string, InnerBundleInfo> &newInfos, InnerBundleInfo &oldInfo) { LOG_D(BMS_TAG_INSTALLER, "start rollback due to install failed"); if (!isAppExist_) { if (!newInfos.empty() && newInfos.begin()->second.IsPreInstallApp() && !BundleUtil::CheckSystemFreeSize(APP_INSTALL_PATH, FIVE_MB)) { LOG_I(BMS_TAG_INSTALLER, "pre bundleName:%{public}s no need rollback due to no space", newInfos.begin()->second.GetBundleName().c_str()); return; } if (newInfos.begin()->second.GetApplicationBundleType() == BundleType::ATOMIC_SERVICE) { int32_t uid = newInfos.begin()->second.GetUid(userId_); if (uid != Constants::INVALID_UID) { LOG_I(BMS_TAG_INSTALLER, "uninstall atomic service need delete quota, bundleName:%{public}s", newInfos.begin()->second.GetBundleName().c_str()); std::string bundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::BASE + newInfos.begin()->second.GetBundleName(); PrepareBundleDirQuota(newInfos.begin()->second.GetBundleName(), uid, bundleDataDir, 0); } } RemoveBundleAndDataDir(newInfos.begin()->second, false); // delete accessTokenId if (BundlePermissionMgr::DeleteAccessTokenId(newInfos.begin()->second.GetAccessTokenId(userId_)) != AccessToken::AccessTokenKitRet::RET_SUCCESS) { LOG_E(BMS_TAG_INSTALLER, "delete accessToken failed"); } // remove driver file std::shared_ptr driverInstaller = std::make_shared<DriverInstaller>(); for (const auto &info : newInfos) { driverInstaller->RemoveDriverSoFile(info.second, "", false); } // remove profile from code signature RemoveProfileFromCodeSign(bundleName_); // remove innerBundleInfo RemoveInfo(bundleName_, ""); return; } InnerBundleInfo preInfo; bool isExist = false; if (!GetInnerBundleInfo(preInfo, isExist) || !isExist) { LOG_I(BMS_TAG_INSTALLER, "finish rollback due to install failed"); return; } for (const auto &info : newInfos) { RollBack(info.second, oldInfo); } // need delete definePermissions and requestPermissions UpdateHapToken(preInfo.GetAppType() != oldInfo.GetAppType(), oldInfo); LOG_D(BMS_TAG_INSTALLER, "finish rollback due to install failed"); } void BaseBundleInstaller::RollBack(const InnerBundleInfo &info, InnerBundleInfo &oldInfo) { // rollback hap installed std::shared_ptr driverInstaller = std::make_shared<DriverInstaller>(); auto modulePackage = info.GetCurrentModulePackage(); if (installedModules_[modulePackage]) { std::string createModulePath = info.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + modulePackage + ServiceConstants::TMP_SUFFIX; RemoveModuleDir(createModulePath); oldInfo.SetCurrentModulePackage(modulePackage); RollBackModuleInfo(bundleName_, oldInfo); // remove driver file of installed module driverInstaller->RemoveDriverSoFile(info, info.GetModuleName(modulePackage), true); } else { RemoveModuleDir(info.GetModuleDir(modulePackage)); // remove driver file driverInstaller->RemoveDriverSoFile(info, info.GetModuleName(modulePackage), false); // remove module info RemoveInfo(bundleName_, modulePackage); } } void BaseBundleInstaller::RemoveInfo(const std::string &bundleName, const std::string &packageName) { LOG_D(BMS_TAG_INSTALLER, "remove innerBundleInfo due to rollback"); if (!InitDataMgr()) { return; } if (packageName.empty()) { dataMgr_->UpdateBundleInstallState(bundleName, InstallState::UPDATING_FAIL); } else { InnerBundleInfo innerBundleInfo; bool isExist = false; if (!GetInnerBundleInfo(innerBundleInfo, isExist) || !isExist) { LOG_I(BMS_TAG_INSTALLER, "finish rollback due to install failed"); return; } dataMgr_->UpdateBundleInstallState(bundleName, InstallState::ROLL_BACK); dataMgr_->RemoveModuleInfo(bundleName, packageName, innerBundleInfo); } LOG_D(BMS_TAG_INSTALLER, "finish to remove innerBundleInfo due to rollback"); } void BaseBundleInstaller::RollBackModuleInfo(const std::string &bundleName, InnerBundleInfo &oldInfo) { LOG_D(BMS_TAG_INSTALLER, "rollBackMoudleInfo due to rollback"); if (!InitDataMgr()) { return; } InnerBundleInfo innerBundleInfo; bool isExist = false; if (!GetInnerBundleInfo(innerBundleInfo, isExist) || !isExist) { return; } dataMgr_->UpdateBundleInstallState(bundleName, InstallState::ROLL_BACK); dataMgr_->UpdateInnerBundleInfo(bundleName, oldInfo, innerBundleInfo); LOG_D(BMS_TAG_INSTALLER, "finsih rollBackMoudleInfo due to rollback"); } ErrCode BaseBundleInstaller::ProcessBundleUninstall( const std::string &bundleName, const InstallParam &installParam, int32_t &uid) { LOG_D(BMS_TAG_INSTALLER, "start to process %{public}s bundle uninstall", bundleName.c_str()); if (bundleName.empty()) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle name empty"); return ERR_APPEXECFWK_UNINSTALL_INVALID_NAME; } if (!InitDataMgr()) { return ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR; } userId_ = GetUserId(installParam.userId); if (userId_ == Constants::INVALID_USERID) { return ERR_APPEXECFWK_INSTALL_PARAM_ERROR; } if (!dataMgr_->HasUserId(userId_)) { LOG_E(BMS_TAG_INSTALLER, "The user %{public}d does not exist when uninstall", userId_); return ERR_APPEXECFWK_USER_NOT_EXIST; } auto &mtx = dataMgr_->GetBundleMutex(bundleName); std::lock_guard lock {mtx}; InnerBundleInfo oldInfo; ScopeGuard enableGuard([&] { dataMgr_->EnableBundle(bundleName); }); if (!dataMgr_->FetchInnerBundleInfo(bundleName, oldInfo)) { LOG_W(BMS_TAG_INSTALLER, "uninstall bundle info missing"); return ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE; } if (installParam.GetIsUninstallAndRecover()) { PreInstallBundleInfo preInstallBundleInfo; if (!dataMgr_->GetPreInstallBundleInfo(bundleName, preInstallBundleInfo)) { LOG_E(BMS_TAG_INSTALLER, "UninstallAndRecover %{public}s is not pre-install app", bundleName.c_str()); return ERR_APPEXECFWK_UNINSTALL_AND_RECOVER_NOT_PREINSTALLED_BUNDLE; } } bundleType_ = oldInfo.GetApplicationBundleType(); uninstallBundleAppId_ = oldInfo.GetAppId(); versionCode_ = oldInfo.GetVersionCode(); appIdentifier_ = oldInfo.GetAppIdentifier(); if (oldInfo.GetApplicationBundleType() == BundleType::SHARED) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle is shared library"); return ERR_APPEXECFWK_UNINSTALL_BUNDLE_IS_SHARED_LIBRARY; } UninstallBundleInfo uninstallBundleInfo; GetUninstallBundleInfo(installParam.isKeepData, userId_, oldInfo, uninstallBundleInfo); InnerBundleUserInfo curInnerBundleUserInfo; if (!oldInfo.GetInnerBundleUserInfo(userId_, curInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "bundle(%{public}s) get user(%{public}d) failed when uninstall", oldInfo.GetBundleName().c_str(), userId_); return ERR_APPEXECFWK_USER_NOT_INSTALL_HAP; } uid = curInnerBundleUserInfo.uid; if (!installParam.GetForceExecuted() && !oldInfo.IsRemovable() && installParam.GetKillProcess() && !installParam.GetIsUninstallAndRecover()) { LOG_E(BMS_TAG_INSTALLER, "uninstall system app"); return ERR_APPEXECFWK_UNINSTALL_SYSTEM_APP_ERROR; } if (!installParam.GetForceExecuted() && !oldInfo.GetUninstallState() && installParam.GetKillProcess() && !installParam.GetIsUninstallAndRecover()) { LOG_E(BMS_TAG_INSTALLER, "bundle : %{public}s can not be uninstalled, uninstallState : %{public}d", bundleName.c_str(), oldInfo.GetUninstallState()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL; } if (!UninstallAppControl(oldInfo.GetAppId(), userId_)) { LOG_E(BMS_TAG_INSTALLER, "bundleName: %{public}s is not allow uninstall", bundleName.c_str()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL; } if (!CheckWhetherCanBeUninstalled(bundleName)) { return ERR_APPEXECFWK_UNINSTALL_CONTROLLED; } // reboot scan case will not kill the bundle if (installParam.GetKillProcess()) { // kill the bundle process during uninstall. if (!AbilityManagerHelper::UninstallApplicationProcesses(oldInfo.GetApplicationName(), uid)) { LOG_E(BMS_TAG_INSTALLER, "can not kill process, uid : %{public}d", uid); return ERR_APPEXECFWK_UNINSTALL_KILLING_APP_ERROR; } } std::shared_ptr<BundleCloneInstaller> cloneInstaller = std::make_shared<BundleCloneInstaller>(); cloneInstaller->UninstallAllCloneApps(bundleName, installParam.userId); auto res = RemoveDataGroupDirs(oldInfo.GetBundleName(), userId_, installParam.isKeepData); if (res != ERR_OK) { APP_LOGW("remove group dir failed for %{public}s", oldInfo.GetBundleName().c_str()); } DeleteEncryptionKeyId(oldInfo); if (oldInfo.GetInnerBundleUserInfos().size() > 1) { LOG_D(BMS_TAG_INSTALLER, "only delete userinfo %{public}d", userId_); auto res = RemoveBundleUserData(oldInfo, installParam.isKeepData, !installParam.isRemoveUser); if (res != ERR_OK) { return res; } SaveUninstallBundleInfo(bundleName, installParam.isKeepData, uninstallBundleInfo); return ERR_OK; } dataMgr_->DisableBundle(bundleName); if (!dataMgr_->UpdateBundleInstallState(bundleName, InstallState::UNINSTALL_START)) { LOG_E(BMS_TAG_INSTALLER, "uninstall already start"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } std::string packageName; oldInfo.SetInstallMark(bundleName, packageName, InstallExceptionStatus::UNINSTALL_BUNDLE_START); if (!dataMgr_->SaveInnerBundleInfo(oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "save install mark failed"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } ErrCode ret = ProcessBundleUnInstallNative(oldInfo, userId_, bundleName); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove nativeBundle failed"); return ret; } ErrCode result = RemoveBundle(oldInfo, installParam.isKeepData, !installParam.isRemoveUser); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove whole bundle failed"); return result; } result = DeleteOldArkNativeFile(oldInfo); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "delete old arkNativeFile failed"); return result; } result = DeleteArkProfile(bundleName, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to removeArkProfile, error is %{public}d", result); return result; } result = DeleteShaderCache(bundleName); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to DeleteShaderCache, error is %{public}d", result); return result; } if ((result = CleanAsanDirectory(oldInfo)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove asan log path, error is %{public}d", result); return result; } enableGuard.Dismiss(); #ifdef BUNDLE_FRAMEWORK_QUICK_FIX std::shared_ptr<QuickFixDataMgr> quickFixDataMgr = DelayedSingleton<QuickFixDataMgr>::GetInstance(); if (quickFixDataMgr != nullptr) { LOG_D(BMS_TAG_INSTALLER, "DeleteInnerAppQuickFix when bundleName :%{public}s uninstall", bundleName.c_str()); quickFixDataMgr->DeleteInnerAppQuickFix(bundleName); } #endif if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->DeleteAppProvisionInfo(bundleName)) { LOG_W(BMS_TAG_INSTALLER, "bundleName: %{public}s delete appProvisionInfo failed", bundleName.c_str()); } #ifdef BUNDLE_FRAMEWORK_APP_CONTROL std::shared_ptr<AppControlManager> appControlMgr = DelayedSingleton<AppControlManager>::GetInstance(); if (appControlMgr != nullptr) { LOG_D(BMS_TAG_INSTALLER, "Delete disposed rule when bundleName :%{public}s uninstall", bundleName.c_str()); appControlMgr->DeleteAllDisposedRuleByBundle(oldInfo, Constants::MAIN_APP_INDEX, userId_); } #endif LOG_D(BMS_TAG_INSTALLER, "finish to process %{public}s bundle uninstall", bundleName.c_str()); // remove drive so file std::shared_ptr driverInstaller = std::make_shared<DriverInstaller>(); driverInstaller->RemoveDriverSoFile(oldInfo, "", false); if (oldInfo.IsPreInstallApp()) { LOG_I(BMS_TAG_INSTALLER, "Pre-installed app %{public}s detected, Marking as uninstalled", bundleName.c_str()); MarkPreInstallState(bundleName, true); } BundleResourceHelper::DeleteResourceInfo(bundleName, userId_); // remove profile from code signature RemoveProfileFromCodeSign(bundleName); ClearDomainVerifyStatus(oldInfo.GetAppIdentifier(), bundleName); SaveUninstallBundleInfo(bundleName, installParam.isKeepData, uninstallBundleInfo); return ERR_OK; } ErrCode BaseBundleInstaller::ProcessBundleUninstall( const std::string &bundleName, const std::string &modulePackage, const InstallParam &installParam, int32_t &uid) { LOG_D(BMS_TAG_INSTALLER, "process %{public}s in %{public}s uninstall", bundleName.c_str(), modulePackage.c_str()); if (bundleName.empty() || modulePackage.empty()) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle name or module name empty"); return ERR_APPEXECFWK_UNINSTALL_INVALID_NAME; } if (!InitDataMgr()) { return ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR; } userId_ = GetUserId(installParam.userId); if (userId_ == Constants::INVALID_USERID) { return ERR_APPEXECFWK_INSTALL_PARAM_ERROR; } if (!dataMgr_->HasUserId(userId_)) { LOG_E(BMS_TAG_INSTALLER, "The user %{public}d does not exist when uninstall", userId_); return ERR_APPEXECFWK_USER_NOT_EXIST; } auto &mtx = dataMgr_->GetBundleMutex(bundleName); std::lock_guard lock {mtx}; InnerBundleInfo oldInfo; if (!dataMgr_->GetInnerBundleInfo(bundleName, oldInfo)) { LOG_W(BMS_TAG_INSTALLER, "uninstall bundle info missing"); return ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE; } uninstallBundleAppId_ = oldInfo.GetAppId(); versionCode_ = oldInfo.GetVersionCode(); ScopeGuard enableGuard([&] { dataMgr_->EnableBundle(bundleName); }); if (oldInfo.GetApplicationBundleType() == BundleType::SHARED) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle is shared library"); return ERR_APPEXECFWK_UNINSTALL_BUNDLE_IS_SHARED_LIBRARY; } InnerBundleUserInfo curInnerBundleUserInfo; if (!oldInfo.GetInnerBundleUserInfo(userId_, curInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "bundle(%{public}s) get user(%{public}d) failed when uninstall", oldInfo.GetBundleName().c_str(), userId_); return ERR_APPEXECFWK_USER_NOT_INSTALL_HAP; } uid = curInnerBundleUserInfo.uid; if (!installParam.GetForceExecuted() && !oldInfo.IsRemovable() && installParam.GetKillProcess()) { LOG_E(BMS_TAG_INSTALLER, "uninstall system app"); return ERR_APPEXECFWK_UNINSTALL_SYSTEM_APP_ERROR; } if (!installParam.GetForceExecuted() && !oldInfo.GetUninstallState() && installParam.GetKillProcess() && !installParam.GetIsUninstallAndRecover()) { LOG_E(BMS_TAG_INSTALLER, "bundle : %{public}s can not be uninstalled, uninstallState : %{public}d", bundleName.c_str(), oldInfo.GetUninstallState()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL; } bool isModuleExist = oldInfo.FindModule(modulePackage); if (!isModuleExist) { LOG_E(BMS_TAG_INSTALLER, "uninstall bundle info missing"); return ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_MODULE; } if (!UninstallAppControl(oldInfo.GetAppId(), userId_)) { LOG_D(BMS_TAG_INSTALLER, "bundleName: %{public}s is not allow uninstall", bundleName.c_str()); return ERR_BUNDLE_MANAGER_APP_CONTROL_DISALLOWED_UNINSTALL; } if (!dataMgr_->UpdateBundleInstallState(bundleName, InstallState::UNINSTALL_START)) { LOG_E(BMS_TAG_INSTALLER, "uninstall already start"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } ScopeGuard stateGuard([&] { dataMgr_->UpdateBundleInstallState(bundleName, InstallState::INSTALL_SUCCESS); }); // reboot scan case will not kill the bundle if (installParam.GetKillProcess()) { // kill the bundle process during uninstall. if (!AbilityManagerHelper::UninstallApplicationProcesses(oldInfo.GetApplicationName(), uid)) { LOG_E(BMS_TAG_INSTALLER, "can not kill process, uid : %{public}d", uid); return ERR_APPEXECFWK_UNINSTALL_KILLING_APP_ERROR; } } oldInfo.SetInstallMark(bundleName, modulePackage, InstallExceptionStatus::UNINSTALL_PACKAGE_START); if (!dataMgr_->SaveInnerBundleInfo(oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "save install mark failed"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } UninstallBundleInfo uninstallBundleInfo; GetUninstallBundleInfo(installParam.isKeepData, userId_, oldInfo, uninstallBundleInfo); bool onlyInstallInUser = oldInfo.GetInnerBundleUserInfos().size() == 1; ErrCode result = ERR_OK; // if it is the only module in the bundle if (oldInfo.IsOnlyModule(modulePackage)) { LOG_I(BMS_TAG_INSTALLER, "%{public}s is only module", modulePackage.c_str()); enableGuard.Dismiss(); stateGuard.Dismiss(); if (onlyInstallInUser) { result = ProcessBundleUnInstallNative(oldInfo, userId_, bundleName); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove nativeBundle failed"); return result; } result = RemoveBundle(oldInfo, installParam.isKeepData); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove bundle failed"); return result; } // remove profile from code signature RemoveProfileFromCodeSign(bundleName); ClearDomainVerifyStatus(oldInfo.GetAppIdentifier(), bundleName); result = DeleteOldArkNativeFile(oldInfo); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "delete old arkNativeFile failed"); return result; } result = DeleteArkProfile(bundleName, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to removeArkProfile, error is %{public}d", result); return result; } if ((result = CleanAsanDirectory(oldInfo)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove asan log path, error is %{public}d", result); return result; } if (oldInfo.IsPreInstallApp()) { LOG_I(BMS_TAG_INSTALLER, "%{public}s detected, Marking as uninstalled", bundleName.c_str()); MarkPreInstallState(bundleName, true); } SaveUninstallBundleInfo(bundleName, installParam.isKeepData, uninstallBundleInfo); return ERR_OK; } auto removeRes = RemoveBundleUserData(oldInfo, installParam.isKeepData); if (removeRes != ERR_OK) { return removeRes; } SaveUninstallBundleInfo(bundleName, installParam.isKeepData, uninstallBundleInfo); return ERR_OK; } if (onlyInstallInUser) { LOG_I(BMS_TAG_INSTALLER, "%{public}s is only install at the userId %{public}d", bundleName.c_str(), userId_); result = RemoveModuleAndDataDir(oldInfo, modulePackage, userId_, installParam.isKeepData); } if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove module dir failed"); return result; } oldInfo.SetInstallMark(bundleName, modulePackage, InstallExceptionStatus::INSTALL_FINISH); LOG_D(BMS_TAG_INSTALLER, "remove module %{public}s in %{public}s ", modulePackage.c_str(), bundleName.c_str()); if (!dataMgr_->RemoveModuleInfo(bundleName, modulePackage, oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "RemoveModuleInfo failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } std::shared_ptr driverInstaller = std::make_shared<DriverInstaller>(); driverInstaller->RemoveDriverSoFile(oldInfo, oldInfo.GetModuleName(modulePackage), false); LOG_D(BMS_TAG_INSTALLER, "finish %{public}s in %{public}s uninstall", bundleName.c_str(), modulePackage.c_str()); return ERR_OK; } void BaseBundleInstaller::MarkPreInstallState(const std::string &bundleName, bool isUninstalled) { LOG_I(BMS_TAG_INSTALLER, "bundle: %{public}s isUninstalled: %{public}d", bundleName.c_str(), isUninstalled); if (!dataMgr_) { LOG_E(BMS_TAG_INSTALLER, "dataMgr is nullptr"); return; } PreInstallBundleInfo preInstallBundleInfo; preInstallBundleInfo.SetBundleName(bundleName); if (!dataMgr_->GetPreInstallBundleInfo(bundleName, preInstallBundleInfo)) { LOG_I(BMS_TAG_INSTALLER, "No PreInstallBundleInfo(%{public}s) in db", bundleName.c_str()); return; } preInstallBundleInfo.SetIsUninstalled(isUninstalled); dataMgr_->SavePreInstallBundleInfo(bundleName, preInstallBundleInfo); } ErrCode BaseBundleInstaller::ProcessInstallBundleByBundleName( const std::string &bundleName, const InstallParam &installParam, int32_t &uid) { LOG_D(BMS_TAG_INSTALLER, "Process Install Bundle(%{public}s) start", bundleName.c_str()); return InnerProcessInstallByPreInstallInfo(bundleName, installParam, uid); } ErrCode BaseBundleInstaller::ProcessRecover( const std::string &bundleName, const InstallParam &installParam, int32_t &uid) { LOG_D(BMS_TAG_INSTALLER, "Process Recover Bundle(%{public}s) start", bundleName.c_str()); ErrCode result = InnerProcessInstallByPreInstallInfo(bundleName, installParam, uid); return result; } ErrCode BaseBundleInstaller::InnerProcessInstallByPreInstallInfo( const std::string &bundleName, const InstallParam &installParam, int32_t &uid) { if (!InitDataMgr()) { return ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR; } userId_ = GetUserId(installParam.userId); if (userId_ == Constants::INVALID_USERID) { return ERR_APPEXECFWK_INSTALL_PARAM_ERROR; } if (!dataMgr_->HasUserId(userId_)) { LOG_E(BMS_TAG_INSTALLER, "The user %{public}d does not exist", userId_); return ERR_APPEXECFWK_USER_NOT_EXIST; } { auto &mtx = dataMgr_->GetBundleMutex(bundleName); std::lock_guard lock {mtx}; InnerBundleInfo oldInfo; bool isAppExist = dataMgr_->GetInnerBundleInfo(bundleName, oldInfo); if (isAppExist) { dataMgr_->EnableBundle(bundleName); if (oldInfo.GetApplicationBundleType() == BundleType::SHARED) { LOG_D(BMS_TAG_INSTALLER, "shared bundle (%{public}s) is irrelevant to user", bundleName.c_str()); return ERR_OK; } versionCode_ = oldInfo.GetVersionCode(); if (oldInfo.GetApplicationBundleType() == BundleType::APP_SERVICE_FWK) { LOG_D(BMS_TAG_INSTALLER, "Appservice (%{public}s) only install in U0", bundleName.c_str()); return ERR_OK; } if (oldInfo.HasInnerBundleUserInfo(userId_)) { LOG_E(BMS_TAG_INSTALLER, "App is exist in user(%{public}d)", userId_); return ERR_APPEXECFWK_INSTALL_ALREADY_EXIST; } ErrCode ret = InstallNormalAppControl(oldInfo.GetAppId(), userId_, installParam.isPreInstallApp); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "%{private}s check install app control failed", oldInfo.GetAppId().c_str()); return ret; } ret = CheckSingleton(oldInfo, userId_); CHECK_RESULT(ret, "Check singleton failed %{public}d"); InnerBundleUserInfo curInnerBundleUserInfo; curInnerBundleUserInfo.bundleUserInfo.userId = userId_; curInnerBundleUserInfo.bundleName = bundleName; oldInfo.AddInnerBundleUserInfo(curInnerBundleUserInfo); ScopeGuard userGuard([&] { RemoveBundleUserData(oldInfo, false); }); Security::AccessToken::AccessTokenIDEx accessTokenIdEx; if (BundlePermissionMgr::InitHapToken(oldInfo, userId_, 0, accessTokenIdEx) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "bundleName:%{public}s InitHapToken failed", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED; } accessTokenId_ = accessTokenIdEx.tokenIdExStruct.tokenID; oldInfo.SetAccessTokenIdEx(accessTokenIdEx, userId_); auto result = CreateBundleUserData(oldInfo); if (result != ERR_OK) { return result; } std::vector<std::string> extensionDirs = oldInfo.GetAllExtensionDirs(); createExtensionDirs_.assign(extensionDirs.begin(), extensionDirs.end()); CreateExtensionDataDir(oldInfo); GenerateNewUserDataGroupInfos(oldInfo); bundleName_ = bundleName; CreateScreenLockProtectionDir(); // extract ap file result = ExtractAllArkProfileFile(oldInfo); if (result != ERR_OK) { return result; } userGuard.Dismiss(); uid = oldInfo.GetUid(userId_); GetInstallEventInfo(oldInfo, sysEventInfo_); UtdHandler::InstallUtdAsync(bundleName, userId_); return ERR_OK; } } PreInstallBundleInfo preInstallBundleInfo; preInstallBundleInfo.SetBundleName(bundleName); if (!dataMgr_->GetPreInstallBundleInfo(bundleName, preInstallBundleInfo) || preInstallBundleInfo.GetBundlePaths().empty()) { LOG_E(BMS_TAG_INSTALLER, "Get PreInstallBundleInfo faile, bundleName: %{public}s", bundleName.c_str()); return ERR_APPEXECFWK_RECOVER_INVALID_BUNDLE_NAME; } LOG_D(BMS_TAG_INSTALLER, "Get preInstall bundlePath success"); std::vector<std::string> pathVec; auto innerInstallParam = installParam; bool isSharedBundle = preInstallBundleInfo.GetBundlePaths().front().find(PRE_INSTALL_HSP_PATH) != std::string::npos; if (isSharedBundle) { innerInstallParam.sharedBundleDirPaths = preInstallBundleInfo.GetBundlePaths(); } else { pathVec = preInstallBundleInfo.GetBundlePaths(); } innerInstallParam.isPreInstallApp = true; innerInstallParam.removable = preInstallBundleInfo.IsRemovable(); innerInstallParam.copyHapToInstallPath = false; return ProcessBundleInstall(pathVec, innerInstallParam, preInstallBundleInfo.GetAppType(), uid); } ErrCode BaseBundleInstaller::RemoveBundle(InnerBundleInfo &info, bool isKeepData, const bool async) { if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!dataMgr_->UpdateBundleInstallState(info.GetBundleName(), InstallState::UNINSTALL_SUCCESS)) { LOG_E(BMS_TAG_INSTALLER, "delete inner info failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (info.GetApplicationBundleType() == BundleType::ATOMIC_SERVICE) { int32_t uid = info.GetUid(userId_); if (uid != Constants::INVALID_UID) { LOG_I(BMS_TAG_INSTALLER, "uninstall atomic service need delete quota, bundleName:%{public}s", info.GetBundleName().c_str()); std::string bundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::BASE + info.GetBundleName(); PrepareBundleDirQuota(info.GetBundleName(), uid, bundleDataDir, 0); } } ErrCode result = RemoveBundleAndDataDir(info, isKeepData, async); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove bundle dir failed"); return result; } accessTokenId_ = info.GetAccessTokenId(userId_); if (BundlePermissionMgr::DeleteAccessTokenId(accessTokenId_) != AccessToken::AccessTokenKitRet::RET_SUCCESS) { LOG_E(BMS_TAG_INSTALLER, "delete accessToken failed"); } return ERR_OK; } ErrCode BaseBundleInstaller::ProcessBundleInstallNative(InnerBundleInfo &info, int32_t &userId) { if (info.GetInnerModuleInfoHnpInfo(info.GetCurModuleName())) { std::string moduleHnpsPath = info.GetInnerModuleInfoHnpPath(info.GetCurModuleName()); ErrCode ret = InstalldClient::GetInstance()->ProcessBundleInstallNative(std::to_string(userId), moduleHnpsPath, modulePath_, info.GetCpuAbi(), info.GetBundleName()); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "installing the native package failed. error code: %{public}d", ret); return ret; } if ((InstalldClient::GetInstance()->RemoveDir(moduleHnpsPath)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "delete dir %{public}s failed", moduleHnpsPath.c_str()); } } return ERR_OK; } ErrCode BaseBundleInstaller::ProcessBundleUnInstallNative(InnerBundleInfo &info, int32_t &userId, std::string bundleName) { if (info.GetInnerModuleInfoHnpInfo(info.GetCurModuleName())) { ErrCode ret = InstalldClient::GetInstance()->ProcessBundleUnInstallNative( std::to_string(userId).c_str(), bundleName.c_str()); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "uninstalling the native package failed. error code: %{public}d", ret); return ret; } } return ERR_OK; } ErrCode BaseBundleInstaller::ProcessBundleInstallStatus(InnerBundleInfo &info, int32_t &uid) { modulePackage_ = info.GetCurrentModulePackage(); LOG_D(BMS_TAG_INSTALLER, "ProcessBundleInstallStatus with bundleName %{public}s and packageName %{public}s", bundleName_.c_str(), modulePackage_.c_str()); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_START)) { LOG_E(BMS_TAG_INSTALLER, "install already start"); return ERR_APPEXECFWK_INSTALL_STATE_ERROR; } Security::AccessToken::AccessTokenIDEx accessTokenIdEx; if (BundlePermissionMgr::InitHapToken(info, userId_, 0, accessTokenIdEx) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "bundleName:%{public}s InitHapToken failed", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED; } accessTokenId_ = accessTokenIdEx.tokenIdExStruct.tokenID; info.SetAccessTokenIdEx(accessTokenIdEx, userId_); info.SetInstallMark(bundleName_, modulePackage_, InstallExceptionStatus::INSTALL_START); if (!dataMgr_->SaveInnerBundleInfo(info)) { LOG_E(BMS_TAG_INSTALLER, "save install mark to storage failed"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } ScopeGuard stateGuard([&] { dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::INSTALL_FAIL); }); ErrCode result = CreateBundleAndDataDir(info); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "create bundle and data dir failed"); return result; } // delivery sign profile to code signature result = DeliveryProfileToCodeSign(); CHECK_RESULT(result, "delivery profile failed %{public}d"); ScopeGuard bundleGuard([&] { RemoveBundleAndDataDir(info, false); }); std::string modulePath = info.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + modulePackage_; result = ExtractModule(info, modulePath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "extract module failed"); return result; } result = ProcessBundleInstallNative(info, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "Install Native failed"); return result; } info.SetInstallMark(bundleName_, modulePackage_, InstallExceptionStatus::INSTALL_FINISH); uid = info.GetUid(userId_); info.SetBundleInstallTime(BundleUtil::GetCurrentTimeMs(), userId_); if (!dataMgr_->AddInnerBundleInfo(bundleName_, info)) { LOG_E(BMS_TAG_INSTALLER, "add bundle %{public}s info failed", bundleName_.c_str()); dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UNINSTALL_START); dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UNINSTALL_SUCCESS); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } stateGuard.Dismiss(); bundleGuard.Dismiss(); LOG_D(BMS_TAG_INSTALLER, "finish to call processBundleInstallStatus"); return ERR_OK; } bool BaseBundleInstaller::AllowSingletonChange(const std::string &bundleName) { return SINGLETON_WHITE_LIST.find(bundleName) != SINGLETON_WHITE_LIST.end(); } ErrCode BaseBundleInstaller::ProcessBundleUpdateStatus( InnerBundleInfo &oldInfo, InnerBundleInfo &newInfo, bool isReplace, bool killProcess) { if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_STATE_ERROR; } modulePackage_ = newInfo.GetCurrentModulePackage(); if (modulePackage_.empty()) { LOG_E(BMS_TAG_INSTALLER, "get current package failed"); return ERR_APPEXECFWK_INSTALL_PARAM_ERROR; } if (isFeatureNeedUninstall_) { uninstallModuleVec_.emplace_back(modulePackage_); } if (oldInfo.IsSingleton() != newInfo.IsSingleton()) { if ((oldInfo.IsSingleton() && !newInfo.IsSingleton()) && newInfo.IsPreInstallApp() && AllowSingletonChange(newInfo.GetBundleName())) { singletonState_ = SingletonState::SINGLETON_TO_NON; } else if ((!oldInfo.IsSingleton() && newInfo.IsSingleton()) && newInfo.IsPreInstallApp() && AllowSingletonChange(newInfo.GetBundleName())) { singletonState_ = SingletonState::NON_TO_SINGLETON; } else { LOG_E(BMS_TAG_INSTALLER, "Singleton not allow changed"); return ERR_APPEXECFWK_INSTALL_SINGLETON_INCOMPATIBLE; } LOG_I(BMS_TAG_INSTALLER, "Singleton %{public}s changed", newInfo.GetBundleName().c_str()); } auto result = CheckOverlayUpdate(oldInfo, newInfo, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "CheckOverlayUpdate failed due to %{public}d", result); return result; } LOG_D(BMS_TAG_INSTALLER, "%{public}s, %{public}s", newInfo.GetBundleName().c_str(), modulePackage_.c_str()); if (!dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UPDATING_START)) { LOG_E(BMS_TAG_INSTALLER, "update already start"); return ERR_APPEXECFWK_INSTALL_STATE_ERROR; } if (!CheckAppIdentifier(oldInfo.GetAppIdentifier(), newInfo.GetAppIdentifier(), oldInfo.GetProvisionId(), newInfo.GetProvisionId())) { return ERR_APPEXECFWK_INSTALL_FAILED_INCONSISTENT_SIGNATURE; } LOG_D(BMS_TAG_INSTALLER, "ProcessBundleUpdateStatus killProcess = %{public}d", killProcess); // now there are two cases for updating: // 1. bundle exist, hap exist, update hap // 2. bundle exist, install new hap bool isModuleExist = oldInfo.FindModule(modulePackage_); if (isModuleExist) { isModuleUpdate_ = true; } newInfo.RestoreFromOldInfo(oldInfo); result = isModuleExist ? ProcessModuleUpdate(newInfo, oldInfo, isReplace, killProcess) : ProcessNewModuleInstall(newInfo, oldInfo); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "install module failed %{public}d", result); return result; } LOG_D(BMS_TAG_INSTALLER, "finish to call ProcessBundleUpdateStatus"); return ERR_OK; } bool BaseBundleInstaller::CheckAppIdentifier(const std::string &oldAppIdentifier, const std::string &newAppIdentifier, const std::string &oldAppId, const std::string &newAppId) { // for versionCode update if (!oldAppIdentifier.empty() && !newAppIdentifier.empty() && oldAppIdentifier == newAppIdentifier) { return true; } if (oldAppId == newAppId) { return true; } LOG_E(BMS_TAG_INSTALLER, "the appIdentifier or appId of the new bundle is not the same as old one"); return false; } ErrCode BaseBundleInstaller::ProcessNewModuleInstall(InnerBundleInfo &newInfo, InnerBundleInfo &oldInfo) { LOG_D(BMS_TAG_INSTALLER, "ProcessNewModuleInstall %{public}s, userId: %{public}d", newInfo.GetBundleName().c_str(), userId_); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if ((!isFeatureNeedUninstall_ && !otaInstall_) && (newInfo.HasEntry() && oldInfo.HasEntry())) { LOG_E(BMS_TAG_INSTALLER, "install more than one entry module"); return ERR_APPEXECFWK_INSTALL_ENTRY_ALREADY_EXIST; } if ((!isFeatureNeedUninstall_ && !otaInstall_) && bundleInstallChecker_->IsContainModuleName(newInfo, oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "moduleName is already existed"); return ERR_APPEXECFWK_INSTALL_NOT_UNIQUE_DISTRO_MODULE_NAME; } // same version need to check app label ErrCode result = ERR_OK; if (!otaInstall_ && (oldInfo.GetVersionCode() == newInfo.GetVersionCode())) { result = CheckAppLabel(oldInfo, newInfo); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "CheckAppLabel failed %{public}d", result); return result; } if (!CheckDuplicateProxyData(newInfo, oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "CheckDuplicateProxyData with old info failed"); return ERR_APPEXECFWK_INSTALL_CHECK_PROXY_DATA_URI_FAILED; } } if (isAppExist_) { oldInfo.SetInstallMark(bundleName_, modulePackage_, InstallExceptionStatus::UPDATING_NEW_START); } std::string modulePath = newInfo.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + modulePackage_; result = ExtractModule(newInfo, modulePath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "extract module and rename failed"); return result; } result = ProcessBundleInstallNative(newInfo, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "Install Native failed"); return result; } ScopeGuard moduleGuard([&] { RemoveModuleDir(modulePath); }); if (!dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UPDATING_SUCCESS)) { LOG_E(BMS_TAG_INSTALLER, "new moduleupdate state failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } oldInfo.SetInstallMark(bundleName_, modulePackage_, InstallExceptionStatus::INSTALL_FINISH); oldInfo.SetBundleUpdateTime(BundleUtil::GetCurrentTimeMs(), userId_); if ((result = ProcessAsanDirectory(newInfo)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "process asan log directory failed"); return result; } if (!dataMgr_->AddNewModuleInfo(bundleName_, newInfo, oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "add module %{public}s to innerBundleInfo %{public}s failed", modulePackage_.c_str(), bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } moduleGuard.Dismiss(); return ERR_OK; } ErrCode BaseBundleInstaller::ProcessModuleUpdate(InnerBundleInfo &newInfo, InnerBundleInfo &oldInfo, bool isReplace, bool killProcess) { LOG_D(BMS_TAG_INSTALLER, "bundleName :%{public}s, moduleName: %{public}s, userId: %{public}d", newInfo.GetBundleName().c_str(), newInfo.GetCurrentModulePackage().c_str(), userId_); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } // update module type is forbidden if ((!isFeatureNeedUninstall_ && !otaInstall_) && (newInfo.HasEntry() && oldInfo.HasEntry())) { if (!oldInfo.IsEntryModule(modulePackage_)) { LOG_E(BMS_TAG_INSTALLER, "install more than one entry module"); return ERR_APPEXECFWK_INSTALL_ENTRY_ALREADY_EXIST; } } if ((!isFeatureNeedUninstall_ && !otaInstall_) && !bundleInstallChecker_->IsExistedDistroModule(newInfo, oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "moduleName is inconsistent in the updating hap"); return ERR_APPEXECFWK_INSTALL_INCONSISTENT_MODULE_NAME; } ErrCode result = ERR_OK; if (!otaInstall_ && (versionCode_ == oldInfo.GetVersionCode())) { if (((result = CheckAppLabel(oldInfo, newInfo)) != ERR_OK)) { LOG_E(BMS_TAG_INSTALLER, "CheckAppLabel failed %{public}d", result); return result; } if (!isReplace) { if (hasInstalledInUser_) { LOG_E(BMS_TAG_INSTALLER, "fail to install already existing bundle using normal flag"); return ERR_APPEXECFWK_INSTALL_ALREADY_EXIST; } // app versionCode equals to the old and do not need to update module // and only need to update userInfo newInfo.SetOnlyCreateBundleUser(true); if (!dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UPDATING_SUCCESS)) { LOG_E(BMS_TAG_INSTALLER, "update state failed"); return ERR_APPEXECFWK_INSTALL_STATE_ERROR; } return ERR_OK; } } #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION result = OverlayDataMgr::GetInstance()->UpdateOverlayModule(newInfo, oldInfo); CHECK_RESULT(result, "UpdateOverlayModule failed %{public}d"); #endif LOG_D(BMS_TAG_INSTALLER, "ProcessModuleUpdate killProcess = %{public}d", killProcess); // reboot scan case will not kill the bundle if (killProcess) { UpdateKillApplicationProcess(oldInfo); } oldInfo.SetInstallMark(bundleName_, modulePackage_, InstallExceptionStatus::UPDATING_EXISTED_START); result = CheckArkProfileDir(newInfo, oldInfo); CHECK_RESULT(result, "CheckArkProfileDir failed %{public}d"); auto hnpPackageOldInfos = oldInfo.GetInnerModuleInfoHnpInfo(oldInfo.GetCurModuleName()); auto hnpPackageNewInfos = newInfo.GetInnerModuleInfoHnpInfo(newInfo.GetCurModuleName()); if (hnpPackageOldInfos) { for (const auto &item : *hnpPackageOldInfos) { auto it = std::find_if(hnpPackageNewInfos->begin(), hnpPackageNewInfos->end(), [&](const HnpPackage &hnpPackage) {return hnpPackage.package == item.package;}); if (it == hnpPackageNewInfos->end()) { ErrCode ret = ProcessBundleUnInstallNative(oldInfo, userId_, bundleName_); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove nativeBundle failed"); return ret; } } } } result = ProcessAsanDirectory(newInfo); CHECK_RESULT(result, "process asan log directory failed %{public}d"); moduleTmpDir_ = newInfo.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + modulePackage_ + ServiceConstants::TMP_SUFFIX; result = ExtractModule(newInfo, moduleTmpDir_); CHECK_RESULT(result, "extract module and rename failed %{public}d"); result = ProcessBundleInstallNative(newInfo, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "Install Native failed"); return result; } if (!dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UPDATING_SUCCESS)) { LOG_E(BMS_TAG_INSTALLER, "old module update state failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } newInfo.RestoreModuleInfo(oldInfo); oldInfo.SetInstallMark(bundleName_, modulePackage_, InstallExceptionStatus::UPDATING_FINISH); oldInfo.SetBundleUpdateTime(BundleUtil::GetCurrentTimeMs(), userId_); if (!dataMgr_->UpdateInnerBundleInfo(bundleName_, newInfo, oldInfo)) { LOG_E(BMS_TAG_INSTALLER, "update innerBundleInfo %{public}s failed", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } needDeleteQuickFixInfo_ = true; return ERR_OK; } void BaseBundleInstaller::ProcessQuickFixWhenInstallNewModule(const InstallParam &installParam, const std::unordered_map<std::string, InnerBundleInfo> &newInfos) { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX // hqf extract diff file or apply diff patch failed does not affect the hap installation InnerBundleInfo bundleInfo; bool isBundleExist = false; if (!GetInnerBundleInfo(bundleInfo, isBundleExist) || !isBundleExist) { return; } for (auto &info : newInfos) { modulePackage_ = info.second.GetCurrentModulePackage(); if (!installedModules_[modulePackage_]) { modulePath_ = info.first; if (bundleInfo.IsEncryptedMoudle(modulePackage_) && installParam.copyHapToInstallPath) { modulePath_ = GetHapPath(info.second); } ProcessHqfInfo(bundleInfo, info.second); } } #endif } void BaseBundleInstaller::ProcessHqfInfo( const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo) const { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX LOG_D(BMS_TAG_INSTALLER, "bundleName: %{public}s, moduleName: %{public}s", bundleName_.c_str(), modulePackage_.c_str()); std::string cpuAbi; std::string nativeLibraryPath; if (!newInfo.FetchNativeSoAttrs(modulePackage_, cpuAbi, nativeLibraryPath)) { LOG_I(BMS_TAG_INSTALLER, "No native so, bundleName: %{public}s, moduleName: %{public}s", bundleName_.c_str(), modulePackage_.c_str()); return; } auto pos = nativeLibraryPath.rfind(ServiceConstants::LIBS); if (pos != std::string::npos) { nativeLibraryPath = nativeLibraryPath.substr(pos, nativeLibraryPath.length() - pos); } ErrCode ret = ProcessDeployedHqfInfo( nativeLibraryPath, cpuAbi, newInfo, oldInfo.GetAppQuickFix()); if (ret != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "ProcessDeployedHqfInfo failed, errcode: %{public}d", ret); return; } ret = ProcessDeployingHqfInfo(nativeLibraryPath, cpuAbi, newInfo); if (ret != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "ProcessDeployingHqfInfo failed, errcode: %{public}d", ret); return; } LOG_D(BMS_TAG_INSTALLER, "ProcessHqfInfo end"); #endif } ErrCode BaseBundleInstaller::ProcessDeployedHqfInfo(const std::string &nativeLibraryPath, const std::string &cpuAbi, const InnerBundleInfo &newInfo, const AppQuickFix &oldAppQuickFix) const { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX LOG_D(BMS_TAG_INSTALLER, "ProcessDeployedHqfInfo"); if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "dataMgr_ is nullptr"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } auto appQuickFix = oldAppQuickFix; AppqfInfo &appQfInfo = appQuickFix.deployedAppqfInfo; if (isFeatureNeedUninstall_ || appQfInfo.hqfInfos.empty()) { LOG_I(BMS_TAG_INSTALLER, "No need ProcessDeployedHqfInfo"); return ERR_OK; } ErrCode ret = ProcessDiffFiles(appQfInfo, nativeLibraryPath, cpuAbi); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "ProcessDeployedHqfInfo failed, errcode: %{public}d", ret); return ret; } std::string newSoPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::PATH_SEPARATOR + ServiceConstants::PATCH_PATH + std::to_string(appQfInfo.versionCode) + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath; bool isExist = false; if ((InstalldClient::GetInstance()->IsExistDir(newSoPath, isExist) != ERR_OK) || !isExist) { LOG_W(BMS_TAG_INSTALLER, "Patch no diff file"); return ERR_OK; } ret = UpdateLibAttrs(newInfo, cpuAbi, nativeLibraryPath, appQfInfo); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "UpdateModuleLib failed, errcode: %{public}d", ret); return ret; } InnerBundleInfo innerBundleInfo; if (!dataMgr_->FetchInnerBundleInfo(bundleName_, innerBundleInfo)) { LOG_E(BMS_TAG_INSTALLER, "Fetch bundleInfo(%{public}s) failed", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } innerBundleInfo.SetAppQuickFix(appQuickFix); if (!dataMgr_->UpdateQuickFixInnerBundleInfo(bundleName_, innerBundleInfo)) { LOG_E(BMS_TAG_INSTALLER, "update quickfix innerbundleInfo failed"); return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR; } #endif return ERR_OK; } ErrCode BaseBundleInstaller::ProcessDeployingHqfInfo( const std::string &nativeLibraryPath, const std::string &cpuAbi, const InnerBundleInfo &newInfo) const { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX LOG_D(BMS_TAG_INSTALLER, "ProcessDeployingHqfInfo"); std::shared_ptr<QuickFixDataMgr> quickFixDataMgr = DelayedSingleton<QuickFixDataMgr>::GetInstance(); if (quickFixDataMgr == nullptr) { LOG_E(BMS_TAG_INSTALLER, "quick fix data mgr is nullptr"); return ERR_BUNDLEMANAGER_QUICK_FIX_INTERNAL_ERROR; } InnerAppQuickFix innerAppQuickFix; if (!quickFixDataMgr->QueryInnerAppQuickFix(bundleName_, innerAppQuickFix)) { return ERR_OK; } auto appQuickFix = innerAppQuickFix.GetAppQuickFix(); AppqfInfo &appQfInfo = appQuickFix.deployingAppqfInfo; ErrCode ret = ProcessDiffFiles(appQfInfo, nativeLibraryPath, cpuAbi); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "failed errcode: %{public}d path: %{public}s", ret, nativeLibraryPath.c_str()); return ret; } std::string newSoPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::PATH_SEPARATOR + ServiceConstants::PATCH_PATH + std::to_string(appQfInfo.versionCode) + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath; bool isExist = false; if ((InstalldClient::GetInstance()->IsExistDir(newSoPath, isExist) != ERR_OK) || !isExist) { LOG_W(BMS_TAG_INSTALLER, "Patch no diff file"); return ERR_OK; } ret = UpdateLibAttrs(newInfo, cpuAbi, nativeLibraryPath, appQfInfo); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "UpdateModuleLib failed, errcode: %{public}d", ret); return ret; } innerAppQuickFix.SetAppQuickFix(appQuickFix); if (!quickFixDataMgr->SaveInnerAppQuickFix(innerAppQuickFix)) { LOG_E(BMS_TAG_INSTALLER, "bundleName: %{public}s, inner app quick fix save failed", bundleName_.c_str()); return ERR_BUNDLEMANAGER_QUICK_FIX_SAVE_APP_QUICK_FIX_FAILED; } #endif return ERR_OK; } ErrCode BaseBundleInstaller::UpdateLibAttrs(const InnerBundleInfo &newInfo, const std::string &cpuAbi, const std::string &nativeLibraryPath, AppqfInfo &appQfInfo) const { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX auto newNativeLibraryPath = ServiceConstants::PATCH_PATH + std::to_string(appQfInfo.versionCode) + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath; auto moduleName = newInfo.GetCurModuleName(); bool isLibIsolated = newInfo.IsLibIsolated(moduleName); if (!isLibIsolated) { appQfInfo.nativeLibraryPath = newNativeLibraryPath; appQfInfo.cpuAbi = cpuAbi; return ERR_OK; } for (auto &hqfInfo : appQfInfo.hqfInfos) { if (hqfInfo.moduleName != moduleName) { continue; } hqfInfo.nativeLibraryPath = newNativeLibraryPath; hqfInfo.cpuAbi = cpuAbi; if (!BundleUtil::StartWith(appQfInfo.nativeLibraryPath, ServiceConstants::PATCH_PATH)) { appQfInfo.nativeLibraryPath.clear(); } return ERR_OK; } return ERR_BUNDLEMANAGER_QUICK_FIX_MODULE_NAME_NOT_EXIST; #else return ERR_OK; #endif } bool BaseBundleInstaller::CheckHapLibsWithPatchLibs( const std::string &nativeLibraryPath, const std::string &hqfLibraryPath) const { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX if (!hqfLibraryPath.empty()) { auto position = hqfLibraryPath.find(ServiceConstants::PATH_SEPARATOR); if (position == std::string::npos) { return false; } auto newHqfLibraryPath = hqfLibraryPath.substr(position); if (!BundleUtil::EndWith(nativeLibraryPath, newHqfLibraryPath)) { LOG_E(BMS_TAG_INSTALLER, "error: nativeLibraryPath not same, newInfo: %{public}s, hqf: %{public}s", nativeLibraryPath.c_str(), newHqfLibraryPath.c_str()); return false; } } #endif return true; } bool BaseBundleInstaller::ExtractSoFiles(const std::string &soPath, const std::string &cpuAbi) const { ExtractParam extractParam; extractParam.extractFileType = ExtractFileType::SO; extractParam.srcPath = modulePath_; extractParam.targetPath = soPath; extractParam.cpuAbi = cpuAbi; if (InstalldClient::GetInstance()->ExtractFiles(extractParam) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "bundleName: %{public}s moduleName: %{public}s extract so failed", bundleName_.c_str(), modulePackage_.c_str()); return false; } return true; } bool BaseBundleInstaller::ExtractEncryptedSoFiles(const InnerBundleInfo &info, const std::string &tmpSoPath, int32_t uid) const { LOG_D(BMS_TAG_INSTALLER, "start to extract decoded so files to tmp path"); std::string cpuAbi = ""; std::string nativeLibraryPath = ""; bool isSoExisted = info.FetchNativeSoAttrs(info.GetCurrentModulePackage(), cpuAbi, nativeLibraryPath); if (!isSoExisted) { LOG_D(BMS_TAG_INSTALLER, "so is not existed"); return true; } std::string realSoFilesPath; if (info.IsCompressNativeLibs(info.GetCurModuleName())) { realSoFilesPath.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR) .append(bundleName_).append(ServiceConstants::PATH_SEPARATOR).append(nativeLibraryPath); if (realSoFilesPath.back() != ServiceConstants::PATH_SEPARATOR[0]) { realSoFilesPath += ServiceConstants::PATH_SEPARATOR; } } LOG_D(BMS_TAG_INSTALLER, "real path %{public}s tmpPath %{public}s", realSoFilesPath.c_str(), tmpSoPath.c_str()); return InstalldClient::GetInstance()->ExtractEncryptedSoFiles(modulePath_, realSoFilesPath, cpuAbi, tmpSoPath, uid) == ERR_OK; } ErrCode BaseBundleInstaller::ProcessDiffFiles(const AppqfInfo &appQfInfo, const std::string &nativeLibraryPath, const std::string &cpuAbi) const { #ifdef BUNDLE_FRAMEWORK_QUICK_FIX const std::string moduleName = modulePackage_; auto iter = find_if(appQfInfo.hqfInfos.begin(), appQfInfo.hqfInfos.end(), [&moduleName](const auto &hqfInfo) { return hqfInfo.moduleName == moduleName; }); if (iter != appQfInfo.hqfInfos.end()) { std::string oldSoPath = ServiceConstants::HAP_COPY_PATH + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::TMP_SUFFIX + ServiceConstants::LIBS; ScopeGuard guardRemoveOldSoPath([oldSoPath] {InstalldClient::GetInstance()->RemoveDir(oldSoPath);}); InnerBundleInfo innerBundleInfo; if (dataMgr_ == nullptr || !dataMgr_->FetchInnerBundleInfo(bundleName_, innerBundleInfo)) { LOG_E(BMS_TAG_INSTALLER, "Fetch bundleInfo(%{public}s) failed", bundleName_.c_str()); return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST; } int32_t bundleUid = Constants::INVALID_UID; if (innerBundleInfo.IsEncryptedMoudle(modulePackage_)) { InnerBundleUserInfo innerBundleUserInfo; if (!innerBundleInfo.GetInnerBundleUserInfo(Constants::ALL_USERID, innerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "no user info of bundle %{public}s", bundleName_.c_str()); return ERR_BUNDLEMANAGER_QUICK_FIX_BUNDLE_NAME_NOT_EXIST; } bundleUid = innerBundleUserInfo.uid; if (!ExtractEncryptedSoFiles(innerBundleInfo, oldSoPath, bundleUid)) { LOG_W(BMS_TAG_INSTALLER, "module:%{public}s has no so file", moduleName.c_str()); return ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED; } } else { if (!ExtractSoFiles(oldSoPath, cpuAbi)) { return ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED; } } const std::string tempDiffPath = ServiceConstants::HAP_COPY_PATH + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::TMP_SUFFIX; ScopeGuard removeDiffPath([tempDiffPath] { InstalldClient::GetInstance()->RemoveDir(tempDiffPath); }); ErrCode ret = InstalldClient::GetInstance()->ExtractDiffFiles(iter->hqfFilePath, tempDiffPath, cpuAbi); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "error: ExtractDiffFiles failed errcode :%{public}d", ret); return ERR_BUNDLEMANAGER_QUICK_FIX_EXTRACT_DIFF_FILES_FAILED; } std::string newSoPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::PATH_SEPARATOR + ServiceConstants::PATCH_PATH + std::to_string(appQfInfo.versionCode) + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath; ret = InstalldClient::GetInstance()->ApplyDiffPatch(oldSoPath, tempDiffPath, newSoPath, bundleUid); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "error: ApplyDiffPatch failed errcode :%{public}d", ret); return ERR_BUNDLEMANAGER_QUICK_FIX_APPLY_DIFF_PATCH_FAILED; } } #endif return ERR_OK; } ErrCode BaseBundleInstaller::SetDirApl(const InnerBundleInfo &info) { auto& bundleUserInfos = info.GetInnerBundleUserInfos(); for (const auto &userInfoPair : bundleUserInfos) { auto &userInfo = userInfoPair.second; const std::map<std::string, InnerBundleCloneInfo> &cloneInfos = userInfo.cloneInfos; auto userId = userInfo.bundleUserInfo.userId; ErrCode userRet = SetDirApl(userId, info.GetBundleName(), info.GetBundleName(), info.GetAppPrivilegeLevel(), info.IsPreInstallApp(), info.GetBaseApplicationInfo().appProvisionType); if (userRet != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to SetDirApl bundle dir, userId %{public}d, error is %{public}d", userId, userRet); return userRet; } for (const auto &cloneInfoPair : cloneInfos) { std::string cloneBundleName = BundleCloneCommonHelper::GetCloneDataDir( info.GetBundleName(), cloneInfoPair.second.appIndex); ErrCode cloneRet = this->SetDirApl(userId, info.GetBundleName(), cloneBundleName, info.GetAppPrivilegeLevel(), info.IsPreInstallApp(), info.GetBaseApplicationInfo().appProvisionType); if (cloneRet != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to SetDirApl clone bundle dir, error is %{public}d", cloneRet); return cloneRet; } } } return ERR_OK; } ErrCode BaseBundleInstaller::SetDirApl( int32_t userId, const std::string &bundleName, const std::string &CloneBundleName, const std::string &appPrivilegeLevel, bool isPreInstallApp, const std::string &appProvisionType) { for (const auto &el : ServiceConstants::BUNDLE_EL) { std::string baseBundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + el + ServiceConstants::PATH_SEPARATOR + std::to_string(userId); std::string baseDataDir = baseBundleDataDir + ServiceConstants::BASE + CloneBundleName; std::string databaseDataDir = baseBundleDataDir + ServiceConstants::DATABASE + CloneBundleName; bool isBaseExist = true; bool isDatabaseExist = true; ErrCode result = InstalldClient::GetInstance()->IsExistDir(baseDataDir, isBaseExist); ErrCode dataResult = InstalldClient::GetInstance()->IsExistDir(databaseDataDir, isDatabaseExist); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "IsExistDir error is %{public}d", result); return result; } if (dataResult != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "IsExistDataDir error is %{public}d", dataResult); return dataResult; } if (!isBaseExist || !isDatabaseExist) { LOG_D(BMS_TAG_INSTALLER, "base %{public}s or data %{public}s is not exist", baseDataDir.c_str(), databaseDataDir.c_str()); continue; } result = InstalldClient::GetInstance()->SetDirApl( baseDataDir, bundleName, appPrivilegeLevel, isPreInstallApp, appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to SetDirApl baseDir dir, error is %{public}d", result); return result; } result = InstalldClient::GetInstance()->SetDirApl( databaseDataDir, bundleName, appPrivilegeLevel, isPreInstallApp, appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to SetDirApl databaseDir dir, error is %{public}d", result); return result; } } return ERR_OK; } ErrCode BaseBundleInstaller::CreateBundleAndDataDir(InnerBundleInfo &info) const { ErrCode result = CreateBundleCodeDir(info); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to create bundle code dir, error is %{public}d", result); return result; } ScopeGuard codePathGuard([&] { InstalldClient::GetInstance()->RemoveDir(info.GetAppCodePath()); }); result = CreateBundleDataDir(info); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to create bundle data dir, error is %{public}d", result); return result; } codePathGuard.Dismiss(); return ERR_OK; } ErrCode BaseBundleInstaller::CreateBundleCodeDir(InnerBundleInfo &info) const { auto appCodePath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_; LOG_D(BMS_TAG_INSTALLER, "create bundle dir %{public}s", appCodePath.c_str()); ErrCode result = InstalldClient::GetInstance()->CreateBundleDir(appCodePath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to create bundle dir, error is %{public}d", result); return result; } info.SetAppCodePath(appCodePath); return ERR_OK; } static void SendToStorageQuota(const std::string &bundleName, const int uid, const std::string &bundleDataDirPath, const int limitSizeMb) { #ifdef STORAGE_SERVICE_ENABLE auto systemAbilityManager = SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); if (!systemAbilityManager) { LOG_W(BMS_TAG_INSTALLER, "SendToStorageQuota, systemAbilityManager error"); return; } auto remote = systemAbilityManager->CheckSystemAbility(STORAGE_MANAGER_MANAGER_ID); if (!remote) { LOG_W(BMS_TAG_INSTALLER, "SendToStorageQuota, CheckSystemAbility error"); return; } auto proxy = iface_cast<StorageManager::IStorageManager>(remote); if (!proxy) { LOG_W(BMS_TAG_INSTALLER, "SendToStorageQuotactl, proxy get error"); return; } int err = proxy->SetBundleQuota(bundleName, uid, bundleDataDirPath, limitSizeMb); if (err != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "SendToStorageQuota, SetBundleQuota error, err=%{public}d, uid=%{public}d", err, uid); } #endif // STORAGE_SERVICE_ENABLE } void BaseBundleInstaller::PrepareBundleDirQuota(const std::string &bundleName, const int32_t uid, const std::string &bundleDataDirPath, const int32_t limitSize) const { if (limitSize == 0) { SendToStorageQuota(bundleName, uid, bundleDataDirPath, 0); return; } int32_t atomicserviceDatasizeThreshold = limitSize; #ifdef STORAGE_SERVICE_ENABLE #ifdef QUOTA_PARAM_SET_ENABLE char szAtomicDatasizeThresholdMb[THRESHOLD_VAL_LEN] = {0}; int32_t ret = GetParameter(SYSTEM_PARAM_ATOMICSERVICE_DATASIZE_THRESHOLD, "", szAtomicDatasizeThresholdMb, THRESHOLD_VAL_LEN); if (ret <= 0) { LOG_I(BMS_TAG_INSTALLER, "GetParameter failed"); } else if (strcmp(szAtomicDatasizeThresholdMb, "") != 0) { atomicserviceDatasizeThreshold = atoi(szAtomicDatasizeThresholdMb); LOG_I(BMS_TAG_INSTALLER, "InstalldQuotaUtils init atomicserviceDataThreshold mb success"); } if (atomicserviceDatasizeThreshold <= 0) { LOG_W(BMS_TAG_INSTALLER, "no need to prepare quota"); return; } #endif // QUOTA_PARAM_SET_ENABLE #endif // STORAGE_SERVICE_ENABLE SendToStorageQuota(bundleName, uid, bundleDataDirPath, atomicserviceDatasizeThreshold); } ErrCode BaseBundleInstaller::CreateBundleDataDir(InnerBundleInfo &info) const { if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "dataMgr_ is nullptr"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } InnerBundleUserInfo newInnerBundleUserInfo; if (!info.GetInnerBundleUserInfo(userId_, newInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "bundle(%{public}s) get user(%{public}d) failed", info.GetBundleName().c_str(), userId_); return ERR_APPEXECFWK_USER_NOT_EXIST; } if (!dataMgr_->GenerateUidAndGid(newInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "fail to generate uid and gid"); return ERR_APPEXECFWK_INSTALL_GENERATE_UID_ERROR; } CreateDirParam createDirParam; createDirParam.bundleName = info.GetBundleName(); createDirParam.userId = userId_; createDirParam.uid = newInnerBundleUserInfo.uid; createDirParam.gid = newInnerBundleUserInfo.uid; createDirParam.apl = info.GetAppPrivilegeLevel(); createDirParam.isPreInstallApp = info.IsPreInstallApp(); createDirParam.debug = info.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG; auto result = InstalldClient::GetInstance()->CreateBundleDataDir(createDirParam); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to create bundle data dir, error is %{public}d", result); return result; } std::string bundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::BASE + info.GetBundleName(); if (info.GetApplicationBundleType() == BundleType::ATOMIC_SERVICE) { PrepareBundleDirQuota(info.GetBundleName(), newInnerBundleUserInfo.uid, bundleDataDir, ATOMIC_SERVICE_DATASIZE_THRESHOLD_MB_PRESET); } else { PrepareBundleDirQuota(info.GetBundleName(), newInnerBundleUserInfo.uid, bundleDataDir, 0); } if (info.GetIsNewVersion()) { int32_t gid = (info.GetAppProvisionType() == Constants::APP_PROVISION_TYPE_DEBUG) ? GetIntParameter(BMS_KEY_SHELL_UID, ServiceConstants::SHELL_UID) : newInnerBundleUserInfo.uid; result = CreateArkProfile( info.GetBundleName(), userId_, newInnerBundleUserInfo.uid, gid); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to create ark profile, error is %{public}d", result); return result; } } result = CreateShaderCache(info.GetBundleName(), createDirParam.uid, createDirParam.gid); if (result != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "fail to create shader cache, error is %{public}d", result); } CreateCloudShader(info.GetBundleName(), createDirParam.uid, createDirParam.gid); // create asan log directory when asanEnabled is true // In update condition, delete asan log directory when asanEnabled is false if directory is exist if ((result = ProcessAsanDirectory(info)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "process asan log directory failed"); return result; } std::string dataBaseDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] + ServiceConstants::DATABASE + info.GetBundleName(); info.SetAppDataBaseDir(dataBaseDir); info.AddInnerBundleUserInfo(newInnerBundleUserInfo); return ERR_OK; } ErrCode BaseBundleInstaller::CreateDataGroupDirs( const std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes, const InnerBundleInfo &oldInfo) { if (dataMgr_ == nullptr) { LOG_W(BMS_TAG_INSTALLER, "dataMgr_ null"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (hapVerifyRes.empty()) { LOG_W(BMS_TAG_INSTALLER, "hapVerifyRes empty"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } std::unordered_set<std::string> groupIds; GetDataGroupIds(hapVerifyRes, groupIds); dataMgr_->GenerateDataGroupInfos(bundleName_, groupIds, userId_); return ERR_OK; } void BaseBundleInstaller::RemoveOldGroupDirs(const InnerBundleInfo &oldInfo) { if (dataMgr_ == nullptr) { LOG_W(BMS_TAG_INSTALLER, "dataMgr_ null"); return; } dataMgr_->RemoveOldGroupDirs(oldInfo); } std::vector<std::string> BaseBundleInstaller::GenerateScreenLockProtectionDir(const std::string &bundleName) const { std::vector<std::string> dirs; if (bundleName.empty()) { LOG_E(BMS_TAG_INSTALLER, "bundleName is empty"); return dirs; } dirs.emplace_back(ServiceConstants::SCREEN_LOCK_FILE_DATA_PATH + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::BASE + bundleName); dirs.emplace_back(ServiceConstants::SCREEN_LOCK_FILE_DATA_PATH + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::DATABASE + bundleName); return dirs; } bool BaseBundleInstaller::SetEncryptionDirPolicy(InnerBundleInfo &info) { InnerBundleUserInfo userInfo; if (!InitDataMgr()) { return false; } if (!info.GetInnerBundleUserInfo(userId_, userInfo)) { LOG_E(BMS_TAG_INSTALLER, "%{public}s get user %{public}d failed", info.GetBundleName().c_str(), userId_); return false; } if (!userInfo.keyId.empty()) { LOG_I(BMS_TAG_INSTALLER, "keyId is not empty, bundleName: %{public}s", info.GetBundleName().c_str()); return true; } int32_t uid = userInfo.uid; std::string bundleName = info.GetBundleName(); std::string keyId = ""; auto result = InstalldClient::GetInstance()->SetEncryptionPolicy(uid, bundleName, userId_, keyId); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "SetEncryptionPolicy failed"); } LOG_D(BMS_TAG_INSTALLER, "%{public}s, keyId: %{public}s", bundleName.c_str(), keyId.c_str()); info.SetkeyId(userId_, keyId); if (!dataMgr_->UpdateInnerBundleInfo(info, false)) { LOG_E(BMS_TAG_INSTALLER, "save keyId failed"); return false; } return result == ERR_OK; } void BaseBundleInstaller::CreateScreenLockProtectionExistDirs(const InnerBundleInfo &info, const std::string &dir) { LOG_I(BMS_TAG_INSTALLER, "CreateScreenLockProtectionExistDirs start"); auto pos = dir.rfind(ServiceConstants::PATH_SEPARATOR); if (pos == std::string::npos || !BundleUtil::IsExistDir(dir.substr(0, pos))) { LOG_E(BMS_TAG_INSTALLER, "parent dir(%{public}s) missing: el5", dir.substr(0, pos).c_str()); return; } InnerBundleUserInfo newInnerBundleUserInfo; if (!info.GetInnerBundleUserInfo(userId_, newInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "bundle(%{public}s) get user(%{public}d) failed", info.GetBundleName().c_str(), userId_); return; } int32_t mode = S_IRWXU; int32_t gid = newInnerBundleUserInfo.uid; if (dir.find(ServiceConstants::DATABASE) != std::string::npos) { mode = S_IRWXU | S_IRWXG | S_ISGID; gid = ServiceConstants::DATABASE_DIR_GID; } if (InstalldClient::GetInstance()->Mkdir(dir, mode, newInnerBundleUserInfo.uid, gid) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "create Screen Lock Protection dir %{public}s failed", dir.c_str()); } ErrCode result = InstalldClient::GetInstance()->SetDirApl( dir, info.GetBundleName(), info.GetAppPrivilegeLevel(), info.IsPreInstallApp(), info.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG); if (result != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "fail to SetDirApl dir %{public}s, error is %{public}d", dir.c_str(), result); } } void BaseBundleInstaller::CreateScreenLockProtectionDir() { LOG_I(BMS_TAG_INSTALLER, "CreateScreenLockProtectionDir start"); if (!InitDataMgr()) { LOG_E(BMS_TAG_INSTALLER, "init failed"); return; } InnerBundleInfo info; if (!dataMgr_->FetchInnerBundleInfo(bundleName_, info)) { LOG_E(BMS_TAG_INSTALLER, "get failed"); return; } std::vector<std::string> dirs = GenerateScreenLockProtectionDir(bundleName_); bool hasPermission = false; std::vector<RequestPermission> reqPermissions = info.GetAllRequestPermissions(); auto it = std::find_if(reqPermissions.begin(), reqPermissions.end(), [](const RequestPermission& permission) { return permission.name == PERMISSION_PROTECT_SCREEN_LOCK_DATA; }); if (it != reqPermissions.end()) { hasPermission = true; } if (!hasPermission) { LOG_I(BMS_TAG_INSTALLER, "no protection permission found, remove dirs"); for (const std::string &dir : dirs) { if (InstalldClient::GetInstance()->RemoveDir(dir) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "remove Screen Lock Protection dir %{public}s failed", dir.c_str()); } } return; } bool dirExist = false; for (const std::string &dir : dirs) { if (InstalldClient::GetInstance()->IsExistDir(dir, dirExist) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "check if dir existed failed"); return; } if (!dirExist) { LOG_D(BMS_TAG_INSTALLER, "ScreenLockProtectionDir: %{public}s need to be created", dir.c_str()); CreateScreenLockProtectionExistDirs(info, dir); } } if (!dirExist) { if (!SetEncryptionDirPolicy(info)) { LOG_E(BMS_TAG_INSTALLER, "Encryption failed dir"); } } } void BaseBundleInstaller::DeleteEncryptionKeyId(const InnerBundleInfo &oldInfo) const { if (oldInfo.GetBundleName().empty()) { LOG_W(BMS_TAG_INSTALLER, "bundleName is empty"); return; } std::vector<std::string> dirs = GenerateScreenLockProtectionDir(oldInfo.GetBundleName()); for (const std::string &dir : dirs) { if (InstalldClient::GetInstance()->RemoveDir(dir) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "remove Screen Lock Protection dir %{public}s failed", dir.c_str()); } } if (InstalldClient::GetInstance()->DeleteEncryptionKeyId(oldInfo.GetBundleName(), userId_) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "delete encryption key id failed"); } } void BaseBundleInstaller::DeleteScreenLockProtectionDir(const std::string bundleName) const { std::vector<std::string> dirs = GenerateScreenLockProtectionDir(bundleName); for (const std::string &dir : dirs) { auto result = InstalldClient::GetInstance()->RemoveDir(dir); if (result != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "remove Screen Lock Protection dir %{public}s failed", dir.c_str()); } } } void BaseBundleInstaller::DeleteGroupDirsForException(const InnerBundleInfo &oldInfo) const { if (dataMgr_ == nullptr) { LOG_W(BMS_TAG_INSTALLER, "dataMgr_ null"); return; } dataMgr_->DeleteGroupDirsForException(oldInfo, userId_); } ErrCode BaseBundleInstaller::RemoveDataGroupDirs(const std::string &bundleName, int32_t userId, bool isKeepData) const { if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "dataMgr_ is nullptr"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } dataMgr_->DeleteUserDataGroupInfos(bundleName, userId, isKeepData); return ERR_OK; } ErrCode BaseBundleInstaller::CreateArkProfile( const std::string &bundleName, int32_t userId, int32_t uid, int32_t gid) const { ErrCode result = DeleteArkProfile(bundleName, userId); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to removeArkProfile, error is %{public}d", result); return result; } std::string arkProfilePath; arkProfilePath.append(ARK_PROFILE_PATH).append(std::to_string(userId)) .append(ServiceConstants::PATH_SEPARATOR).append(bundleName); LOG_D(BMS_TAG_INSTALLER, "CreateArkProfile %{public}s", arkProfilePath.c_str()); int32_t mode = (uid == gid) ? S_IRWXU : (S_IRWXU | S_IRGRP | S_IXGRP); return InstalldClient::GetInstance()->Mkdir(arkProfilePath, mode, uid, gid); } ErrCode BaseBundleInstaller::DeleteArkProfile(const std::string &bundleName, int32_t userId) const { std::string arkProfilePath; arkProfilePath.append(ARK_PROFILE_PATH).append(std::to_string(userId)) .append(ServiceConstants::PATH_SEPARATOR).append(bundleName); LOG_D(BMS_TAG_INSTALLER, "DeleteArkProfile %{public}s", arkProfilePath.c_str()); return InstalldClient::GetInstance()->RemoveDir(arkProfilePath); } ErrCode BaseBundleInstaller::ExtractModule(InnerBundleInfo &info, const std::string &modulePath) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); // need remove modulePath, make sure the directory is empty if (InstalldClient::GetInstance()->RemoveDir(modulePath) != ERR_OK) { APP_LOGW("remove dir %{public}s failed", modulePath.c_str()); } auto result = InnerProcessNativeLibs(info, modulePath); CHECK_RESULT(result, "fail to InnerProcessNativeLibs, error is %{public}d"); result = ExtractArkNativeFile(info, modulePath); CHECK_RESULT(result, "fail to extractArkNativeFile, error is %{public}d"); if (info.GetIsNewVersion()) { result = CopyPgoFileToArkProfileDir(modulePackage_, modulePath_, info.GetBundleName(), userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to CopyPgoFileToArkProfileDir, error is %{public}d", result); return result; } } ExtractResourceFiles(info, modulePath); result = ExtractResFileDir(modulePath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to ExtractResFileDir, error is %{public}d", result); return result; } if (auto hnpPackageInfos = info.GetInnerModuleInfoHnpInfo(info.GetCurModuleName())) { std::map<std::string, std::string> hnpPackageInfoMap; std::stringstream hnpPackageInfoString; for (const auto &hnp_packageInfo : *hnpPackageInfos) { hnpPackageInfoMap[hnp_packageInfo.package] = hnp_packageInfo.type; } for (const auto &hnpPackageKV : hnpPackageInfoMap) { hnpPackageInfoString << "{" << hnpPackageKV.first << ":" << hnpPackageKV.second << "}"; } std::string cpuAbi = info.GetCpuAbi(); result = ExtractHnpFileDir(cpuAbi, hnpPackageInfoString.str(), modulePath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to ExtractHnpsFileDir, error is %{public}d", result); return result; } } if (info.IsPreInstallApp()) { info.SetModuleHapPath(modulePath_); } else { info.SetModuleHapPath(GetHapPath(info)); } auto moduleDir = info.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + info.GetCurrentModulePackage(); info.AddModuleSrcDir(moduleDir); info.AddModuleResPath(moduleDir); info.AddModuleHnpsPath(modulePath); return ERR_OK; } void BaseBundleInstaller::ExtractResourceFiles(const InnerBundleInfo &info, const std::string &targetPath) const { LOG_D(BMS_TAG_INSTALLER, "ExtractResourceFiles begin"); int32_t apiTargetVersion = info.GetBaseApplicationInfo().apiTargetVersion; if (info.IsPreInstallApp() || apiTargetVersion > ServiceConstants::API_VERSION_NINE) { LOG_D(BMS_TAG_INSTALLER, "no need to extract resource files"); return; } LOG_D(BMS_TAG_INSTALLER, "apiTargetVersion is %{public}d, extract resource files", apiTargetVersion); ExtractParam extractParam; extractParam.srcPath = modulePath_; extractParam.targetPath = targetPath + ServiceConstants::PATH_SEPARATOR; extractParam.extractFileType = ExtractFileType::RESOURCE; ErrCode ret = InstalldClient::GetInstance()->ExtractFiles(extractParam); LOG_D(BMS_TAG_INSTALLER, "ExtractResourceFiles ret : %{public}d", ret); } ErrCode BaseBundleInstaller::ExtractResFileDir(const std::string &modulePath) const { LOG_D(BMS_TAG_INSTALLER, "ExtractResFileDir begin"); ExtractParam extractParam; extractParam.srcPath = modulePath_; extractParam.targetPath = modulePath + ServiceConstants::PATH_SEPARATOR + ServiceConstants::RES_FILE_PATH; LOG_D(BMS_TAG_INSTALLER, "ExtractResFileDir targetPath: %{public}s", extractParam.targetPath.c_str()); extractParam.extractFileType = ExtractFileType::RES_FILE; ErrCode ret = InstalldClient::GetInstance()->ExtractFiles(extractParam); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "ExtractResFileDir ExtractFiles failed, error is %{public}d", ret); return ret; } LOG_D(BMS_TAG_INSTALLER, "ExtractResFileDir end"); return ret; } ErrCode BaseBundleInstaller::ExtractHnpFileDir(const std::string &cpuAbi, const std::string &hnpPackageInfoString, const std::string &modulePath) const { LOG_D(BMS_TAG_INSTALLER, "ExtractHnpFileDir begin"); ExtractParam extractParam; extractParam.srcPath = modulePath_; extractParam.targetPath = modulePath + ServiceConstants::PATH_SEPARATOR + ServiceConstants::HNPS_FILE_PATH; if (ServiceConstants::ABI_MAP.find(cpuAbi) == ServiceConstants::ABI_MAP.end()) { LOG_E(BMS_TAG_INSTALLER, "No support %{public}s abi", cpuAbi.c_str()); return ERR_APPEXECFWK_NATIVE_HNP_EXTRACT_FAILED; } extractParam.cpuAbi = cpuAbi; LOG_D(BMS_TAG_INSTALLER, "ExtractHnpFileDir targetPath: %{public}s", extractParam.targetPath.c_str()); extractParam.extractFileType = ExtractFileType::HNPS_FILE; ErrCode ret = InstalldClient::GetInstance()->ExtractHnpFiles(hnpPackageInfoString, extractParam); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "ExtractHnpFileDir ExtractFiles failed, error is %{public}d", ret); return ret; } LOG_D(BMS_TAG_INSTALLER, "ExtractHnpFileDir end"); return ret; } ErrCode BaseBundleInstaller::ExtractArkNativeFile(InnerBundleInfo &info, const std::string &modulePath) { if (!info.GetArkNativeFilePath().empty()) { LOG_D(BMS_TAG_INSTALLER, "Module %{public}s no need to extract an", modulePackage_.c_str()); return ERR_OK; } std::string cpuAbi = info.GetArkNativeFileAbi(); if (cpuAbi.empty()) { LOG_D(BMS_TAG_INSTALLER, "Module %{public}s no native file", modulePackage_.c_str()); return ERR_OK; } if (ServiceConstants::ABI_MAP.find(cpuAbi) == ServiceConstants::ABI_MAP.end()) { LOG_E(BMS_TAG_INSTALLER, "No support %{public}s abi", cpuAbi.c_str()); return ERR_APPEXECFWK_PARSE_AN_FAILED; } std::string arkNativeFilePath; arkNativeFilePath.append(ServiceConstants::ABI_MAP.at(cpuAbi)).append(ServiceConstants::PATH_SEPARATOR); std::string targetPath; targetPath.append(ARK_CACHE_PATH).append(info.GetBundleName()) .append(ServiceConstants::PATH_SEPARATOR).append(arkNativeFilePath); LOG_D(BMS_TAG_INSTALLER, "Begin extract an modulePath: %{public}s targetPath: %{public}s cpuAbi: %{public}s", modulePath.c_str(), targetPath.c_str(), cpuAbi.c_str()); ExtractParam extractParam; extractParam.srcPath = modulePath_; extractParam.targetPath = targetPath; extractParam.cpuAbi = cpuAbi; extractParam.extractFileType = ExtractFileType::AN; auto result = InstalldClient::GetInstance()->ExtractFiles(extractParam); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "extract files failed, error is %{public}d", result); return result; } info.SetArkNativeFilePath(arkNativeFilePath); return ERR_OK; } ErrCode BaseBundleInstaller::ExtractAllArkProfileFile(const InnerBundleInfo &oldInfo, bool checkRepeat) const { if (!oldInfo.GetIsNewVersion()) { return ERR_OK; } std::string bundleName = oldInfo.GetBundleName(); LOG_I(BMS_TAG_INSTALLER, "Begin to ExtractAllArkProfileFile, bundleName : %{public}s", bundleName.c_str()); const auto &innerModuleInfos = oldInfo.GetInnerModuleInfos(); for (auto iter = innerModuleInfos.cbegin(); iter != innerModuleInfos.cend(); ++iter) { if (checkRepeat && installedModules_.find(iter->first) != installedModules_.end()) { continue; } ErrCode ret = CopyPgoFileToArkProfileDir(iter->second.name, iter->second.hapPath, bundleName, userId_); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to CopyPgoFileToArkProfileDir, error is %{public}d", ret); return ret; } } LOG_D(BMS_TAG_INSTALLER, "ExtractAllArkProfileFile succeed, bundleName : %{public}s", bundleName.c_str()); return ERR_OK; } ErrCode BaseBundleInstaller::CopyPgoFileToArkProfileDir( const std::string &moduleName, const std::string &modulePath, const std::string &bundleName, int32_t userId) const { auto it = pgoParams_.find(moduleName); if (it != pgoParams_.end()) { return CopyPgoFile(moduleName, it->second, bundleName, userId); } return ExtractArkProfileFile(modulePath, bundleName, userId); } ErrCode BaseBundleInstaller::CopyPgoFile( const std::string &moduleName, const std::string &pgoPath, const std::string &bundleName, int32_t userId) const { std::string targetPath; targetPath.append(ARK_PROFILE_PATH).append(std::to_string(userId)) .append(ServiceConstants::PATH_SEPARATOR).append(bundleName) .append(ServiceConstants::PATH_SEPARATOR).append(moduleName) .append(ServiceConstants::AP_SUFFIX); if (InstalldClient::GetInstance()->CopyFile(pgoPath, targetPath) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "copy file from %{public}s to %{public}s failed", pgoPath.c_str(), targetPath.c_str()); return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED; } return ERR_OK; } ErrCode BaseBundleInstaller::ExtractArkProfileFile( const std::string &modulePath, const std::string &bundleName, int32_t userId) const { std::string targetPath; targetPath.append(ARK_PROFILE_PATH).append(std::to_string(userId)) .append(ServiceConstants::PATH_SEPARATOR).append(bundleName); LOG_D(BMS_TAG_INSTALLER, "Begin to extract ap file, modulePath : %{public}s, targetPath : %{public}s", modulePath.c_str(), targetPath.c_str()); ExtractParam extractParam; extractParam.srcPath = modulePath; extractParam.targetPath = targetPath; extractParam.cpuAbi = Constants::EMPTY_STRING; extractParam.extractFileType = ExtractFileType::AP; auto result = InstalldClient::GetInstance()->ExtractFiles(extractParam); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "extract ap files failed, error is %{public}d", result); return result; } return ERR_OK; } ErrCode BaseBundleInstaller::DeleteOldArkNativeFile(const InnerBundleInfo &oldInfo) { std::string targetPath; targetPath.append(ARK_CACHE_PATH).append(oldInfo.GetBundleName()); auto result = InstalldClient::GetInstance()->RemoveDir(targetPath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove arkNativeFilePath %{public}s, error is %{public}d", targetPath.c_str(), result); } return result; } ErrCode BaseBundleInstaller::RemoveBundleAndDataDir(const InnerBundleInfo &info, bool isKeepData, const bool async) { ErrCode result = ERR_OK; if (!isKeepData) { result = RemoveBundleDataDir(info, false, async); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove bundleData dir %{public}s, error is %{public}d", info.GetBundleName().c_str(), result); return result; } } // remove bundle dir result = RemoveBundleCodeDir(info); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove dir fail %{public}s error %{public}d", info.GetAppCodePath().c_str(), result); return result; } return result; } ErrCode BaseBundleInstaller::RemoveBundleCodeDir(const InnerBundleInfo &info) const { auto result = InstalldClient::GetInstance()->RemoveDir(info.GetAppCodePath()); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove bundle code dir %{public}s, error is %{public}d", info.GetAppCodePath().c_str(), result); } return result; } ErrCode BaseBundleInstaller::RemoveBundleDataDir( const InnerBundleInfo &info, bool forException, const bool async) { ErrCode result = InstalldClient::GetInstance()->RemoveBundleDataDir(info.GetBundleName(), userId_, info.GetApplicationBundleType() == BundleType::ATOMIC_SERVICE, async); if (result == ERR_APPEXECFWK_INSTALLD_REMOVE_DIR_FAILED) { LOG_W(BMS_TAG_INSTALLER, "RemoveBundleDataDir failed %{public}d", result); InstallParam installParam; SendBundleSystemEvent( info.GetBundleName(), BundleEventType::UNINSTALL, installParam, sysEventInfo_.preBundleScene, ERR_APPEXECFWK_INSTALLD_REMOVE_DIR_FAILED); } if (forException) { result = InstalldClient::GetInstance()->RemoveExtensionDir(userId_, createExtensionDirs_); } else { auto extensionDirs = info.GetAllExtensionDirs(); result = InstalldClient::GetInstance()->RemoveExtensionDir(userId_, extensionDirs); } if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove bundle extension dir, error is %{public}d", result); } return ERR_OK; } void BaseBundleInstaller::RemoveEmptyDirs(const std::unordered_map<std::string, InnerBundleInfo> &infos) const { for (const auto &item : infos) { const InnerBundleInfo &info = item.second; std::string moduleDir = info.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + info.GetCurrentModulePackage(); bool isDirEmpty = false; InstalldClient::GetInstance()->IsDirEmpty(moduleDir, isDirEmpty); if (isDirEmpty) { LOG_D(BMS_TAG_INSTALLER, "remove empty dir : %{public}s", moduleDir.c_str()); InstalldClient::GetInstance()->RemoveDir(moduleDir); } } } std::string BaseBundleInstaller::GetModuleNames(const std::unordered_map<std::string, InnerBundleInfo> &infos) const { if (infos.empty()) { LOG_E(BMS_TAG_INSTALLER, "module info is empty"); return Constants::EMPTY_STRING; } std::string moduleNames; for (const auto &item : infos) { moduleNames.append(item.second.GetCurrentModulePackage()).append(ServiceConstants::MODULE_NAME_SEPARATOR); } moduleNames.pop_back(); LOG_D(BMS_TAG_INSTALLER, "moduleNames : %{public}s", moduleNames.c_str()); return moduleNames; } ErrCode BaseBundleInstaller::RemoveModuleAndDataDir( const InnerBundleInfo &info, const std::string &modulePackage, int32_t userId, bool isKeepData) const { LOG_D(BMS_TAG_INSTALLER, "RemoveModuleAndDataDir with package name %{public}s", modulePackage.c_str()); auto moduleDir = info.GetModuleDir(modulePackage); auto result = RemoveModuleDir(moduleDir); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove module dir, error is %{public}d", result); return result; } // remove hap result = RemoveModuleDir(GetHapPath(info, info.GetModuleName(modulePackage))); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove module hap, error is %{public}d", result); return result; } LOG_D(BMS_TAG_INSTALLER, "RemoveModuleAndDataDir successfully"); return ERR_OK; } ErrCode BaseBundleInstaller::RemoveModuleDir(const std::string &modulePath) const { LOG_D(BMS_TAG_INSTALLER, "module dir %{public}s to be removed", modulePath.c_str()); return InstalldClient::GetInstance()->RemoveDir(modulePath); } ErrCode BaseBundleInstaller::ExtractModuleFiles(const InnerBundleInfo &info, const std::string &modulePath, const std::string &targetSoPath, const std::string &cpuAbi) { LOG_D(BMS_TAG_INSTALLER, "extract module to %{public}s", modulePath.c_str()); auto result = InstalldClient::GetInstance()->ExtractModuleFiles(modulePath_, modulePath, targetSoPath, cpuAbi); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "extract module files failed, error is %{public}d", result); return result; } return ERR_OK; } ErrCode BaseBundleInstaller::RenameModuleDir(const InnerBundleInfo &info) const { auto moduleDir = info.GetAppCodePath() + ServiceConstants::PATH_SEPARATOR + info.GetCurrentModulePackage(); LOG_D(BMS_TAG_INSTALLER, "rename module to %{public}s", moduleDir.c_str()); auto result = InstalldClient::GetInstance()->RenameModuleDir(moduleDir + ServiceConstants::TMP_SUFFIX, moduleDir); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "rename module dir failed, error is %{public}d", result); return result; } return ERR_OK; } ErrCode BaseBundleInstaller::CheckSysCap(const std::vector<std::string> &bundlePaths) { return bundleInstallChecker_->CheckSysCap(bundlePaths); } ErrCode BaseBundleInstaller::CheckMultipleHapsSignInfo( const std::vector<std::string> &bundlePaths, const InstallParam &installParam, std::vector<Security::Verify::HapVerifyResult>& hapVerifyRes) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); return bundleInstallChecker_->CheckMultipleHapsSignInfo(bundlePaths, hapVerifyRes); } ErrCode BaseBundleInstaller::CheckShellInstall(std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes) { if (sysEventInfo_.callingUid != ServiceConstants::SHELL_UID || hapVerifyRes.empty()) { return ERR_OK; } Security::Verify::ProvisionInfo provisionInfo = hapVerifyRes.begin()->GetProvisionInfo(); if (provisionInfo.distributionType == Security::Verify::AppDistType::APP_GALLERY && provisionInfo.type == Security::Verify::ProvisionType::RELEASE && !IsRdDevice()) { return ERR_APPEXECFWK_INSTALL_RELEASE_BUNDLE_NOT_ALLOWED_FOR_SHELL; } return ERR_OK; } ErrCode BaseBundleInstaller::ParseHapFiles( const std::vector<std::string> &bundlePaths, const InstallParam &installParam, const Constants::AppType appType, std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes, std::unordered_map<std::string, InnerBundleInfo> &infos) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); InstallCheckParam checkParam; checkParam.isPreInstallApp = installParam.isPreInstallApp; checkParam.crowdtestDeadline = installParam.crowdtestDeadline; checkParam.specifiedDistributionType = installParam.specifiedDistributionType; checkParam.appType = appType; checkParam.removable = installParam.removable; ErrCode ret = bundleInstallChecker_->ParseHapFiles( bundlePaths, checkParam, hapVerifyRes, infos); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "parse hap file failed due to errorCode : %{public}d", ret); return ret; } if (!infos.empty()) { bundleType_ = infos.begin()->second.GetApplicationBundleType(); } GenerateOdid(infos, hapVerifyRes); isContainEntry_ = bundleInstallChecker_->IsContainEntry(); /* At this place, hapVerifyRes cannot be empty and unnecessary to check it */ isEnterpriseBundle_ = bundleInstallChecker_->CheckEnterpriseBundle(hapVerifyRes[0]); isInternaltestingBundle_ = bundleInstallChecker_->CheckInternaltestingBundle(hapVerifyRes[0]); appIdentifier_ = (hapVerifyRes[0].GetProvisionInfo().type == Security::Verify::ProvisionType::DEBUG) ? DEBUG_APP_IDENTIFIER : hapVerifyRes[0].GetProvisionInfo().bundleInfo.appIdentifier; SetAppDistributionType(infos); UpdateExtensionSandboxInfo(infos, hapVerifyRes); SetInstallSourceToAppInfo(infos, installParam); return ret; } void BaseBundleInstaller::UpdateExtensionSandboxInfo(std::unordered_map<std::string, InnerBundleInfo> &newInfos, const std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes) { if (newInfos.empty() || hapVerifyRes.empty()) { LOG_E(BMS_TAG_INSTALLER, "innerBundleInfo map or hapVerifyRes is empty"); return; } Security::Verify::ProvisionInfo provisionInfo = hapVerifyRes.begin()->GetProvisionInfo(); auto dataGroupGids = provisionInfo.bundleInfo.dataGroupIds; std::vector<std::string> typeList; ErrCode res = InstalldClient::GetInstance()->GetExtensionSandboxTypeList(typeList); if (res != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "GetExtensionSandboxTypeList failed %{public}d", res); } for (auto &item : newInfos) { item.second.UpdateExtensionSandboxInfo(typeList); auto innerBundleInfo = item.second; auto extensionInfoMap = innerBundleInfo.GetInnerExtensionInfos(); for (auto iter = extensionInfoMap.begin(); iter != extensionInfoMap.end(); iter++) { if (!iter->second.needCreateSandbox) { continue; } std::string key = iter->second.bundleName + "." + iter->second.moduleName + "." + iter->second.name; std::vector<std::string> validGroupIds; GetValidDataGroupIds(iter->second.dataGroupIds, dataGroupGids, validGroupIds); LOG_I(BMS_TAG_INSTALLER, "extension %{public}s need to create dir on user %{public}d", iter->second.name.c_str(), userId_); item.second.UpdateExtensionDataGroupInfo(key, validGroupIds); } } } void BaseBundleInstaller::GetValidDataGroupIds(const std::vector<std::string> &extensionDataGroupIds, const std::vector<std::string> &bundleDataGroupIds, std::vector<std::string> &validGroupIds) const { for (const std::string &dataGroupId : extensionDataGroupIds) { if (std::find(bundleDataGroupIds.begin(), bundleDataGroupIds.end(), dataGroupId) != bundleDataGroupIds.end()) { validGroupIds.emplace_back(dataGroupId); } LOG_I(BMS_TAG_INSTALLER, "dataGroupId %{public}s is invalid", dataGroupId.c_str()); } } void BaseBundleInstaller::GetExtensionDirsChange(std::unordered_map<std::string, InnerBundleInfo> &newInfos, const InnerBundleInfo &oldInfo) { GetCreateExtensionDirs(newInfos); GetRemoveExtensionDirs(newInfos, oldInfo); } void BaseBundleInstaller::CreateExtensionDataDir(InnerBundleInfo &info) const { if (createExtensionDirs_.empty()) { return; } InnerBundleUserInfo newInnerBundleUserInfo; if (!info.GetInnerBundleUserInfo(userId_, newInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "bundle(%{public}s) get user(%{public}d) failed", info.GetBundleName().c_str(), userId_); return; } CreateDirParam createDirParam; createDirParam.bundleName = info.GetBundleName(); createDirParam.userId = userId_; createDirParam.uid = newInnerBundleUserInfo.uid; createDirParam.gid = newInnerBundleUserInfo.uid; createDirParam.apl = info.GetAppPrivilegeLevel(); createDirParam.isPreInstallApp = info.IsPreInstallApp(); createDirParam.debug = info.GetBaseApplicationInfo().appProvisionType == Constants::APP_PROVISION_TYPE_DEBUG; createDirParam.extensionDirs.assign(createExtensionDirs_.begin(), createExtensionDirs_.end()); auto result = InstalldClient::GetInstance()->CreateExtensionDataDir(createDirParam); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to create bundle extension data dir, error is %{public}d", result); } } void BaseBundleInstaller::GenerateNewUserDataGroupInfos(InnerBundleInfo &info) const { if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "dataMgr_ is nullptr"); return; } dataMgr_->GenerateNewUserDataGroupInfos(info.GetBundleName(), userId_); } void BaseBundleInstaller::GetCreateExtensionDirs(std::unordered_map<std::string, InnerBundleInfo> &newInfos) { for (auto &item : newInfos) { auto innerBundleInfo = item.second; auto moduleName = innerBundleInfo.GetCurModuleName(); auto extensionDirSet = innerBundleInfo.GetAllExtensionDirsInSpecifiedModule(moduleName); for (const std::string &dir : extensionDirSet) { newExtensionDirs_.emplace_back(dir); bool dirExist = false; auto result = InstalldClient::GetInstance()->IsExistExtensionDir(userId_, dir, dirExist); if (result != ERR_OK || !dirExist) { LOG_I(BMS_TAG_INSTALLER, "dir: %{public}s need to be created", dir.c_str()); createExtensionDirs_.emplace_back(dir); } } } } void BaseBundleInstaller::GetRemoveExtensionDirs( std::unordered_map<std::string, InnerBundleInfo> &newInfos, const InnerBundleInfo &oldInfo) { if (newInfos.empty()) { LOG_E(BMS_TAG_INSTALLER, "newInfos is empty"); return; } if (!isAppExist_) { // Install it for the first time return; } std::vector<std::string> oldModuleNames; const auto &innerBundleInfo = newInfos.begin()->second; oldInfo.GetModuleNames(oldModuleNames); if (innerBundleInfo.GetVersionCode() > oldInfo.GetVersionCode()) { std::set<std::string> newModules; for (const auto &item : newInfos) { std::vector<std::string> curModules; item.second.GetModuleNames(curModules); newModules.insert(curModules.begin(), curModules.end()); } for (const std::string &oldModuleName : oldModuleNames) { if (newModules.find(oldModuleName) == newModules.end()) { // module does not exist in the later version, so it's extension dir needs to be removed const auto oldExtensionDirs = oldInfo.GetAllExtensionDirsInSpecifiedModule(oldModuleName); LOG_I(BMS_TAG_INSTALLER, "Dirs size %{public}zu need to be removed", oldExtensionDirs.size()); std::copy(oldExtensionDirs.begin(), oldExtensionDirs.end(), std::back_inserter(removeExtensionDirs_)); } } } for (const auto& item : newInfos) { std::string modulePackage = item.second.GetCurModuleName(); if (!oldInfo.FindModule(modulePackage)) { // install a new module continue; } // update a existed module auto oldDirList = oldInfo.GetAllExtensionDirsInSpecifiedModule( oldInfo.GetModuleNameByPackage(modulePackage)); for (const std::string &oldDir : oldDirList) { if (std::find(newExtensionDirs_.begin(), newExtensionDirs_.end(), oldDir) == newExtensionDirs_.end()) { LOG_I(BMS_TAG_INSTALLER, "dir %{public}s need to be removed", oldDir.c_str()); removeExtensionDirs_.emplace_back(oldDir); } } } } void BaseBundleInstaller::RemoveCreatedExtensionDirsForException() const { if (createExtensionDirs_.empty()) { LOG_I(BMS_TAG_INSTALLER, "no need to remove extension sandbox dir"); return; } if (InstalldClient::GetInstance()->RemoveExtensionDir(userId_, createExtensionDirs_) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "remove created extension sandbox dir failed"); } } void BaseBundleInstaller::RemoveOldExtensionDirs() const { if (removeExtensionDirs_.empty()) { LOG_D(BMS_TAG_INSTALLER, "no need to remove old extension sandbox dir"); return; } auto result = InstalldClient::GetInstance()->RemoveExtensionDir(userId_, removeExtensionDirs_); if (result != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "remove old extension sandbox dirfailed"); } } std::string BaseBundleInstaller::GetInstallSource(const InstallParam &installParam) const { if (installParam.isPreInstallApp) { return INSTALL_SOURCE_PREINSTALL; } std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr(); if (dataMgr == nullptr) { LOG_I(BMS_TAG_INSTALLER, "dataMgr is nullptr return unknown"); return INSTALL_SOURCE_UNKNOWN; } std::string callingBundleName; ErrCode ret = dataMgr->GetNameForUid(sysEventInfo_.callingUid, callingBundleName); if (ret != ERR_OK) { LOG_I(BMS_TAG_INSTALLER, "get bundle name failed return unknown"); return INSTALL_SOURCE_UNKNOWN; } return callingBundleName; } void BaseBundleInstaller::SetInstallSourceToAppInfo(std::unordered_map<std::string, InnerBundleInfo> &infos, const InstallParam &installParam) const { std::string installSource = GetInstallSource(installParam); for (auto &info : infos) { info.second.SetInstallSource(installSource); } } void BaseBundleInstaller::SetApplicationFlagsForPreinstallSource( std::unordered_map<std::string, InnerBundleInfo> &infos, const InstallParam &installParam) const { std::string installSource = GetInstallSource(installParam); for (auto &info : infos) { info.second.SetApplicationFlags(installParam.preinstallSourceFlag); } } void BaseBundleInstaller::SetAppDistributionType(const std::unordered_map<std::string, InnerBundleInfo> &infos) { if (infos.empty()) { LOG_E(BMS_TAG_INSTALLER, "infos is empty"); return; } appDistributionType_ = infos.begin()->second.GetAppDistributionType(); } void BaseBundleInstaller::GenerateOdid( std::unordered_map<std::string, InnerBundleInfo> &infos, const std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes) const { if (hapVerifyRes.size() < infos.size() || infos.empty()) { LOG_E(BMS_TAG_INSTALLER, "hapVerifyRes size less than infos size or infos is empty"); return; } std::shared_ptr<BundleDataMgr> dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr(); if (dataMgr == nullptr) { LOG_E(BMS_TAG_INSTALLER, "Get dataMgr shared_ptr nullptr"); return; } std::string developerId = hapVerifyRes[0].GetProvisionInfo().bundleInfo.developerId; if (developerId.empty()) { developerId = hapVerifyRes[0].GetProvisionInfo().bundleInfo.bundleName; } std::string odid; dataMgr->GenerateOdid(developerId, odid); for (auto &item : infos) { item.second.UpdateOdid(developerId, odid); } } void BaseBundleInstaller::GetDataGroupIds(const std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes, std::unordered_set<std::string> &groupIds) { for (size_t i = 0; i < hapVerifyRes.size(); i++) { Security::Verify::ProvisionInfo provisionInfo = hapVerifyRes[i].GetProvisionInfo(); auto dataGroupIds = provisionInfo.bundleInfo.dataGroupIds; if (dataGroupIds.empty()) { continue; } for (const std::string &id : dataGroupIds) { groupIds.insert(id); } } } ErrCode BaseBundleInstaller::CheckInstallCondition( std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes, std::unordered_map<std::string, InnerBundleInfo> &infos) { ErrCode ret = bundleInstallChecker_->CheckDeviceType(infos); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "CheckDeviceType failed due to errorCode : %{public}d", ret); return ret; } ret = bundleInstallChecker_->CheckIsolationMode(infos); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "CheckIsolationMode failed due to errorCode : %{public}d", ret); return ret; } ret = bundleInstallChecker_->CheckHspInstallCondition(hapVerifyRes); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "CheckInstallCondition failed due to errorCode : %{public}d", ret); return ret; } return ERR_OK; } ErrCode BaseBundleInstaller::CheckInstallPermission(const InstallParam &installParam, std::vector<Security::Verify::HapVerifyResult> &hapVerifyRes) { if ((installParam.installBundlePermissionStatus != PermissionStatus::NOT_VERIFIED_PERMISSION_STATUS || installParam.installEnterpriseBundlePermissionStatus != PermissionStatus::NOT_VERIFIED_PERMISSION_STATUS || installParam.installEtpNormalBundlePermissionStatus != PermissionStatus::NOT_VERIFIED_PERMISSION_STATUS || installParam.installEtpMdmBundlePermissionStatus != PermissionStatus::NOT_VERIFIED_PERMISSION_STATUS || installParam.installInternaltestingBundlePermissionStatus != PermissionStatus::NOT_VERIFIED_PERMISSION_STATUS || installParam.installUpdateSelfBundlePermissionStatus != PermissionStatus::NOT_VERIFIED_PERMISSION_STATUS) && !bundleInstallChecker_->VaildInstallPermission(installParam, hapVerifyRes)) { // need vaild permission LOG_E(BMS_TAG_INSTALLER, "install permission denied"); return ERR_APPEXECFWK_INSTALL_PERMISSION_DENIED; } return ERR_OK; } ErrCode BaseBundleInstaller::CheckDependency(std::unordered_map<std::string, InnerBundleInfo> &infos, const SharedBundleInstaller &sharedBundleInstaller) { for (const auto &info : infos) { if (!sharedBundleInstaller.CheckDependency(info.second)) { LOG_E(BMS_TAG_INSTALLER, "cross-app dependency check failed"); return ERR_APPEXECFWK_INSTALL_DEPENDENT_MODULE_NOT_EXIST; } } return bundleInstallChecker_->CheckDependency(infos); } ErrCode BaseBundleInstaller::CheckHapHashParams( std::unordered_map<std::string, InnerBundleInfo> &infos, std::map<std::string, std::string> hashParams) { return bundleInstallChecker_->CheckHapHashParams(infos, hashParams); } ErrCode BaseBundleInstaller::CheckAppLabelInfo(const std::unordered_map<std::string, InnerBundleInfo> &infos) { for (const auto &info : infos) { if (info.second.GetApplicationBundleType() == BundleType::SHARED) { LOG_E(BMS_TAG_INSTALLER, "installing cross-app shared library"); return ERR_APPEXECFWK_INSTALL_FILE_IS_SHARED_LIBRARY; } } ErrCode ret = bundleInstallChecker_->CheckAppLabelInfo(infos); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "check app label info error"); return ret; } if (!CheckApiInfo(infos)) { LOG_E(BMS_TAG_INSTALLER, "CheckApiInfo failed"); return ERR_APPEXECFWK_INSTALL_SDK_INCOMPATIBLE; } bundleName_ = (infos.begin()->second).GetBundleName(); versionCode_ = (infos.begin()->second).GetVersionCode(); return ERR_OK; } bool BaseBundleInstaller::CheckApiInfo(const std::unordered_map<std::string, InnerBundleInfo> &infos) { std::string compileSdkType = infos.begin()->second.GetBaseApplicationInfo().compileSdkType; auto bundleInfo = infos.begin()->second.GetBaseBundleInfo(); if (compileSdkType == COMPILE_SDK_TYPE_OPEN_HARMONY) { return bundleInfo.compatibleVersion <= static_cast<uint32_t>(GetSdkApiVersion()); } BmsExtensionDataMgr bmsExtensionDataMgr; return bmsExtensionDataMgr.CheckApiInfo(infos.begin()->second.GetBaseBundleInfo(), static_cast<uint32_t>(GetSdkApiVersion())); } ErrCode BaseBundleInstaller::CheckMultiNativeFile( std::unordered_map<std::string, InnerBundleInfo> &infos) { return bundleInstallChecker_->CheckMultiNativeFile(infos); } ErrCode BaseBundleInstaller::CheckProxyDatas( const std::unordered_map<std::string, InnerBundleInfo> &infos) { if (!CheckDuplicateProxyData(infos)) { LOG_E(BMS_TAG_INSTALLER, "duplicated uri in proxyDatas"); return ERR_APPEXECFWK_INSTALL_CHECK_PROXY_DATA_URI_FAILED; } for (const auto &info : infos) { ErrCode ret = bundleInstallChecker_->CheckProxyDatas(info.second); if (ret != ERR_OK) { return ret; } } return ERR_OK; } ErrCode BaseBundleInstaller::CheckMDMUpdateBundleForSelf(const InstallParam &installParam, InnerBundleInfo &oldInfo, const std::unordered_map<std::string, InnerBundleInfo> &newInfos, bool isAppExist) { if (!installParam.isSelfUpdate) { return ERR_OK; } if (!OHOS::system::GetBoolParameter(ServiceConstants::ALLOW_ENTERPRISE_BUNDLE, false) && !OHOS::system::GetBoolParameter(ServiceConstants::IS_ENTERPRISE_DEVICE, false) && !OHOS::system::GetBoolParameter(ServiceConstants::DEVELOPERMODE_STATE, false)) { LOG_E(BMS_TAG_INSTALLER, "not enterprise device or developer mode is off"); return ERR_APPEXECFWK_INSTALL_ENTERPRISE_BUNDLE_NOT_ALLOWED; } if (!isAppExist) { LOG_E(BMS_TAG_INSTALLER, "not self update"); return ERR_APPEXECFWK_INSTALL_SELF_UPDATE_BUNDLENAME_NOT_SAME; } std::string appDistributionType = oldInfo.GetAppDistributionType(); if (appDistributionType != Constants::APP_DISTRIBUTION_TYPE_ENTERPRISE_MDM) { LOG_E(BMS_TAG_INSTALLER, "not mdm app"); return ERR_APPEXECFWK_INSTALL_SELF_UPDATE_NOT_MDM; } std::string bundleName = oldInfo.GetBundleName(); for (const auto &info : newInfos) { if (bundleName != info.second.GetBundleName()) { LOG_E(BMS_TAG_INSTALLER, "bundleName %{public}s not same", info.second.GetBundleName().c_str()); return ERR_APPEXECFWK_INSTALL_SELF_UPDATE_BUNDLENAME_NOT_SAME; } } return ERR_OK; } bool BaseBundleInstaller::GetInnerBundleInfo(InnerBundleInfo &info, bool &isAppExist) { if (!InitDataMgr()) { return false; } isAppExist = dataMgr_->GetInnerBundleInfo(bundleName_, info); return true; } bool BaseBundleInstaller::InitDataMgr() { if (dataMgr_ == nullptr) { dataMgr_ = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr(); if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "Get dataMgr shared_ptr nullptr"); return false; } } return true; } ErrCode BaseBundleInstaller::CheckVersionCompatibility(const InnerBundleInfo &oldInfo) { if (oldInfo.GetEntryInstallationFree()) { return CheckVersionCompatibilityForHmService(oldInfo); } return CheckVersionCompatibilityForApplication(oldInfo); } // In the process of hap updating, the version code of the entry hap which is about to be updated must not less the // version code of the current entry haps in the device; if no-entry hap in the device, the updating haps should // have same version code with the current version code; if the no-entry haps is to be updated, which should has the // same version code with that of the entry hap in the device. ErrCode BaseBundleInstaller::CheckVersionCompatibilityForApplication(const InnerBundleInfo &oldInfo) { LOG_D(BMS_TAG_INSTALLER, "start to check version compatibility for application"); if (oldInfo.HasEntry()) { if (isContainEntry_ && versionCode_ < oldInfo.GetVersionCode()) { LOG_E(BMS_TAG_INSTALLER, "fail to update lower version bundle"); return ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE; } if (!isContainEntry_ && versionCode_ > oldInfo.GetVersionCode()) { LOG_E(BMS_TAG_INSTALLER, "version code is not compatible"); return ERR_APPEXECFWK_INSTALL_VERSION_NOT_COMPATIBLE; } if (!isContainEntry_ && versionCode_ < oldInfo.GetVersionCode()) { LOG_E(BMS_TAG_INSTALLER, "version code is not compatible"); return ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE; } } else { if (versionCode_ < oldInfo.GetVersionCode()) { LOG_E(BMS_TAG_INSTALLER, "fail to update lower version bundle"); return ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE; } } if (versionCode_ > oldInfo.GetVersionCode()) { if (oldInfo.GetApplicationBundleType() == BundleType::APP_SERVICE_FWK) { LOG_E(BMS_TAG_INSTALLER, "Not alloweded instal appService hap(%{public}s) due to the hsp does not exist", oldInfo.GetBundleName().c_str()); return ERR_APP_SERVICE_FWK_INSTALL_TYPE_FAILED; } LOG_D(BMS_TAG_INSTALLER, "need to uninstall lower version feature hap"); isFeatureNeedUninstall_ = true; } LOG_D(BMS_TAG_INSTALLER, "finish to check version compatibility for application"); return ERR_OK; } ErrCode BaseBundleInstaller::CheckVersionCompatibilityForHmService(const InnerBundleInfo &oldInfo) { LOG_D(BMS_TAG_INSTALLER, "start to check version compatibility for hm service"); if (versionCode_ < oldInfo.GetVersionCode()) { LOG_E(BMS_TAG_INSTALLER, "fail to update lower version bundle"); return ERR_APPEXECFWK_INSTALL_VERSION_DOWNGRADE; } if (versionCode_ > oldInfo.GetVersionCode()) { LOG_D(BMS_TAG_INSTALLER, "need to uninstall lower version hap"); isFeatureNeedUninstall_ = true; } LOG_D(BMS_TAG_INSTALLER, "finish to check version compatibility for hm service"); return ERR_OK; } ErrCode BaseBundleInstaller::UninstallLowerVersionFeature(const std::vector<std::string> &packageVec, bool killProcess) { LOG_D(BMS_TAG_INSTALLER, "start to uninstall lower version feature hap"); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } InnerBundleInfo info; bool isExist = false; if (!GetInnerBundleInfo(info, isExist) || !isExist) { return ERR_APPEXECFWK_UNINSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!dataMgr_->UpdateBundleInstallState(bundleName_, InstallState::UNINSTALL_START)) { LOG_E(BMS_TAG_INSTALLER, "uninstall already start"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } // kill the bundle process during uninstall. if (killProcess) { if (!AbilityManagerHelper::UninstallApplicationProcesses( info.GetApplicationName(), info.GetUid(userId_), true)) { LOG_W(BMS_TAG_INSTALLER, "can not kill process"); } InnerBundleUserInfo userInfo; if (!info.GetInnerBundleUserInfo(userId_, userInfo)) { LOG_W(BMS_TAG_INSTALLER, "the origin application is not installed at current user"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } for (auto &cloneInfo : userInfo.cloneInfos) { if (!AbilityManagerHelper::UninstallApplicationProcesses( info.GetApplicationName(), cloneInfo.second.uid, true, std::stoi(cloneInfo.first))) { LOG_W(BMS_TAG_INSTALLER, "fail to kill clone application"); } } } std::vector<std::string> moduleVec = info.GetModuleNameVec(); InnerBundleInfo oldInfo = info; for (const auto &package : moduleVec) { if (find(packageVec.begin(), packageVec.end(), package) == packageVec.end()) { LOG_D(BMS_TAG_INSTALLER, "uninstall package %{public}s", package.c_str()); ErrCode result = RemoveModuleAndDataDir(info, package, Constants::UNSPECIFIED_USERID, true); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove module dir failed"); return result; } // remove driver file std::shared_ptr driverInstaller = std::make_shared<DriverInstaller>(); driverInstaller->RemoveDriverSoFile(info, info.GetModuleName(package), false); if (!dataMgr_->RemoveModuleInfo(bundleName_, package, info, false)) { LOG_E(BMS_TAG_INSTALLER, "RemoveModuleInfo failed"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } } } needDeleteQuickFixInfo_ = true; LOG_D(BMS_TAG_INSTALLER, "finish to uninstall lower version feature hap"); return ERR_OK; } int32_t BaseBundleInstaller::GetConfirmUserId( const int32_t &userId, std::unordered_map<std::string, InnerBundleInfo> &newInfos) { bool isSingleton = newInfos.begin()->second.IsSingleton(); LOG_I(BMS_TAG_INSTALLER, "The userId is Unspecified and app is singleton(%{public}d) when install", static_cast<int32_t>(isSingleton)); if (isSingleton) { return Constants::DEFAULT_USERID; } if (userId != Constants::UNSPECIFIED_USERID || newInfos.size() <= 0) { return userId; } return AccountHelper::GetCurrentActiveUserId(); } ErrCode BaseBundleInstaller::CheckUserId(const int32_t &userId) const { if (userId == Constants::UNSPECIFIED_USERID) { return ERR_OK; } if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "dataMgr_ is nullptr"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!dataMgr_->HasUserId(userId)) { LOG_E(BMS_TAG_INSTALLER, "The user %{public}d does not exist when install", userId); return ERR_APPEXECFWK_USER_NOT_EXIST; } return ERR_OK; } int32_t BaseBundleInstaller::GetUserId(const int32_t &userId) const { if (userId == Constants::UNSPECIFIED_USERID) { return userId; } if (userId < Constants::DEFAULT_USERID) { LOG_E(BMS_TAG_INSTALLER, "userId(%{public}d) is invalid", userId); return Constants::INVALID_USERID; } LOG_D(BMS_TAG_INSTALLER, "BundleInstaller GetUserId, now userId is %{public}d", userId); return userId; } ErrCode BaseBundleInstaller::CreateBundleUserData(InnerBundleInfo &innerBundleInfo) { LOG_I(BMS_TAG_INSTALLER, "CreateNewUserData %{public}s userId: %{public}d", innerBundleInfo.GetBundleName().c_str(), userId_); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!innerBundleInfo.HasInnerBundleUserInfo(userId_)) { return ERR_APPEXECFWK_USER_NOT_EXIST; } ErrCode result = CreateBundleDataDir(innerBundleInfo); if (result != ERR_OK) { RemoveBundleDataDir(innerBundleInfo, true); return result; } innerBundleInfo.SetBundleInstallTime(BundleUtil::GetCurrentTimeMs(), userId_); InnerBundleUserInfo innerBundleUserInfo; if (!innerBundleInfo.GetInnerBundleUserInfo(userId_, innerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "oldInfo do not have user"); return ERR_APPEXECFWK_USER_NOT_EXIST; } #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION OverlayDataMgr::GetInstance()->AddOverlayModuleStates(innerBundleInfo, innerBundleUserInfo); #endif if (!dataMgr_->AddInnerBundleUserInfo(innerBundleInfo.GetBundleName(), innerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "update bundle user info to db failed %{public}s when createNewUser", innerBundleInfo.GetBundleName().c_str()); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } return ERR_OK; } ErrCode BaseBundleInstaller::UninstallAllSandboxApps(const std::string &bundleName, int32_t userId) { // All sandbox will be uninstalled when the original application is updated or uninstalled LOG_D(BMS_TAG_INSTALLER, "UninstallAllSandboxApps begin"); if (bundleName.empty()) { LOG_E(BMS_TAG_INSTALLER, "UninstallAllSandboxApps failed due to empty bundle name"); return ERR_APPEXECFWK_INSTALL_PARAM_ERROR; } auto helper = DelayedSingleton<BundleSandboxAppHelper>::GetInstance(); if (helper == nullptr) { LOG_E(BMS_TAG_INSTALLER, "UninstallAllSandboxApps failed due to helper nullptr"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } if (helper->UninstallAllSandboxApps(bundleName, userId) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "UninstallAllSandboxApps failed"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } LOG_D(BMS_TAG_INSTALLER, "UninstallAllSandboxApps finish"); return ERR_OK; } ErrCode BaseBundleInstaller::CheckNativeFileWithOldInfo( const InnerBundleInfo &oldInfo, std::unordered_map<std::string, InnerBundleInfo> &newInfos) { LOG_D(BMS_TAG_INSTALLER, "CheckNativeFileWithOldInfo begin"); if (HasAllOldModuleUpdate(oldInfo, newInfos)) { LOG_D(BMS_TAG_INSTALLER, "All installed haps will be updated"); return ERR_OK; } ErrCode result = CheckNativeSoWithOldInfo(oldInfo, newInfos); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "Check nativeSo with oldInfo failed, result: %{public}d", result); return result; } result = CheckArkNativeFileWithOldInfo(oldInfo, newInfos); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "Check arkNativeFile with oldInfo failed, result: %{public}d", result); return result; } LOG_D(BMS_TAG_INSTALLER, "CheckNativeFileWithOldInfo end"); return ERR_OK; } bool BaseBundleInstaller::HasAllOldModuleUpdate( const InnerBundleInfo &oldInfo, std::unordered_map<std::string, InnerBundleInfo> &newInfos) { const auto &newInfo = newInfos.begin()->second; bool allOldModuleUpdate = true; if (newInfo.GetVersionCode() > oldInfo.GetVersionCode()) { LOG_D(BMS_TAG_INSTALLER, "All installed haps will be updated"); DeleteOldArkNativeFile(oldInfo); return allOldModuleUpdate; } std::vector<std::string> installedModules = oldInfo.GetModuleNameVec(); for (const auto &installedModule : installedModules) { auto updateModule = std::find_if(std::begin(newInfos), std::end(newInfos), [ &installedModule ] (const auto &item) { return item.second.FindModule(installedModule); }); if (updateModule == newInfos.end()) { LOG_D(BMS_TAG_INSTALLER, "Some installed haps will not be updated"); allOldModuleUpdate = false; break; } } return allOldModuleUpdate; } ErrCode BaseBundleInstaller::CheckArkNativeFileWithOldInfo( const InnerBundleInfo &oldInfo, std::unordered_map<std::string, InnerBundleInfo> &newInfos) { LOG_D(BMS_TAG_INSTALLER, "CheckArkNativeFileWithOldInfo begin"); std::string oldArkNativeFileAbi = oldInfo.GetArkNativeFileAbi(); if (oldArkNativeFileAbi.empty()) { LOG_D(BMS_TAG_INSTALLER, "OldInfo no arkNativeFile"); return ERR_OK; } if (newInfos.empty()) { LOG_D(BMS_TAG_INSTALLER, "newInfos is empty"); return ERR_APPEXECFWK_INSTALL_AN_INCOMPATIBLE; } std::string arkNativeFileAbi = newInfos.begin()->second.GetArkNativeFileAbi(); if (arkNativeFileAbi.empty()) { LOG_D(BMS_TAG_INSTALLER, "NewInfos no arkNativeFile"); for (auto& item : newInfos) { item.second.SetArkNativeFileAbi(oldInfo.GetArkNativeFileAbi()); item.second.SetArkNativeFilePath(oldInfo.GetArkNativeFilePath()); } } LOG_D(BMS_TAG_INSTALLER, "CheckArkNativeFileWithOldInfo end"); return ERR_OK; } ErrCode BaseBundleInstaller::CheckNativeSoWithOldInfo( const InnerBundleInfo &oldInfo, std::unordered_map<std::string, InnerBundleInfo> &newInfos) { LOG_D(BMS_TAG_INSTALLER, "CheckNativeSoWithOldInfo begin"); if (oldInfo.GetNativeLibraryPath().empty()) { LOG_D(BMS_TAG_INSTALLER, "OldInfo does not has so"); return ERR_OK; } const auto &newInfo = newInfos.begin()->second; bool newInfoHasSo = !newInfo.GetNativeLibraryPath().empty(); //newInfo should be consistent with oldInfo if (!newInfoHasSo) { for (auto& item : newInfos) { item.second.SetNativeLibraryPath(oldInfo.GetNativeLibraryPath()); item.second.SetCpuAbi(oldInfo.GetCpuAbi()); } } LOG_D(BMS_TAG_INSTALLER, "CheckNativeSoWithOldInfo end"); return ERR_OK; } ErrCode BaseBundleInstaller::CheckAppLabel(const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo) const { // check app label for inheritance installation LOG_D(BMS_TAG_INSTALLER, "CheckAppLabel begin"); if (oldInfo.GetMinCompatibleVersionCode() != newInfo.GetMinCompatibleVersionCode()) { return ERR_APPEXECFWK_INSTALL_MINCOMPATIBLE_VERSIONCODE_NOT_SAME; } if (oldInfo.GetTargetVersion()!= newInfo.GetTargetVersion()) { return ERR_APPEXECFWK_INSTALL_RELEASETYPE_TARGET_NOT_SAME; } if (oldInfo.GetCompatibleVersion() != newInfo.GetCompatibleVersion()) { return ERR_APPEXECFWK_INSTALL_RELEASETYPE_COMPATIBLE_NOT_SAME; } if (!CheckReleaseTypeIsCompatible(oldInfo, newInfo)) { return ERR_APPEXECFWK_INSTALL_RELEASETYPE_NOT_SAME; } if (oldInfo.GetAppDistributionType() != newInfo.GetAppDistributionType()) { return ERR_APPEXECFWK_INSTALL_APP_DISTRIBUTION_TYPE_NOT_SAME; } if (oldInfo.GetAppProvisionType() != newInfo.GetAppProvisionType()) { return ERR_APPEXECFWK_INSTALL_APP_PROVISION_TYPE_NOT_SAME; } if (oldInfo.GetAppFeature() != newInfo.GetAppFeature()) { return ERR_APPEXECFWK_INSTALL_APPTYPE_NOT_SAME; } if (oldInfo.GetIsNewVersion() != newInfo.GetIsNewVersion()) { LOG_E(BMS_TAG_INSTALLER, "same version update module condition, model type must be the same"); return ERR_APPEXECFWK_INSTALL_STATE_ERROR; } #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION if (oldInfo.GetTargetBundleName() != newInfo.GetTargetBundleName()) { return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_BUNDLE_NAME_NOT_SAME; } if (oldInfo.GetTargetPriority() != newInfo.GetTargetPriority()) { return ERR_BUNDLEMANAGER_OVERLAY_INSTALLATION_FAILED_TARGET_PRIORITY_NOT_SAME; } #endif if (oldInfo.GetApplicationBundleType() != newInfo.GetApplicationBundleType()) { return ERR_APPEXECFWK_BUNDLE_TYPE_NOT_SAME; } LOG_D(BMS_TAG_INSTALLER, "CheckAppLabel end"); return ERR_OK; } bool BaseBundleInstaller::CheckReleaseTypeIsCompatible( const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo) const { if (oldInfo.GetReleaseType() != newInfo.GetReleaseType()) { LOG_W(BMS_TAG_INSTALLER, "the releaseType not same: [%{public}s, %{public}s] vs [%{public}s, %{public}s]", oldInfo.GetCurModuleName().c_str(), oldInfo.GetReleaseType().c_str(), newInfo.GetCurModuleName().c_str(), newInfo.GetReleaseType().c_str()); } return true; } ErrCode BaseBundleInstaller::RemoveBundleUserData( InnerBundleInfo &innerBundleInfo, bool isKeepData, const bool async) { auto bundleName = innerBundleInfo.GetBundleName(); LOG_D(BMS_TAG_INSTALLER, "remove user(%{public}d) in bundle(%{public}s)", userId_, bundleName.c_str()); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } if (!innerBundleInfo.HasInnerBundleUserInfo(userId_)) { return ERR_APPEXECFWK_USER_NOT_EXIST; } // delete accessTokenId accessTokenId_ = innerBundleInfo.GetAccessTokenId(userId_); if (BundlePermissionMgr::DeleteAccessTokenId(accessTokenId_) != AccessToken::AccessTokenKitRet::RET_SUCCESS) { LOG_E(BMS_TAG_INSTALLER, "delete accessToken failed"); } if (innerBundleInfo.GetApplicationBundleType() == BundleType::ATOMIC_SERVICE) { int32_t uid = innerBundleInfo.GetUid(userId_); if (uid != Constants::INVALID_UID) { LOG_I(BMS_TAG_INSTALLER, "uninstall atomic service need delete quota, bundleName:%{public}s", innerBundleInfo.GetBundleName().c_str()); std::string bundleDataDir = ServiceConstants::BUNDLE_APP_DATA_BASE_DIR + ServiceConstants::BUNDLE_EL[1] + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::BASE + innerBundleInfo.GetBundleName(); PrepareBundleDirQuota(innerBundleInfo.GetBundleName(), uid, bundleDataDir, 0); } } innerBundleInfo.RemoveInnerBundleUserInfo(userId_); if (!dataMgr_->RemoveInnerBundleUserInfo(bundleName, userId_)) { LOG_E(BMS_TAG_INSTALLER, "update bundle user info to db failed %{public}s when remove user", bundleName.c_str()); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } ErrCode result = ERR_OK; if (!isKeepData) { result = RemoveBundleDataDir(innerBundleInfo, false, async); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "remove user data directory failed"); return result; } } result = DeleteArkProfile(bundleName, userId_); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to removeArkProfile, error is %{public}d", result); return result; } if ((result = CleanAsanDirectory(innerBundleInfo)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "fail to remove asan log path, error is %{public}d", result); return result; } if (dataMgr_->DeleteDesktopShortcutInfo(bundleName, userId_, 0) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "fail to delete shortcut info"); } return ERR_OK; } ErrCode BaseBundleInstaller::CheckInstallationFree(const InnerBundleInfo &innerBundleInfo, const std::unordered_map<std::string, InnerBundleInfo> &infos) const { for (const auto &item : infos) { if (innerBundleInfo.GetEntryInstallationFree() != item.second.GetEntryInstallationFree()) { LOG_E(BMS_TAG_INSTALLER, "CheckInstallationFree cannot install application and hm service simultaneously"); return ERR_APPEXECFWK_INSTALL_TYPE_ERROR; } } return ERR_OK; } void BaseBundleInstaller::SaveHapPathToRecords( bool isPreInstallApp, const std::unordered_map<std::string, InnerBundleInfo> &infos) { if (isPreInstallApp) { LOG_D(BMS_TAG_INSTALLER, "PreInstallApp do not need to save hap path to record"); return; } for (const auto &item : infos) { auto hapPathIter = hapPathRecords_.find(item.first); if (hapPathIter == hapPathRecords_.end()) { std::string tempDir = GetTempHapPath(item.second); if (tempDir.empty()) { LOG_W(BMS_TAG_INSTALLER, "get temp hap path failed"); continue; } LOG_D(BMS_TAG_INSTALLER, "tempDir is %{public}s", tempDir.c_str()); hapPathRecords_.emplace(item.first, tempDir); } std::string signatureFileDir = ""; FindSignatureFileDir(item.second.GetCurModuleName(), signatureFileDir); auto signatureFileIter = signatureFileMap_.find(item.first); if (signatureFileIter == signatureFileMap_.end()) { signatureFileMap_.emplace(item.first, signatureFileDir); } } } ErrCode BaseBundleInstaller::SaveHapToInstallPath(const std::unordered_map<std::string, InnerBundleInfo> &infos, const InnerBundleInfo &oldInfo) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); // size of code signature files should be same with the size of hap and hsp if (!signatureFileMap_.empty() && (signatureFileMap_.size() != hapPathRecords_.size())) { LOG_E(BMS_TAG_INSTALLER, "each hap or hsp needs to be verified code signature"); return ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FAILED; } // 1. copy hsp or hap file to temp installation dir ErrCode result = ERR_OK; for (const auto &hapPathRecord : hapPathRecords_) { LOG_D(BMS_TAG_INSTALLER, "Save from %{public}s to %{public}s", hapPathRecord.first.c_str(), hapPathRecord.second.c_str()); if ((signatureFileMap_.find(hapPathRecord.first) != signatureFileMap_.end()) && (!signatureFileMap_.at(hapPathRecord.first).empty())) { result = InstalldClient::GetInstance()->CopyFile(hapPathRecord.first, hapPathRecord.second, signatureFileMap_.at(hapPathRecord.first)); CHECK_RESULT(result, "Copy hap to install path failed or code signature hap failed %{public}d"); } else { if (InstalldClient::GetInstance()->MoveHapToCodeDir( hapPathRecord.first, hapPathRecord.second) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "Copy hap to install path failed"); return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED; } if (VerifyCodeSignatureForHap(infos, hapPathRecord.first, hapPathRecord.second) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "enable code signature failed"); return ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FAILED; } } } LOG_D(BMS_TAG_INSTALLER, "copy hap to install path success"); // 2. check encryption of hap if ((result = CheckHapEncryption(infos, oldInfo)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "check encryption of hap failed %{public}d", result); return result; } // 3. move file from temp dir to real installation dir if ((result = MoveFileToRealInstallationDir(infos)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "move file to real installation path failed %{public}d", result); return result; } return ERR_OK; } void BaseBundleInstaller::ResetInstallProperties() { bundleInstallChecker_->ResetProperties(); isContainEntry_ = false; isAppExist_ = false; hasInstalledInUser_ = false; isFeatureNeedUninstall_ = false; versionCode_ = 0; uninstallModuleVec_.clear(); installedModules_.clear(); state_ = InstallerState::INSTALL_START; singletonState_ = SingletonState::DEFAULT; accessTokenId_ = 0; sysEventInfo_.Reset(); moduleName_.clear(); verifyCodeParams_.clear(); pgoParams_.clear(); otaInstall_ = false; signatureFileMap_.clear(); hapPathRecords_.clear(); uninstallBundleAppId_.clear(); isModuleUpdate_ = false; isEntryInstalled_ = false; entryModuleName_.clear(); isEnterpriseBundle_ = false; isInternaltestingBundle_ = false; appIdentifier_.clear(); targetSoPathMap_.clear(); existBeforeKeepDataApp_ = false; } void BaseBundleInstaller::OnSingletonChange(bool killProcess) { if (singletonState_ == SingletonState::DEFAULT) { return; } InnerBundleInfo info; bool isExist = false; if (!GetInnerBundleInfo(info, isExist) || !isExist) { LOG_E(BMS_TAG_INSTALLER, "Get innerBundleInfo failed when singleton changed"); return; } InstallParam installParam; installParam.needSendEvent = false; installParam.SetForceExecuted(true); installParam.SetKillProcess(killProcess); if (singletonState_ == SingletonState::SINGLETON_TO_NON) { LOG_I(BMS_TAG_INSTALLER, "Bundle changes from singleton app to non singleton app"); installParam.userId = Constants::DEFAULT_USERID; UninstallBundle(bundleName_, installParam); return; } if (singletonState_ == SingletonState::NON_TO_SINGLETON) { LOG_I(BMS_TAG_INSTALLER, "Bundle changes from non singleton app to singleton app"); for (const auto &infoItem : info.GetInnerBundleUserInfos()) { int32_t installedUserId = infoItem.second.bundleUserInfo.userId; if (installedUserId == Constants::DEFAULT_USERID) { continue; } installParam.userId = installedUserId; UninstallBundle(bundleName_, installParam); } } } void BaseBundleInstaller::RestoreHaps(const std::vector<std::string> &bundlePaths, const InstallParam &installParam) { if (!installParam.IsRenameInstall() || bundlePaths_.empty() || bundlePaths.empty()) { LOG_I(BMS_TAG_INSTALLER, "No need to restore haps"); return; } const std::string newPrefix = std::string(ServiceConstants::BUNDLE_MANAGER_SERVICE_PATH) + ServiceConstants::GALLERY_DOWNLOAD_PATH + std::to_string(userId_) + ServiceConstants::PATH_SEPARATOR; std::string targetDir = bundlePaths.front().substr(0, bundlePaths.front().find_last_of('/') + 1); if (bundlePaths.front().find(APP_INSTALL_SANDBOX_PATH) == 0) { targetDir = newPrefix + targetDir.substr(std::strlen(APP_INSTALL_SANDBOX_PATH)); } else { LOG_W(BMS_TAG_INSTALLER, "Invalid bundle path: %{public}s", bundlePaths.front().c_str()); return; } for (const auto &originPath : bundlePaths_) { std::string targetPath = targetDir + originPath.substr(originPath.find_last_of('/') + 1); LOG_I(BMS_TAG_INSTALLER, "Restore hap: %{public}s -> %{public}s", originPath.c_str(), targetPath.c_str()); if (!BundleUtil::RenameFile(originPath, targetPath)) { LOG_W(BMS_TAG_INSTALLER, "failed: %{public}s -> %{public}s", originPath.c_str(), targetPath.c_str()); } } } void BaseBundleInstaller::SendBundleSystemEvent(const std::string &bundleName, BundleEventType bundleEventType, const InstallParam &installParam, InstallScene preBundleScene, ErrCode errCode) { sysEventInfo_.bundleName = bundleName; sysEventInfo_.isPreInstallApp = installParam.isPreInstallApp; sysEventInfo_.errCode = errCode; sysEventInfo_.isFreeInstallMode = (installParam.installFlag == InstallFlag::FREE_INSTALL); sysEventInfo_.userId = userId_; sysEventInfo_.versionCode = versionCode_; sysEventInfo_.preBundleScene = preBundleScene; GetCallingEventInfo(sysEventInfo_); EventReport::SendBundleSystemEvent(bundleEventType, sysEventInfo_); } void BaseBundleInstaller::GetCallingEventInfo(EventInfo &eventInfo) { LOG_D(BMS_TAG_INSTALLER, "GetCallingEventInfo start, bundleName:%{public}s", eventInfo.callingBundleName.c_str()); if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "Get dataMgr shared_ptr nullptr"); return; } if (!dataMgr_->GetBundleNameForUid(eventInfo.callingUid, eventInfo.callingBundleName)) { LOG_W(BMS_TAG_INSTALLER, "CallingUid %{public}d is not hap, no bundleName", eventInfo.callingUid); eventInfo.callingBundleName = Constants::EMPTY_STRING; return; } BundleInfo bundleInfo; if (!dataMgr_->GetBundleInfo(eventInfo.callingBundleName, BundleFlag::GET_BUNDLE_DEFAULT, bundleInfo, eventInfo.callingUid / Constants::BASE_USER_RANGE)) { LOG_E(BMS_TAG_INSTALLER, "GetBundleInfo failed, bundleName: %{public}s", eventInfo.callingBundleName.c_str()); return; } eventInfo.callingAppId = bundleInfo.appId; } void BaseBundleInstaller::GetInstallEventInfo(EventInfo &eventInfo) { LOG_D(BMS_TAG_INSTALLER, "GetInstallEventInfo start, bundleName:%{public}s", bundleName_.c_str()); InnerBundleInfo info; bool isExist = false; if (!GetInnerBundleInfo(info, isExist) || !isExist) { LOG_E(BMS_TAG_INSTALLER, "Get innerBundleInfo failed, bundleName: %{public}s", bundleName_.c_str()); return; } eventInfo.fingerprint = info.GetCertificateFingerprint(); eventInfo.appDistributionType = info.GetAppDistributionType(); eventInfo.hideDesktopIcon = info.IsHideDesktopIcon(); eventInfo.timeStamp = info.GetBundleUpdateTime(userId_); // report hapPath and hashValue for (const auto &innerModuleInfo : info.GetInnerModuleInfos()) { eventInfo.filePath.push_back(innerModuleInfo.second.hapPath); eventInfo.hashValue.push_back(innerModuleInfo.second.hashValue); } } void BaseBundleInstaller::GetInstallEventInfo(const InnerBundleInfo &bundleInfo, EventInfo &eventInfo) { LOG_D(BMS_TAG_INSTALLER, "GetInstallEventInfo start, bundleName:%{public}s", bundleInfo.GetBundleName().c_str()); eventInfo.fingerprint = bundleInfo.GetCertificateFingerprint(); eventInfo.appDistributionType = bundleInfo.GetAppDistributionType(); eventInfo.hideDesktopIcon = bundleInfo.IsHideDesktopIcon(); eventInfo.timeStamp = bundleInfo.GetBundleUpdateTime(userId_); // report hapPath and hashValue for (const auto &innerModuleInfo : bundleInfo.GetInnerModuleInfos()) { eventInfo.filePath.push_back(innerModuleInfo.second.hapPath); eventInfo.hashValue.push_back(innerModuleInfo.second.hashValue); } } void BaseBundleInstaller::SetCallingUid(int32_t callingUid) { sysEventInfo_.callingUid = callingUid; } ErrCode BaseBundleInstaller::NotifyBundleStatus(const NotifyBundleEvents &installRes) { std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>(); commonEventMgr->NotifyBundleStatus(installRes, dataMgr_); return ERR_OK; } void BaseBundleInstaller::AddBundleStatus(const NotifyBundleEvents &installRes) { bundleEvents_.emplace_back(installRes); } bool BaseBundleInstaller::NotifyAllBundleStatus() { if (bundleEvents_.empty()) { LOG_E(BMS_TAG_INSTALLER, "bundleEvents is empty"); return false; } auto dataMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetDataMgr(); if (!dataMgr) { LOG_E(BMS_TAG_INSTALLER, "Get dataMgr shared_ptr nullptr"); return false; } std::shared_ptr<BundleCommonEventMgr> commonEventMgr = std::make_shared<BundleCommonEventMgr>(); for (const auto &bundleEvent : bundleEvents_) { commonEventMgr->NotifyBundleStatus(bundleEvent, dataMgr); } return true; } void BaseBundleInstaller::AddNotifyBundleEvents(const NotifyBundleEvents ¬ifyBundleEvents) { auto userMgr = DelayedSingleton<BundleMgrService>::GetInstance()->GetBundleUserMgr(); if (userMgr == nullptr) { LOG_E(BMS_TAG_INSTALLER, "userMgr is null"); return; } userMgr->AddNotifyBundleEvents(notifyBundleEvents); } ErrCode BaseBundleInstaller::CheckOverlayInstallation(std::unordered_map<std::string, InnerBundleInfo> &newInfos, int32_t userId) { #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION std::shared_ptr<BundleOverlayInstallChecker> overlayChecker = std::make_shared<BundleOverlayInstallChecker>(); return overlayChecker->CheckOverlayInstallation(newInfos, userId, overlayType_); #else LOG_D(BMS_TAG_INSTALLER, "overlay is not supported"); return ERR_OK; #endif } ErrCode BaseBundleInstaller::CheckOverlayUpdate(const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo, int32_t userId) const { #ifdef BUNDLE_FRAMEWORK_OVERLAY_INSTALLATION std::shared_ptr<BundleOverlayInstallChecker> overlayChecker = std::make_shared<BundleOverlayInstallChecker>(); return overlayChecker->CheckOverlayUpdate(oldInfo, newInfo, userId); #else LOG_D(BMS_TAG_INSTALLER, "overlay is not supported"); return ERR_OK; #endif } NotifyType BaseBundleInstaller::GetNotifyType() { if (isAppExist_ && hasInstalledInUser_) { if (overlayType_ != NON_OVERLAY_TYPE) { return NotifyType::OVERLAY_UPDATE; } return NotifyType::UPDATE; } if (overlayType_ != NON_OVERLAY_TYPE) { return NotifyType::OVERLAY_INSTALL; } return NotifyType::INSTALL; } ErrCode BaseBundleInstaller::CheckArkProfileDir(const InnerBundleInfo &newInfo, const InnerBundleInfo &oldInfo) const { if (newInfo.GetVersionCode() > oldInfo.GetVersionCode()) { const auto userInfos = oldInfo.GetInnerBundleUserInfos(); for (auto iter = userInfos.begin(); iter != userInfos.end(); iter++) { int32_t userId = iter->second.bundleUserInfo.userId; int32_t gid = (newInfo.GetAppProvisionType() == Constants::APP_PROVISION_TYPE_DEBUG) ? GetIntParameter(BMS_KEY_SHELL_UID, ServiceConstants::SHELL_UID) : oldInfo.GetUid(userId); ErrCode result = newInfo.GetIsNewVersion() ? CreateArkProfile(bundleName_, userId, oldInfo.GetUid(userId), gid) : DeleteArkProfile(bundleName_, userId); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "bundleName: %{public}s CheckArkProfileDir failed, result:%{public}d", bundleName_.c_str(), result); return result; } } } return ERR_OK; } ErrCode BaseBundleInstaller::ProcessAsanDirectory(InnerBundleInfo &info) const { if (dataMgr_ == nullptr) { LOG_E(BMS_TAG_INSTALLER, "dataMgr_ is nullptr"); return ERR_APPEXECFWK_INSTALL_BUNDLE_MGR_SERVICE_ERROR; } const std::string bundleName = info.GetBundleName(); const std::string asanLogDir = ServiceConstants::BUNDLE_ASAN_LOG_DIR + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::PATH_SEPARATOR + bundleName + ServiceConstants::PATH_SEPARATOR + LOG; bool dirExist = false; ErrCode errCode = InstalldClient::GetInstance()->IsExistDir(asanLogDir, dirExist); if (errCode != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "check asan log directory failed"); return errCode; } bool asanEnabled = info.GetAsanEnabled(); // create asan log directory if asanEnabled is true if (!dirExist && asanEnabled) { InnerBundleUserInfo newInnerBundleUserInfo; if (!info.GetInnerBundleUserInfo(userId_, newInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "bundle(%{public}s) get user(%{public}d) failed", info.GetBundleName().c_str(), userId_); return ERR_APPEXECFWK_USER_NOT_EXIST; } if (!dataMgr_->GenerateUidAndGid(newInnerBundleUserInfo)) { LOG_E(BMS_TAG_INSTALLER, "fail to gererate uid and gid"); return ERR_APPEXECFWK_INSTALL_GENERATE_UID_ERROR; } mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; if ((errCode = InstalldClient::GetInstance()->Mkdir(asanLogDir, mode, newInnerBundleUserInfo.uid, newInnerBundleUserInfo.uid)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "create asan log directory failed"); return errCode; } } if (asanEnabled) { info.SetAsanLogPath(LOG); } // clean asan directory if (dirExist && !asanEnabled) { if ((errCode = CleanAsanDirectory(info)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "clean asan log directory failed"); return errCode; } } return ERR_OK; } void BaseBundleInstaller::GetUninstallBundleInfo(bool isKeepData, int32_t userId, const InnerBundleInfo &oldInfo, UninstallBundleInfo &uninstallBundleInfo) { if (!isKeepData) { return; } uninstallBundleInfo.userInfos[std::to_string(userId)].uid = oldInfo.GetUid(userId); uninstallBundleInfo.userInfos[std::to_string(userId)].gids.emplace_back(oldInfo.GetGid(userId)); uninstallBundleInfo.userInfos[std::to_string(userId)].accessTokenId = oldInfo.GetAccessTokenId(userId); uninstallBundleInfo.userInfos[std::to_string(userId)].accessTokenIdEx = oldInfo.GetAccessTokenIdEx(userId); uninstallBundleInfo.appId = oldInfo.GetAppId(); uninstallBundleInfo.appIdentifier = oldInfo.GetAppIdentifier(); uninstallBundleInfo.appProvisionType = oldInfo.GetAppProvisionType(); uninstallBundleInfo.bundleType = oldInfo.GetApplicationBundleType(); } void BaseBundleInstaller::SaveUninstallBundleInfo(const std::string bundleName, bool isKeepData, const UninstallBundleInfo &uninstallBundleInfo) { if (!isKeepData) { return; } if (!dataMgr_->UpdateUninstallBundleInfo(bundleName, uninstallBundleInfo)) { LOG_E(BMS_TAG_INSTALLER, "update failed"); } } void BaseBundleInstaller::DeleteUninstallBundleInfo(const std::string &bundleName) { if (!InitDataMgr()) { LOG_E(BMS_TAG_INSTALLER, "init failed"); return; } if (!existBeforeKeepDataApp_) { return; } if (!dataMgr_->DeleteUninstallBundleInfo(bundleName, userId_)) { LOG_E(BMS_TAG_INSTALLER, "delete failed"); } } bool BaseBundleInstaller::CheckInstallOnKeepData(const std::string &bundleName, bool isOTA, const std::unordered_map<std::string, InnerBundleInfo> &infos) { if (isOTA) { return true; } if (!InitDataMgr() || infos.empty()) { LOG_E(BMS_TAG_INSTALLER, "init failed or empty infos"); return true; } UninstallBundleInfo uninstallBundleInfo; if (!dataMgr_->GetUninstallBundleInfo(bundleName, uninstallBundleInfo)) { return true; } existBeforeKeepDataApp_ = true; LOG_I(BMS_TAG_INSTALLER, "this app was uninstalled with keep data before"); if (!CheckAppIdentifier(uninstallBundleInfo.appIdentifier, infos.begin()->second.GetAppIdentifier(), uninstallBundleInfo.appId, infos.begin()->second.GetAppId())) { LOG_E(BMS_TAG_INSTALLER, "%{public}s has been uninstalled with keep data, and the appIdentifier or appId is not the same", bundleName.c_str()); return false; } return true; } ErrCode BaseBundleInstaller::CleanAsanDirectory(InnerBundleInfo &info) const { const std::string bundleName = info.GetBundleName(); const std::string asanLogDir = ServiceConstants::BUNDLE_ASAN_LOG_DIR + ServiceConstants::PATH_SEPARATOR + std::to_string(userId_) + ServiceConstants::PATH_SEPARATOR + bundleName; ErrCode errCode = InstalldClient::GetInstance()->RemoveDir(asanLogDir); if (errCode != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "clean asan log path failed"); return errCode; } info.SetAsanLogPath(""); return errCode; } void BaseBundleInstaller::AddAppProvisionInfo(const std::string &bundleName, const Security::Verify::ProvisionInfo &provisionInfo, const InstallParam &installParam) const { AppProvisionInfo appProvisionInfo = bundleInstallChecker_->ConvertToAppProvisionInfo(provisionInfo); if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->AddAppProvisionInfo( bundleName, appProvisionInfo)) { LOG_W(BMS_TAG_INSTALLER, "bundleName: %{public}s add appProvisionInfo failed", bundleName.c_str()); } if (!installParam.specifiedDistributionType.empty()) { if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->SetSpecifiedDistributionType( bundleName, installParam.specifiedDistributionType)) { LOG_W(BMS_TAG_INSTALLER, "bundleName: %{public}s SetSpecifiedDistributionType failed", bundleName.c_str()); } } if (!installParam.additionalInfo.empty()) { if (!DelayedSingleton<AppProvisionInfoManager>::GetInstance()->SetAdditionalInfo( bundleName, installParam.additionalInfo)) { LOG_W(BMS_TAG_INSTALLER, "bundleName: %{public}s SetAdditionalInfo failed", bundleName.c_str()); } } } ErrCode BaseBundleInstaller::InnerProcessNativeLibs(InnerBundleInfo &info, const std::string &modulePath) { std::string targetSoPath; std::string cpuAbi; std::string nativeLibraryPath; bool isCompressNativeLibrary = info.IsCompressNativeLibs(info.GetCurModuleName()); if (info.FetchNativeSoAttrs(modulePackage_, cpuAbi, nativeLibraryPath)) { if (isCompressNativeLibrary) { bool isLibIsolated = info.IsLibIsolated(info.GetCurModuleName()); // extract so file: if hap so is not isolated, then extract so to tmp path. if (isLibIsolated) { if (BundleUtil::EndWith(modulePath, ServiceConstants::TMP_SUFFIX)) { nativeLibraryPath = BuildTempNativeLibraryPath(nativeLibraryPath); } } else { nativeLibraryPath = info.GetCurrentModulePackage() + ServiceConstants::TMP_SUFFIX + ServiceConstants::PATH_SEPARATOR + nativeLibraryPath; } LOG_D(BMS_TAG_INSTALLER, "Need extract to temp dir: %{public}s", nativeLibraryPath.c_str()); targetSoPath.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR) .append(info.GetBundleName()).append(ServiceConstants::PATH_SEPARATOR).append(nativeLibraryPath) .append(ServiceConstants::PATH_SEPARATOR); targetSoPathMap_.emplace(info.GetCurModuleName(), targetSoPath); } } LOG_D(BMS_TAG_INSTALLER, "begin extract module modulePath:%{public}s targetSoPath:%{public}s cpuAbi:%{public}s", modulePath.c_str(), targetSoPath.c_str(), cpuAbi.c_str()); std::string signatureFileDir = ""; auto ret = FindSignatureFileDir(info.GetCurModuleName(), signatureFileDir); if (ret != ERR_OK) { return ret; } if (isCompressNativeLibrary) { auto result = ExtractModuleFiles(info, modulePath, targetSoPath, cpuAbi); CHECK_RESULT(result, "fail to extract module dir, error is %{public}d"); // verify hap or hsp code signature for compressed so files result = VerifyCodeSignatureForNativeFiles(info, cpuAbi, targetSoPath, signatureFileDir); CHECK_RESULT(result, "fail to VerifyCodeSignature, error is %{public}d"); // check whether the hap or hsp is encrypted result = CheckSoEncryption(info, cpuAbi, targetSoPath); CHECK_RESULT(result, "fail to CheckSoEncryption, error is %{public}d"); } else { auto result = InstalldClient::GetInstance()->CreateBundleDir(modulePath); CHECK_RESULT(result, "fail to create temp bundle dir, error is %{public}d"); std::vector<std::string> fileNames; result = InstalldClient::GetInstance()->GetNativeLibraryFileNames(modulePath_, cpuAbi, fileNames); CHECK_RESULT(result, "fail to GetNativeLibraryFileNames, error is %{public}d"); info.SetNativeLibraryFileNames(modulePackage_, fileNames); } return ERR_OK; } ErrCode BaseBundleInstaller::VerifyCodeSignatureForNativeFiles(InnerBundleInfo &info, const std::string &cpuAbi, const std::string &targetSoPath, const std::string &signatureFileDir) const { if (copyHapToInstallPath_) { LOG_I(BMS_TAG_INSTALLER, "hap will be copied to install path, verified code signature later"); return ERR_OK; } LOG_D(BMS_TAG_INSTALLER, "begin to verify code signature for native files"); const std::string compileSdkType = info.GetBaseApplicationInfo().compileSdkType; CodeSignatureParam codeSignatureParam; codeSignatureParam.modulePath = modulePath_; codeSignatureParam.cpuAbi = cpuAbi; codeSignatureParam.targetSoPath = targetSoPath; codeSignatureParam.signatureFileDir = signatureFileDir; codeSignatureParam.isEnterpriseBundle = isEnterpriseBundle_; codeSignatureParam.isInternaltestingBundle = isInternaltestingBundle_; codeSignatureParam.appIdentifier = appIdentifier_; codeSignatureParam.isPreInstalledBundle = info.IsPreInstallApp(); codeSignatureParam.isCompileSdkOpenHarmony = (compileSdkType == COMPILE_SDK_TYPE_OPEN_HARMONY); return InstalldClient::GetInstance()->VerifyCodeSignature(codeSignatureParam); } ErrCode BaseBundleInstaller::VerifyCodeSignatureForHap(const std::unordered_map<std::string, InnerBundleInfo> &infos, const std::string &srcHapPath, const std::string &realHapPath) { LOG_D(BMS_TAG_INSTALLER, "begin to verify code signature for hap or internal hsp"); auto iter = infos.find(srcHapPath); if (iter == infos.end()) { return ERR_OK; } std::string moduleName = (iter->second).GetCurModuleName(); std::string cpuAbi; std::string nativeLibraryPath; (iter->second).FetchNativeSoAttrs((iter->second).GetCurrentModulePackage(), cpuAbi, nativeLibraryPath); const std::string compileSdkType = (iter->second).GetBaseApplicationInfo().compileSdkType; std::string signatureFileDir = ""; auto ret = FindSignatureFileDir(moduleName, signatureFileDir); if (ret != ERR_OK) { return ret; } auto targetSoPath = targetSoPathMap_.find(moduleName); CodeSignatureParam codeSignatureParam; if (targetSoPath != targetSoPathMap_.end()) { codeSignatureParam.targetSoPath = targetSoPath->second; } codeSignatureParam.cpuAbi = cpuAbi; codeSignatureParam.modulePath = realHapPath; codeSignatureParam.signatureFileDir = signatureFileDir; codeSignatureParam.isEnterpriseBundle = isEnterpriseBundle_; codeSignatureParam.isInternaltestingBundle = isInternaltestingBundle_; codeSignatureParam.appIdentifier = appIdentifier_; codeSignatureParam.isCompileSdkOpenHarmony = (compileSdkType == COMPILE_SDK_TYPE_OPEN_HARMONY); codeSignatureParam.isPreInstalledBundle = (iter->second).IsPreInstallApp(); return InstalldClient::GetInstance()->VerifyCodeSignatureForHap(codeSignatureParam); } ErrCode BaseBundleInstaller::CheckSoEncryption(InnerBundleInfo &info, const std::string &cpuAbi, const std::string &targetSoPath) { LOG_D(BMS_TAG_INSTALLER, "begin to check so encryption"); CheckEncryptionParam param; param.modulePath = modulePath_; param.cpuAbi = cpuAbi; param.targetSoPath = targetSoPath; int uid = info.GetUid(userId_); param.bundleId = uid - userId_ * Constants::BASE_USER_RANGE; param.isCompressNativeLibrary = info.IsCompressNativeLibs(info.GetCurModuleName()); if (info.GetModuleTypeByPackage(modulePackage_) == Profile::MODULE_TYPE_SHARED) { param.installBundleType = InstallBundleType::INTER_APP_HSP; } bool isEncrypted = false; ErrCode result = InstalldClient::GetInstance()->CheckEncryption(param, isEncrypted); CHECK_RESULT(result, "fail to CheckSoEncryption, error is %{public}d"); if ((info.GetBaseApplicationInfo().debug || (info.GetAppProvisionType() == Constants::APP_PROVISION_TYPE_DEBUG)) && isEncrypted) { LOG_E(BMS_TAG_INSTALLER, "-n %{public}s debug encrypted bundle is not allowed to install", info.GetBundleName().c_str()); return ERR_APPEXECFWK_INSTALL_DEBUG_ENCRYPTED_BUNDLE_FAILED; } if (isEncrypted && sysEventInfo_.callingUid == ServiceConstants::SHELL_UID) { LOG_E(BMS_TAG_INSTALLER, "-n %{public}s encrypted bundle is not allowed for shell", info.GetBundleName().c_str()); return ERR_APPEXECFWK_INSTALL_ENCRYPTED_BUNDLE_NOT_ALLOWED_FOR_SHELL; } if (isEncrypted) { LOG_D(BMS_TAG_INSTALLER, "module %{public}s is encrypted", modulePath_.c_str()); info.SetApplicationReservedFlag(static_cast<uint32_t>(ApplicationReservedFlag::ENCRYPTED_APPLICATION)); } return ERR_OK; } void BaseBundleInstaller::ProcessOldNativeLibraryPath(const std::unordered_map<std::string, InnerBundleInfo> &newInfos, uint32_t oldVersionCode, const std::string &oldNativeLibraryPath) const { if (((oldVersionCode >= versionCode_) && !otaInstall_) || oldNativeLibraryPath.empty()) { return; } for (const auto &item : newInfos) { const auto &moduleInfos = item.second.GetInnerModuleInfos(); for (const auto &moduleItem: moduleInfos) { if (moduleItem.second.compressNativeLibs) { // no need to delete library path return; } } } std::string oldLibPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::PATH_SEPARATOR + ServiceConstants::LIBS; if (InstalldClient::GetInstance()->RemoveDir(oldLibPath) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "bundleNmae: %{public}s remove old libs dir failed", bundleName_.c_str()); } } void BaseBundleInstaller::ProcessAOT(bool isOTA, const std::unordered_map<std::string, InnerBundleInfo> &infos) const { if (isOTA) { LOG_D(BMS_TAG_INSTALLER, "is OTA, no need to AOT"); return; } AOTHandler::GetInstance().HandleInstall(infos); } void BaseBundleInstaller::RemoveOldHapIfOTA(const InstallParam &installParam, const std::unordered_map<std::string, InnerBundleInfo> &newInfos, const InnerBundleInfo &oldInfo) const { if (!installParam.isOTA || installParam.copyHapToInstallPath) { return; } for (const auto &info : newInfos) { std::string oldHapPath = oldInfo.GetModuleHapPath(info.second.GetCurrentModulePackage()); if (oldHapPath.empty() || oldHapPath.rfind(Constants::BUNDLE_CODE_DIR, 0) != 0) { continue; } LOG_I(BMS_TAG_INSTALLER, "remove old hap %{public}s", oldHapPath.c_str()); if (InstalldClient::GetInstance()->RemoveDir(oldHapPath) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "remove old hap failed, errno: %{public}d", errno); } } } ErrCode BaseBundleInstaller::CopyHapsToSecurityDir(const InstallParam &installParam, std::vector<std::string> &bundlePaths) { HITRACE_METER_NAME(HITRACE_TAG_APP, __PRETTY_FUNCTION__); if (!installParam.withCopyHaps) { LOG_D(BMS_TAG_INSTALLER, "no need to copy preInstallApp to secure dir"); return ERR_OK; } if (!bundlePaths_.empty()) { bundlePaths = bundlePaths_; LOG_D(BMS_TAG_INSTALLER, "using the existed hap files in security dir"); return ERR_OK; } for (size_t index = 0; index < bundlePaths.size(); ++index) { if (!BundleUtil::CheckSystemSize(bundlePaths[index], APP_INSTALL_PATH)) { LOG_E(BMS_TAG_INSTALLER, "install %{public}s failed insufficient disk memory", bundlePaths[index].c_str()); return ERR_APPEXECFWK_INSTALL_DISK_MEM_INSUFFICIENT; } auto destination = BundleUtil::CopyFileToSecurityDir(bundlePaths[index], DirType::STREAM_INSTALL_DIR, toDeleteTempHapPath_, installParam.IsRenameInstall()); if (destination.empty()) { LOG_E(BMS_TAG_INSTALLER, "copy file %{public}s to security dir failed", bundlePaths[index].c_str()); return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED; } if (bundlePaths[index].find(ServiceConstants::STREAM_INSTALL_PATH) != std::string::npos) { BundleUtil::DeleteDir(bundlePaths[index]); } bundlePaths[index] = destination; } bundlePaths_ = bundlePaths; return ERR_OK; } ErrCode BaseBundleInstaller::ParseHapPaths(const InstallParam &installParam, const std::vector<std::string> &inBundlePaths, std::vector<std::string> &parsedPaths) { parsedPaths.reserve(inBundlePaths.size()); if (!installParam.IsRenameInstall()) { parsedPaths.assign(inBundlePaths.begin(), inBundlePaths.end()); return ERR_OK; } LOG_I(BMS_TAG_INSTALLER, "rename install"); const std::string newPrefix = std::string(ServiceConstants::BUNDLE_MANAGER_SERVICE_PATH) + ServiceConstants::GALLERY_DOWNLOAD_PATH + std::to_string(userId_) + ServiceConstants::PATH_SEPARATOR; for (const auto &bundlePath : inBundlePaths) { if (bundlePath.find("..") != std::string::npos) { LOG_E(BMS_TAG_INSTALLER, "path invalid: %{public}s", bundlePath.c_str()); return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; } if (bundlePath.find(APP_INSTALL_SANDBOX_PATH) == 0) { std::string newPath = newPrefix + bundlePath.substr(std::strlen(APP_INSTALL_SANDBOX_PATH)); parsedPaths.push_back(newPath); LOG_D(BMS_TAG_INSTALLER, "parsed path: %{public}s", newPath.c_str()); } else { LOG_E(BMS_TAG_INSTALLER, "path invalid: %{public}s", bundlePath.c_str()); return ERR_APPEXECFWK_INSTALL_FILE_PATH_INVALID; } } return ERR_OK; } ErrCode BaseBundleInstaller::RenameAllTempDir(const std::unordered_map<std::string, InnerBundleInfo> &newInfos) const { LOG_D(BMS_TAG_INSTALLER, "begin to rename all temp dir"); ErrCode ret = ERR_OK; for (const auto &info : newInfos) { if (info.second.IsOnlyCreateBundleUser()) { continue; } if ((ret = RenameModuleDir(info.second)) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "rename dir failed"); break; } } RemoveEmptyDirs(newInfos); return ret; } ErrCode BaseBundleInstaller::FindSignatureFileDir(const std::string &moduleName, std::string &signatureFileDir) { LOG_D(BMS_TAG_INSTALLER, "begin to find code signature file of moudle %{public}s", moduleName.c_str()); if (verifyCodeParams_.empty()) { signatureFileDir = ""; LOG_D(BMS_TAG_INSTALLER, "verifyCodeParams_ is empty and no need to verify code signature of module %{public}s", moduleName.c_str()); return ERR_OK; } if (signatureFileTmpMap_.find(moduleName) != signatureFileTmpMap_.end()) { signatureFileDir = signatureFileTmpMap_.at(moduleName); LOG_D(BMS_TAG_INSTALLER, "signature file of %{public}s is existed in temp map", moduleName.c_str()); return ERR_OK; } auto iterator = verifyCodeParams_.find(moduleName); if (iterator == verifyCodeParams_.end()) { LOG_E(BMS_TAG_INSTALLER, "no signature file dir exist of module %{public}s", moduleName.c_str()); return ERR_BUNDLEMANAGER_INSTALL_CODE_SIGNATURE_FAILED; } signatureFileDir = verifyCodeParams_.at(moduleName); // check validity of the signature file auto ret = bundleInstallChecker_->CheckSignatureFileDir(signatureFileDir); if (ret != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "checkout signature file dir %{public}s failed", signatureFileDir.c_str()); return ret; } // copy code signature file to security dir std::string destinationStr = BundleUtil::CopyFileToSecurityDir(signatureFileDir, DirType::SIG_FILE_DIR, toDeleteTempHapPath_); if (destinationStr.empty()) { LOG_E(BMS_TAG_INSTALLER, "copy file %{public}s to security dir failed", signatureFileDir.c_str()); return ERR_APPEXECFWK_INSTALL_COPY_HAP_FAILED; } if (signatureFileDir.find(ServiceConstants::SIGNATURE_FILE_PATH) != std::string::npos) { BundleUtil::DeleteDir(signatureFileDir); } signatureFileDir = destinationStr; signatureFileTmpMap_.emplace(moduleName, destinationStr); LOG_D(BMS_TAG_INSTALLER, "signatureFileDir is %{public}s", signatureFileDir.c_str()); return ERR_OK; } std::string BaseBundleInstaller::GetTempHapPath(const InnerBundleInfo &info) { std::string hapPath = GetHapPath(info); if (hapPath.empty() || (!BundleUtil::EndWith(hapPath, ServiceConstants::INSTALL_FILE_SUFFIX) && !BundleUtil::EndWith(hapPath, ServiceConstants::HSP_FILE_SUFFIX))) { LOG_E(BMS_TAG_INSTALLER, "invalid hapPath %{public}s", hapPath.c_str()); return ""; } auto posOfPathSep = hapPath.rfind(ServiceConstants::PATH_SEPARATOR); if (posOfPathSep == std::string::npos) { return ""; } std::string tempDir = hapPath.substr(0, posOfPathSep + 1) + info.GetCurrentModulePackage(); if (installedModules_[info.GetCurrentModulePackage()]) { tempDir += ServiceConstants::TMP_SUFFIX; } return tempDir.append(hapPath.substr(posOfPathSep)); } ErrCode BaseBundleInstaller::CheckHapEncryption(const std::unordered_map<std::string, InnerBundleInfo> &infos, const InnerBundleInfo &oldInfo) { LOG_D(BMS_TAG_INSTALLER, "begin to check hap encryption"); InnerBundleInfo newInfo; bool isExist = false; if (!GetInnerBundleInfo(newInfo, isExist) || !isExist) { LOG_E(BMS_TAG_INSTALLER, "Get innerBundleInfo failed, bundleName: %{public}s", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } for (const auto &info : infos) { if (hapPathRecords_.find(info.first) == hapPathRecords_.end()) { LOG_E(BMS_TAG_INSTALLER, "path %{public}s cannot be found in hapPathRecord", info.first.c_str()); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } std::string hapPath = hapPathRecords_.at(info.first); CheckEncryptionParam param; param.modulePath = hapPath; int uid = info.second.GetUid(userId_); param.bundleId = uid - userId_ * Constants::BASE_USER_RANGE; param.isCompressNativeLibrary = info.second.IsCompressNativeLibs(info.second.GetCurModuleName()); if (info.second.GetModuleTypeByPackage(modulePackage_) == Profile::MODULE_TYPE_SHARED) { param.installBundleType = InstallBundleType::INTER_APP_HSP; } bool isEncrypted = false; ErrCode result = InstalldClient::GetInstance()->CheckEncryption(param, isEncrypted); CHECK_RESULT(result, "fail to CheckHapEncryption, error is %{public}d"); if ((info.second.GetBaseApplicationInfo().debug || (info.second.GetAppProvisionType() == Constants::APP_PROVISION_TYPE_DEBUG)) && isEncrypted) { LOG_E(BMS_TAG_INSTALLER, "-n %{public}s debug encrypted bundle is not allowed to install", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_DEBUG_ENCRYPTED_BUNDLE_FAILED; } newInfo.SetMoudleIsEncrpted(info.second.GetCurrentModulePackage(), isEncrypted); } UpdateEncryptionStatus(infos, oldInfo, newInfo); if (dataMgr_ == nullptr || !dataMgr_->UpdateInnerBundleInfo(newInfo, false)) { LOG_E(BMS_TAG_INSTALLER, "save UpdateInnerBundleInfo failed"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } return ERR_OK; } void BaseBundleInstaller::UpdateEncryptionStatus(const std::unordered_map<std::string, InnerBundleInfo> &infos, const InnerBundleInfo &oldInfo, InnerBundleInfo &newInfo) { if (IsBundleEncrypted(infos, oldInfo, newInfo)) { LOG_D(BMS_TAG_INSTALLER, "application contains encrypted module"); newInfo.SetApplicationReservedFlag(static_cast<uint32_t>(ApplicationReservedFlag::ENCRYPTED_APPLICATION)); } else { LOG_D(BMS_TAG_INSTALLER, "application does not contain encrypted module"); newInfo.ClearApplicationReservedFlag(static_cast<uint32_t>(ApplicationReservedFlag::ENCRYPTED_APPLICATION)); } } void BaseBundleInstaller::ClearEncryptionStatus() { InnerBundleInfo newInfo; if (dataMgr_ == nullptr || !dataMgr_->FetchInnerBundleInfo(bundleName_, newInfo)) { LOG_E(BMS_TAG_INSTALLER, "Get innerBundleInfo failed, bundleName: %{public}s", bundleName_.c_str()); return; } newInfo.ClearApplicationReservedFlag(static_cast<uint32_t>(ApplicationReservedFlag::ENCRYPTED_APPLICATION)); if (!dataMgr_->UpdateInnerBundleInfo(newInfo, false)) { LOG_E(BMS_TAG_INSTALLER, "UpdateInnerBundleInfo failed"); return; } LOG_I(BMS_TAG_INSTALLER, "encryption status is cleared for: %{public}s", bundleName_.c_str()); } bool BaseBundleInstaller::IsBundleEncrypted(const std::unordered_map<std::string, InnerBundleInfo> &infos, const InnerBundleInfo &oldInfo, const InnerBundleInfo &newInfo) { // any of the new module is entryped, then the bundle is entryped for (const auto &info : infos) { if (newInfo.IsEncryptedMoudle(info.second.GetCurrentModulePackage())) { LOG_D(BMS_TAG_INSTALLER, "new installed module is encrypted"); return true; } } // infos does not contain encrypted module // if upgrade, no need to check old bundle if (infos.empty() || infos.begin()->second.GetVersionCode() > oldInfo.GetVersionCode()) { return false; } // if not upgrade and old bundle is not encrypted, the new bundle is alse not encrypted if (!oldInfo.IsContainEncryptedModule()) { return false; } // if old bundle is encrypted, check whether all encrypted old modules are updated std::vector<std::string> encryptedModuleNames; oldInfo.GetAllEncryptedModuleNames(encryptedModuleNames); for (const auto &moduleName : encryptedModuleNames) { bool moduleUpdated = false; for (const auto &info : infos) { if (moduleName == info.second.GetModuleName(info.second.GetCurrentModulePackage())) { moduleUpdated = true; break; } } if (!moduleUpdated) { LOG_I(BMS_TAG_INSTALLER, "%{public}s is encrypted and not updated", moduleName.c_str()); return true; } } return false; } ErrCode BaseBundleInstaller::MoveFileToRealInstallationDir( const std::unordered_map<std::string, InnerBundleInfo> &infos) { LOG_D(BMS_TAG_INSTALLER, "start to move file to real installation dir"); for (const auto &info : infos) { if (hapPathRecords_.find(info.first) == hapPathRecords_.end()) { LOG_E(BMS_TAG_INSTALLER, "path %{public}s cannot be found in hapPathRecord", info.first.c_str()); return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED; } std::string realInstallationPath = GetHapPath(info.second); LOG_D(BMS_TAG_INSTALLER, "move hsp or hsp file from path %{public}s to path %{public}s", hapPathRecords_.at(info.first).c_str(), realInstallationPath.c_str()); // 1. move hap or hsp to real installation dir auto result = InstalldClient::GetInstance()->MoveFile(hapPathRecords_.at(info.first), realInstallationPath); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "move file to real path failed %{public}d", result); return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED; } int32_t hapFd = open(realInstallationPath.c_str(), O_RDONLY); if (fsync(hapFd) != 0) { LOG_E(BMS_TAG_INSTALLER, "fsync %{public}s failed", realInstallationPath.c_str()); } close(hapFd); } return ERR_OK; } ErrCode BaseBundleInstaller::MoveSoFileToRealInstallationDir( const std::unordered_map<std::string, InnerBundleInfo> &infos) { LOG_D(BMS_TAG_INSTALLER, "start to move so file to real installation dir"); for (const auto &info : infos) { if (info.second.IsLibIsolated(info.second.GetCurModuleName()) || !info.second.IsCompressNativeLibs(info.second.GetCurModuleName())) { LOG_I(BMS_TAG_INSTALLER, "so files are isolated or decompressed and no necessary to move so files"); continue; } std::string cpuAbi = ""; std::string nativeLibraryPath = ""; bool isSoExisted = info.second.FetchNativeSoAttrs(info.second.GetCurrentModulePackage(), cpuAbi, nativeLibraryPath); if (isSoExisted) { std::string tempSoDir; tempSoDir.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR) .append(info.second.GetBundleName()).append(ServiceConstants::PATH_SEPARATOR) .append(info.second.GetCurrentModulePackage()) .append(ServiceConstants::TMP_SUFFIX).append(ServiceConstants::PATH_SEPARATOR) .append(nativeLibraryPath); bool isDirExisted = false; auto result = InstalldClient::GetInstance()->IsExistDir(tempSoDir, isDirExisted); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "check if dir existed failed %{public}d", result); return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED; } if (!isDirExisted) { LOG_W(BMS_TAG_INSTALLER, "%{public}s is not existed not need to be moved", tempSoDir.c_str()); continue; } std::string realSoDir; realSoDir.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR) .append(info.second.GetBundleName()).append(ServiceConstants::PATH_SEPARATOR) .append(nativeLibraryPath); LOG_D(BMS_TAG_INSTALLER, "move file from %{public}s to %{public}s", tempSoDir.c_str(), realSoDir.c_str()); isDirExisted = false; result = InstalldClient::GetInstance()->IsExistDir(realSoDir, isDirExisted); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "check if dir existed failed %{public}d", result); return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED; } if (!isDirExisted) { InstalldClient::GetInstance()->CreateBundleDir(realSoDir); } result = InstalldClient::GetInstance()->MoveFiles(tempSoDir, realSoDir); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "move file to real path failed %{public}d", result); return ERR_APPEXECFWK_INSTALLD_MOVE_FILE_FAILED; } RemoveTempSoDir(tempSoDir); if (!installedModules_[info.second.GetCurrentModulePackage()]) { RemoveTempPathOnlyUsedForSo(info.second); } } } return ERR_OK; } void BaseBundleInstaller::UpdateAppInstallControlled(int32_t userId) { #ifdef BUNDLE_FRAMEWORK_APP_CONTROL if (!DelayedSingleton<AppControlManager>::GetInstance()->IsAppInstallControlEnabled()) { LOG_D(BMS_TAG_INSTALLER, "app control feature is disabled"); return; } if (bundleName_.empty() || dataMgr_ == nullptr) { LOG_W(BMS_TAG_INSTALLER, "invalid bundleName_ or dataMgr is nullptr"); return; } InnerBundleInfo info; bool isAppExisted = dataMgr_->QueryInnerBundleInfo(bundleName_, info); if (!isAppExisted) { LOG_W(BMS_TAG_INSTALLER, "bundle %{public}s is not existed", bundleName_.c_str()); return; } InnerBundleUserInfo userInfo; if (!info.GetInnerBundleUserInfo(userId, userInfo)) { LOG_W(BMS_TAG_INSTALLER, "current bundle (%{public}s) is not installed at current userId (%{public}d)", bundleName_.c_str(), userId); return; } std::string currentAppId = info.GetAppId(); std::vector<std::string> appIds; ErrCode ret = DelayedSingleton<AppControlManager>::GetInstance()->GetAppInstallControlRule( AppControlConstants::EDM_CALLING, AppControlConstants::APP_DISALLOWED_UNINSTALL, userId, appIds); if ((ret == ERR_OK) && (std::find(appIds.begin(), appIds.end(), currentAppId) != appIds.end())) { LOG_W(BMS_TAG_INSTALLER, "bundle %{public}s cannot be removed", bundleName_.c_str()); userInfo.isRemovable = false; dataMgr_->AddInnerBundleUserInfo(bundleName_, userInfo); } #else LOG_W(BMS_TAG_INSTALLER, "app control is disable"); #endif } ErrCode BaseBundleInstaller::UninstallBundleFromBmsExtension(const std::string &bundleName) { LOG_D(BMS_TAG_INSTALLER, "start to uninstall bundle from bms extension"); if (!DelayedSingleton<BundleMgrService>::GetInstance()->IsBrokerServiceStarted()) { LOG_W(BMS_TAG_INSTALLER, "broker is not started"); return ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE; } BmsExtensionDataMgr bmsExtensionDataMgr; auto ret = bmsExtensionDataMgr.Uninstall(bundleName); if (ret == ERR_OK) { LOG_D(BMS_TAG_INSTALLER, "uninstall bundle(%{public}s) from bms extension successfully", bundleName.c_str()); return ERR_OK; } if ((ret == ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE) || (ret == ERR_BUNDLE_MANAGER_INSTALL_FAILED_BUNDLE_EXTENSION_NOT_EXISTED)) { LOG_E(BMS_TAG_INSTALLER, "uninstall failed due to bundle(%{public}s is not existed)", bundleName.c_str()); return ERR_APPEXECFWK_UNINSTALL_MISSING_INSTALLED_BUNDLE; } LOG_E(BMS_TAG_INSTALLER, "uninstall bundle(%{public}s) from bms extension faile due to errcode %{public}d", bundleName.c_str(), ret); return ERR_BUNDLE_MANAGER_UNINSTALL_FROM_BMS_EXTENSION_FAILED; } ErrCode BaseBundleInstaller::CheckBundleInBmsExtension(const std::string &bundleName, int32_t userId) { LOG_D(BMS_TAG_INSTALLER, "start to check bundle(%{public}s) from bms extension", bundleName.c_str()); if (!DelayedSingleton<BundleMgrService>::GetInstance()->IsBrokerServiceStarted()) { LOG_W(BMS_TAG_INSTALLER, "broker is not started"); return ERR_OK; } BmsExtensionDataMgr bmsExtensionDataMgr; BundleInfo extensionBundleInfo; auto ret = bmsExtensionDataMgr.GetBundleInfo(bundleName, BundleFlag::GET_BUNDLE_DEFAULT, userId, extensionBundleInfo); if (ret == ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "the bundle(%{public}s) is already existed in the bms extension", bundleName.c_str()); return ERR_APPEXECFWK_INSTALL_ALREADY_EXIST; } return ERR_OK; } void BaseBundleInstaller::RemoveTempSoDir(const std::string &tempSoDir) { auto firstPos = tempSoDir.find(ServiceConstants::TMP_SUFFIX); if (firstPos == std::string::npos) { LOG_W(BMS_TAG_INSTALLER, "invalid tempSoDir %{public}s", tempSoDir.c_str()); return; } auto secondPos = tempSoDir.find(ServiceConstants::PATH_SEPARATOR, firstPos); if (secondPos == std::string::npos) { LOG_W(BMS_TAG_INSTALLER, "invalid tempSoDir %{public}s", tempSoDir.c_str()); return; } auto thirdPos = tempSoDir.find(ServiceConstants::PATH_SEPARATOR, secondPos + 1); if (thirdPos == std::string::npos) { InstalldClient::GetInstance()->RemoveDir(tempSoDir); return; } std::string subTempSoDir = tempSoDir.substr(0, thirdPos); InstalldClient::GetInstance()->RemoveDir(subTempSoDir); } ErrCode BaseBundleInstaller::InstallEntryMoudleFirst(std::unordered_map<std::string, InnerBundleInfo> &newInfos, InnerBundleInfo &bundleInfo, const InnerBundleUserInfo &innerBundleUserInfo, const InstallParam &installParam) { LOG_D(BMS_TAG_INSTALLER, "start to install entry firstly"); if (!isAppExist_ || isEntryInstalled_) { LOG_D(BMS_TAG_INSTALLER, "no need to install entry firstly"); return ERR_OK; } ErrCode result = ERR_OK; for (auto &info : newInfos) { if (info.second.HasEntry()) { modulePath_ = info.first; InnerBundleInfo &newInfo = info.second; newInfo.AddInnerBundleUserInfo(innerBundleUserInfo); bool isReplace = (installParam.installFlag == InstallFlag::REPLACE_EXISTING || installParam.installFlag == InstallFlag::FREE_INSTALL); // app exist, but module may not result = ProcessBundleUpdateStatus(bundleInfo, newInfo, isReplace, installParam.GetKillProcess()); if (result == ERR_OK) { entryModuleName_ = info.second.GetCurrentModulePackage(); LOG_D(BMS_TAG_INSTALLER, "entry packageName is %{public}s", entryModuleName_.c_str()); } break; } } isEntryInstalled_ = true; return result; } ErrCode BaseBundleInstaller::DeliveryProfileToCodeSign() const { LOG_D(BMS_TAG_INSTALLER, "start to delivery sign profile to code signature"); Security::Verify::ProvisionInfo provisionInfo = verifyRes_.GetProvisionInfo(); if (provisionInfo.profileBlockLength == 0 || provisionInfo.profileBlock == nullptr) { LOG_D(BMS_TAG_INSTALLER, "Emulator does not verify signature"); return ERR_OK; } if (provisionInfo.distributionType == Security::Verify::AppDistType::ENTERPRISE || provisionInfo.distributionType == Security::Verify::AppDistType::ENTERPRISE_NORMAL || provisionInfo.distributionType == Security::Verify::AppDistType::ENTERPRISE_MDM || provisionInfo.distributionType == Security::Verify::AppDistType::INTERNALTESTING || provisionInfo.type == Security::Verify::ProvisionType::DEBUG) { return InstalldClient::GetInstance()->DeliverySignProfile(provisionInfo.bundleInfo.bundleName, provisionInfo.profileBlockLength, provisionInfo.profileBlock.get()); } return ERR_OK; } ErrCode BaseBundleInstaller::RemoveProfileFromCodeSign(const std::string &bundleName) const { LOG_D(BMS_TAG_INSTALLER, "remove sign profile of bundle %{public}s from code signature", bundleName.c_str()); return InstalldClient::GetInstance()->RemoveSignProfile(bundleName); } void BaseBundleInstaller::DeleteOldNativeLibraryPath() const { std::string oldLibPath = Constants::BUNDLE_CODE_DIR + ServiceConstants::PATH_SEPARATOR + bundleName_ + ServiceConstants::PATH_SEPARATOR + ServiceConstants::LIBS; if (InstalldClient::GetInstance()->RemoveDir(oldLibPath) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "bundleNmae: %{public}s remove old libs dir failed", bundleName_.c_str()); } } void BaseBundleInstaller::RemoveTempPathOnlyUsedForSo(const InnerBundleInfo &innerBundleInfo) const { LOG_D(BMS_TAG_INSTALLER, "start"); std::string tempDir; tempDir.append(Constants::BUNDLE_CODE_DIR).append(ServiceConstants::PATH_SEPARATOR) .append(innerBundleInfo.GetBundleName()).append(ServiceConstants::PATH_SEPARATOR) .append(innerBundleInfo.GetCurrentModulePackage()) .append(ServiceConstants::TMP_SUFFIX); bool isDirEmpty = false; if (InstalldClient::GetInstance()->IsDirEmpty(tempDir, isDirEmpty) != ERR_OK) { LOG_W(BMS_TAG_INSTALLER, "IsDirEmpty failed"); } if (isDirEmpty && (InstalldClient::GetInstance()->RemoveDir(tempDir) != ERR_OK)) { LOG_W(BMS_TAG_INSTALLER, "remove tmp so path:%{public}s failed", tempDir.c_str()); } LOG_D(BMS_TAG_INSTALLER, "end"); } bool BaseBundleInstaller::NeedDeleteOldNativeLib( std::unordered_map<std::string, InnerBundleInfo> &newInfos, const InnerBundleInfo &oldInfo) { if (newInfos.empty()) { LOG_D(BMS_TAG_INSTALLER, "NewInfos is null"); return false; } if (!isAppExist_) { LOG_D(BMS_TAG_INSTALLER, "No old app"); return false; } if (oldInfo.GetNativeLibraryPath().empty()) { LOG_D(BMS_TAG_INSTALLER, "Old app no library"); return false; } if ((versionCode_ > oldInfo.GetVersionCode())) { LOG_D(BMS_TAG_INSTALLER, "Higher versionCode"); return true; } if (oldInfo.GetApplicationBundleType() == BundleType::APP_SERVICE_FWK) { LOG_D(BMS_TAG_INSTALLER, "Appservice not delete library"); return false; } for (const auto &info : newInfos) { if (info.second.IsOnlyCreateBundleUser()) { LOG_D(BMS_TAG_INSTALLER, "Some hap no update module"); return false; } } return otaInstall_ || HasAllOldModuleUpdate(oldInfo, newInfos); } ErrCode BaseBundleInstaller::UpdateHapToken(bool needUpdate, InnerBundleInfo &newInfo) { LOG_I(BMS_TAG_INSTALLER, "UpdateHapToken %{public}s start, needUpdate:%{public}d", bundleName_.c_str(), needUpdate); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } auto bundleUserInfos = newInfo.GetInnerBundleUserInfos(); for (const auto &uerInfo : bundleUserInfos) { if (uerInfo.second.accessTokenId == 0) { continue; } Security::AccessToken::AccessTokenIDEx accessTokenIdEx; accessTokenIdEx.tokenIDEx = uerInfo.second.accessTokenIdEx; if (BundlePermissionMgr::UpdateHapToken(accessTokenIdEx, newInfo) != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "UpdateHapToken failed %{public}s", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED; } if (needUpdate) { newInfo.SetAccessTokenIdEx(accessTokenIdEx, uerInfo.second.bundleUserInfo.userId); } const std::map<std::string, InnerBundleCloneInfo> &cloneInfos = uerInfo.second.cloneInfos; for (const auto &cloneInfoPair : cloneInfos) { Security::AccessToken::AccessTokenIDEx cloneAccessTokenIdEx; cloneAccessTokenIdEx.tokenIDEx = cloneInfoPair.second.accessTokenIdEx; if (BundlePermissionMgr::UpdateHapToken(cloneAccessTokenIdEx, newInfo) != ERR_OK) { LOG_NOFUNC_E(BMS_TAG_INSTALLER, "UpdateHapToken failed %{public}s", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_GRANT_REQUEST_PERMISSIONS_FAILED; } if (needUpdate) { newInfo.SetAccessTokenIdExWithAppIndex(cloneAccessTokenIdEx, uerInfo.second.bundleUserInfo.userId, cloneInfoPair.second.appIndex); } } } if (needUpdate && !dataMgr_->UpdateInnerBundleInfo(newInfo, false)) { LOG_E(BMS_TAG_INSTALLER, "save UpdateInnerBundleInfo failed %{publlic}s", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } LOG_I(BMS_TAG_INSTALLER, "UpdateHapToken %{public}s end", bundleName_.c_str()); return ERR_OK; } #ifdef APP_DOMAIN_VERIFY_ENABLED void BaseBundleInstaller::PrepareSkillUri(const std::vector<Skill> &skills, std::vector<AppDomainVerify::SkillUri> &skillUris) const { for (const auto &skill : skills) { if (!skill.domainVerify) { continue; } for (const auto &uri : skill.uris) { if (uri.scheme != SKILL_URI_SCHEME_HTTPS) { continue; } AppDomainVerify::SkillUri skillUri; skillUri.scheme = uri.scheme; skillUri.host = uri.host; skillUri.port = uri.port; skillUri.path = uri.path; skillUri.pathStartWith = uri.pathStartWith; skillUri.pathRegex = uri.pathRegex; skillUri.type = uri.type; skillUris.push_back(skillUri); } } } #endif void BaseBundleInstaller::VerifyDomain() { #ifdef APP_DOMAIN_VERIFY_ENABLED LOG_D(BMS_TAG_INSTALLER, "start to verify domain"); InnerBundleInfo bundleInfo; bool isExist = false; if (!GetInnerBundleInfo(bundleInfo, isExist) || !isExist) { LOG_E(BMS_TAG_INSTALLER, "Get innerBundleInfo failed, bundleName: %{public}s", bundleName_.c_str()); return; } std::string appIdentifier = bundleInfo.GetAppIdentifier(); if (isAppExist_) { LOG_I(BMS_TAG_INSTALLER, "app exist, need to clear old domain info"); ClearDomainVerifyStatus(appIdentifier, bundleName_); } std::vector<AppDomainVerify::SkillUri> skillUris; std::map<std::string, std::vector<Skill>> skillInfos = bundleInfo.GetInnerSkillInfos(); for (const auto &skillInfo : skillInfos) { PrepareSkillUri(skillInfo.second, skillUris); } if (skillUris.empty()) { LOG_I(BMS_TAG_INSTALLER, "no skill uri need to verify domain"); return; } std::string fingerprint = bundleInfo.GetCertificateFingerprint(); LOG_I(BMS_TAG_INSTALLER, "start to call VerifyDomain, size of skillUris: %{public}zu", skillUris.size()); // call VerifyDomain std::string identity = IPCSkeleton::ResetCallingIdentity(); DelayedSingleton<AppDomainVerify::AppDomainVerifyMgrClient>::GetInstance()->VerifyDomain( appIdentifier, bundleName_, fingerprint, skillUris); IPCSkeleton::SetCallingIdentity(identity); #else LOG_I(BMS_TAG_INSTALLER, "app domain verify is disabled"); return; #endif } void BaseBundleInstaller::ClearDomainVerifyStatus(const std::string &appIdentifier, const std::string &bundleName) const { #ifdef APP_DOMAIN_VERIFY_ENABLED LOG_I(BMS_TAG_INSTALLER, "start to clear domain verify status"); std::string identity = IPCSkeleton::ResetCallingIdentity(); // call ClearDomainVerifyStatus if (!DelayedSingleton<AppDomainVerify::AppDomainVerifyMgrClient>::GetInstance()->ClearDomainVerifyStatus( appIdentifier, bundleName)) { LOG_W(BMS_TAG_INSTALLER, "ClearDomainVerifyStatus failed"); } IPCSkeleton::SetCallingIdentity(identity); #else LOG_I(BMS_TAG_INSTALLER, "app domain verify is disabled"); return; #endif } bool BaseBundleInstaller::IsRdDevice() const { BmsExtensionDataMgr bmsExtensionDataMgr; bool res = bmsExtensionDataMgr.IsRdDevice(); if (res) { LOG_I(BMS_TAG_INSTALLER, "current device is rd device"); return true; } return false; } ErrCode BaseBundleInstaller::CreateShaderCache(const std::string &bundleName, int32_t uid, int32_t gid) const { std::string shaderCachePath; shaderCachePath.append(ServiceConstants::SHADER_CACHE_PATH).append(bundleName); bool isExist = true; ErrCode result = InstalldClient::GetInstance()->IsExistDir(shaderCachePath, isExist); if (result != ERR_OK) { LOG_E(BMS_TAG_INSTALLER, "IsExistDir failed, error is %{public}d", result); return result; } if (isExist) { LOG_D(BMS_TAG_INSTALLER, "shaderCachePath is exist"); return ERR_OK; } LOG_I(BMS_TAG_INSTALLER, "CreateShaderCache %{public}s", shaderCachePath.c_str()); return InstalldClient::GetInstance()->Mkdir(shaderCachePath, S_IRWXU, uid, gid); } ErrCode BaseBundleInstaller::DeleteShaderCache(const std::string &bundleName) const { std::string shaderCachePath; shaderCachePath.append(ServiceConstants::SHADER_CACHE_PATH).append(bundleName); LOG_D(BMS_TAG_INSTALLER, "DeleteShaderCache %{public}s", shaderCachePath.c_str()); return InstalldClient::GetInstance()->RemoveDir(shaderCachePath); } ErrCode BaseBundleInstaller::CleanShaderCache(const std::string &bundleName) const { std::string shaderCachePath; shaderCachePath.append(ServiceConstants::SHADER_CACHE_PATH).append(bundleName); LOG_D(BMS_TAG_INSTALLER, "CleanShaderCache %{public}s", shaderCachePath.c_str()); return InstalldClient::GetInstance()->CleanBundleDataDir(shaderCachePath); } void BaseBundleInstaller::CreateCloudShader(const std::string &bundleName, int32_t uid, int32_t gid) const { const std::string cloudShaderOwner = OHOS::system::GetParameter(ServiceConstants::CLOUD_SHADER_OWNER, ""); if (cloudShaderOwner.empty() || (bundleName != cloudShaderOwner)) { return; } constexpr int32_t mode = (S_IRWXU | S_IXGRP | S_IXOTH); ErrCode result = InstalldClient::GetInstance()->Mkdir(ServiceConstants::CLOUD_SHADER_PATH, mode, uid, gid); LOG_I(BMS_TAG_INSTALLER, "Create cloud shader cache result: %{public}d", result); } std::string BaseBundleInstaller::GetCheckResultMsg() const { return bundleInstallChecker_->GetCheckResultMsg(); } void BaseBundleInstaller::SetCheckResultMsg(const std::string checkResultMsg) const { bundleInstallChecker_->SetCheckResultMsg(checkResultMsg); } bool BaseBundleInstaller::VerifyActivationLock() const { LOG_I(BMS_TAG_INSTALLER, "verify activation lock start"); int32_t mode = GetIntParameter(IS_ROOT_MODE_PARAM, USER_MODE); if (mode != USER_MODE) { char enableActivationLock[BMS_ACTIVATION_LOCK_VAL_LEN] = {0}; int32_t ret = GetParameter(BMS_ACTIVATION_LOCK, "", enableActivationLock, BMS_ACTIVATION_LOCK_VAL_LEN); if (ret <= 0) { return true; } if (std::strcmp(enableActivationLock, BMS_TRUE) != 0) { LOG_D(BMS_TAG_INSTALLER, "activation lock no check, because lock is off"); return true; } } BmsExtensionDataMgr bmsExtensionDataMgr; bool pass = false; ErrCode res = bmsExtensionDataMgr.VerifyActivationLock(pass); if ((res == ERR_OK) && !pass) { LOG_E(BMS_TAG_INSTALLER, "machine be controlled, not allow to install app"); return false; } LOG_D(BMS_TAG_INSTALLER, "activation lock pass"); // otherwise, pass return true; } bool BaseBundleInstaller::IsAppInBlocklist(const std::string &bundleName, const int32_t userId) const { BmsExtensionDataMgr bmsExtensionDataMgr; bool res = bmsExtensionDataMgr.IsAppInBlocklist(bundleName, userId); if (res) { LOG_E(BMS_TAG_INSTALLER, "app %{public}s is in blocklist", bundleName.c_str()); return true; } return false; } bool BaseBundleInstaller::CheckWhetherCanBeUninstalled(const std::string &bundleName) const { BmsExtensionDataMgr bmsExtensionDataMgr; LOG_I(BMS_TAG_INSTALLER, "CheckUninstall %{public}s", bundleName.c_str()); bool res = bmsExtensionDataMgr.CheckWhetherCanBeUninstalled(bundleName); if (!res) { LOG_E(BMS_TAG_INSTALLER, "uninstall %{public}s rejected", bundleName.c_str()); return false; } return true; } void BaseBundleInstaller::CheckBundleNameAndStratAbility(const std::string &bundleName, const std::string &appIdentifier) const { LOG_I(BMS_TAG_INSTALLER, "CheckBundleNameAndStratAbility %{public}s", bundleName.c_str()); BmsExtensionDataMgr bmsExtensionDataMgr; bmsExtensionDataMgr.CheckBundleNameAndStratAbility(bundleName, appIdentifier); } ErrCode BaseBundleInstaller::MarkInstallFinish() { InnerBundleInfo info; bool isExist = false; if (!GetInnerBundleInfo(info, isExist) || !isExist) { LOG_W(BMS_TAG_INSTALLER, "mark finish failed"); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } info.SetBundleStatus(InnerBundleInfo::BundleStatus::ENABLED); info.SetInstallMark(bundleName_, info.GetCurModuleName(), InstallExceptionStatus::INSTALL_FINISH); if (!InitDataMgr()) { return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } if (!dataMgr_->UpdateInnerBundleInfo(info, true)) { if (!dataMgr_->UpdateInnerBundleInfo(info, true)) { LOG_W(BMS_TAG_INSTALLER, "save mark failed, -n:%{public}s", bundleName_.c_str()); return ERR_APPEXECFWK_INSTALL_INTERNAL_ERROR; } } return ERR_OK; } bool BaseBundleInstaller::SetDisposedRuleWhenBundleUpdateStart( const std::unordered_map<std::string, InnerBundleInfo> &infos, const InnerBundleInfo &oldBundleInfo, bool isPreInstallApp) { #ifdef BUNDLE_FRAMEWORK_APP_CONTROL if (isPreInstallApp || !isAppExist_) { return false; } std::vector<std::string> oldModuleNames; oldBundleInfo.GetModuleNames(oldModuleNames); std::vector<std::string> newModuleNames; for (const auto &iter : infos) { iter.second.GetModuleNames(newModuleNames); } needSetDisposeRule_ = false; for (const auto &moduleName : oldModuleNames) { if (std::find(newModuleNames.begin(), newModuleNames.end(), moduleName) != newModuleNames.end()) { needSetDisposeRule_ = true; break; } } if (needSetDisposeRule_) { LOG_I(BMS_TAG_INSTALLER, "set bms disposed rule when -n :%{public}s install start", bundleName_.c_str()); std::shared_ptr<AppControlManager> appControlMgr = DelayedSingleton<AppControlManager>::GetInstance(); if (appControlMgr == nullptr) { LOG_E(BMS_TAG_INSTALLER, "appControlMgr is nullptr, when -n :%{public}s install start", bundleName_.c_str()); return false; } appControlMgr->SetDisposedRuleOnlyForBms(oldBundleInfo.GetAppId()); } return needSetDisposeRule_; #endif } bool BaseBundleInstaller::DeleteDisposedRuleWhenBundleUpdateEnd(const InnerBundleInfo &oldBundleInfo) { #ifdef BUNDLE_FRAMEWORK_APP_CONTROL if (!needSetDisposeRule_) { return false; } LOG_I(BMS_TAG_INSTALLER, "delete bms disposed rule when -n :%{public}s install end", bundleName_.c_str()); std::shared_ptr<AppControlManager> appControlMgr = DelayedSingleton<AppControlManager>::GetInstance(); if (appControlMgr == nullptr) { LOG_E(BMS_TAG_INSTALLER, "appControlMgr is nullptr, when -n :%{public}s install end", bundleName_.c_str()); return false; } appControlMgr->DeleteDisposedRuleOnlyForBms(oldBundleInfo.GetAppId()); return true; #endif } void BaseBundleInstaller::ProcessAddResourceInfo(const InstallParam &installParam, const std::string &bundleName, int32_t userId) { if (!InitDataMgr()) { return; } if (installParam.isOTA && userId != Constants::START_USERID && dataMgr_->HasUserInstallInBundle(bundleName, Constants::START_USERID)) { return; } BundleResourceHelper::AddResourceInfoByBundleName(bundleName, userId); } ErrCode BaseBundleInstaller::CheckShellCanInstallPreApp( const std::unordered_map<std::string, InnerBundleInfo> &newInfos) { if (sysEventInfo_.callingUid != ServiceConstants::SHELL_UID) { return ERR_OK; } if (newInfos.empty()) { return ERR_OK; } std::string bundleName = newInfos.begin()->second.GetBundleName(); if (dataMgr_->IsBundleExist(bundleName)) { return ERR_OK; } PreInstallBundleInfo preInstallBundleInfo; if (!dataMgr_->GetPreInstallBundleInfo(bundleName, preInstallBundleInfo)) { return ERR_OK; } if (preInstallBundleInfo.GetBundlePaths().empty()) { LOG_NOFUNC_W(BMS_TAG_DEFAULT, "pre bundle path empty"); return ERR_OK; } std::string hapPath = preInstallBundleInfo.GetBundlePaths().front(); Security::Verify::HapVerifyResult hapVerifyResult; ErrCode verifyRes = BundleVerifyMgr::HapVerify(hapPath, hapVerifyResult); if (verifyRes != ERR_OK) { LOG_NOFUNC_W(BMS_TAG_DEFAULT, "get appId fail %{public}s", hapPath.c_str()); return ERR_OK; } Security::Verify::ProvisionInfo provisionInfo = hapVerifyResult.GetProvisionInfo(); if (CheckAppIdentifier(provisionInfo.bundleInfo.appIdentifier, newInfos.begin()->second.GetAppIdentifier(), provisionInfo.appId, newInfos.begin()->second.GetProvisionId())) { return ERR_OK; } LOG_E(BMS_TAG_DEFAULT, "%{public}s appId or appIdentifier not same with preinstalled app", newInfos.begin()->second.GetBundleName().c_str()); return ERR_APPEXECFWK_INSTALL_APPID_NOT_SAME_WITH_PREINSTALLED; } void BaseBundleInstaller::UpdateKillApplicationProcess(const InnerBundleInfo &oldInfo) { if (!InitDataMgr()) { LOG_E(BMS_TAG_INSTALLER, "DataMgr null"); return; } auto currentBundleUserIds = dataMgr_->GetUserIds(bundleName_); //kill the bundle process in all user during updating for (auto userId : currentBundleUserIds) { // kill the bundle process during updating if (!AbilityManagerHelper::UninstallApplicationProcesses( oldInfo.GetApplicationName(), oldInfo.GetUid(userId), true)) { LOG_W(BMS_TAG_INSTALLER, "fail to kill running application"); } InnerBundleUserInfo userInfo; if (!oldInfo.GetInnerBundleUserInfo(userId, userInfo)) { LOG_W(BMS_TAG_INSTALLER, "the origin application is not installed at current user"); continue; } for (auto &cloneInfo : userInfo.cloneInfos) { if (!AbilityManagerHelper::UninstallApplicationProcesses( oldInfo.GetApplicationName(), cloneInfo.second.uid, true, atoi(cloneInfo.first.c_str()))) { LOG_W(BMS_TAG_INSTALLER, "fail to kill clone application"); } } } } } // namespace AppExecFwk } // namespace OHOS