/* * Copyright (c) 2021 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 #include "accesstoken_kit.h" #include "access_token.h" #include "ipc_skeleton.h" #include "message_parcel_helper.h" #include "securec.h" #include "tokenid_kit.h" #include "update_define.h" #include "update_log.h" #include "update_service_stub.h" #include "update_system_event.h" #include "updater_sa_ipc_interface_code.h" #include "../../../interfaces/inner_api/modulemgr/include/module_manager.h" using namespace std; namespace OHOS { namespace UpdateEngine { constexpr const pid_t ROOT_UID = 0; constexpr const pid_t EDM_UID = 3057; static constexpr int32_t MAX_VECTOR_SIZE = 128; #define CALL_RESULT_TO_IPC_RESULT(callResult) ((callResult) + CALL_RESULT_OFFSET) #define RETURN_FAIL_WHEN_SERVICE_NULL(service) \ ENGINE_CHECK((service) != nullptr, return INT_CALL_IPC_ERR, "service null") #define CALL_RESULT_TO_IPC_RESULT(callResult) ((callResult) + CALL_RESULT_OFFSET) UpdateServiceStub::UpdateServiceStub() { requestFuncMap_ = { {CAST_UINT(UpdaterSaInterfaceCode::CHECK_VERSION), &UpdateServiceStub::CheckNewVersionStub}, {CAST_UINT(UpdaterSaInterfaceCode::DOWNLOAD), &UpdateServiceStub::DownloadVersionStub}, {CAST_UINT(UpdaterSaInterfaceCode::PAUSE_DOWNLOAD), &UpdateServiceStub::PauseDownloadStub}, {CAST_UINT(UpdaterSaInterfaceCode::RESUME_DOWNLOAD), &UpdateServiceStub::ResumeDownloadStub}, {CAST_UINT(UpdaterSaInterfaceCode::UPGRADE), &UpdateServiceStub::DoUpdateStub}, {CAST_UINT(UpdaterSaInterfaceCode::CLEAR_ERROR), &UpdateServiceStub::ClearErrorStub}, {CAST_UINT(UpdaterSaInterfaceCode::TERMINATE_UPGRADE), &UpdateServiceStub::TerminateUpgradeStub}, {CAST_UINT(UpdaterSaInterfaceCode::SET_POLICY), &UpdateServiceStub::SetUpgradePolicyStub}, {CAST_UINT(UpdaterSaInterfaceCode::GET_POLICY), &UpdateServiceStub::GetUpgradePolicyStub}, {CAST_UINT(UpdaterSaInterfaceCode::GET_NEW_VERSION), &UpdateServiceStub::GetNewVersionStub}, {CAST_UINT(UpdaterSaInterfaceCode::GET_NEW_VERSION_DESCRIPTION), &UpdateServiceStub::GetNewVersionDescriptionStub}, {CAST_UINT(UpdaterSaInterfaceCode::GET_CURRENT_VERSION), &UpdateServiceStub::GetCurrentVersionStub}, {CAST_UINT(UpdaterSaInterfaceCode::GET_CURRENT_VERSION_DESCRIPTION), &UpdateServiceStub::GetCurrentVersionDescriptionStub}, {CAST_UINT(UpdaterSaInterfaceCode::GET_TASK_INFO), &UpdateServiceStub::GetTaskInfoStub}, {CAST_UINT(UpdaterSaInterfaceCode::REGISTER_CALLBACK), &UpdateServiceStub::RegisterUpdateCallbackStub}, {CAST_UINT(UpdaterSaInterfaceCode::UNREGISTER_CALLBACK), &UpdateServiceStub::UnregisterUpdateCallbackStub}, {CAST_UINT(UpdaterSaInterfaceCode::CANCEL), &UpdateServiceStub::CancelStub}, {CAST_UINT(UpdaterSaInterfaceCode::FACTORY_RESET), &UpdateServiceStub::FactoryResetStub}, {CAST_UINT(UpdaterSaInterfaceCode::APPLY_NEW_VERSION), &UpdateServiceStub::ApplyNewVersionStub}, {CAST_UINT(UpdaterSaInterfaceCode::VERIFY_UPGRADE_PACKAGE), &UpdateServiceStub::VerifyUpgradePackageStub} }; } int32_t UpdateServiceStub::GetNewVersionStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); NewVersionInfo newVersionInfo = {}; BusinessError businessError = {}; int32_t ret = service->GetNewVersionInfo(upgradeInfo, newVersionInfo, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to GetNewVersionInfo"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteNewVersionInfo(reply, newVersionInfo); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::GetNewVersionDescriptionStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; VersionDigestInfo versionDigestInfo; DescriptionOptions descriptionOptions; VersionDescriptionInfo newVersionDescriptionInfo; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadVersionDigestInfo(data, versionDigestInfo); MessageParcelHelper::ReadDescriptionOptions(data, descriptionOptions); int32_t ret = service->GetNewVersionDescription(upgradeInfo, versionDigestInfo, descriptionOptions, newVersionDescriptionInfo, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to GetNewVersionDescription"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteVersionDescriptionInfo(reply, newVersionDescriptionInfo); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::GetCurrentVersionStub(UpdateServiceStubPtr service, MessageParcel &data, MessageParcel &reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); CurrentVersionInfo currentVersionInfo = {}; BusinessError businessError = {}; int32_t ret = service->GetCurrentVersionInfo(upgradeInfo, currentVersionInfo, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to GetCurrentVersion"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteCurrentVersionInfo(reply, currentVersionInfo); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::GetCurrentVersionDescriptionStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; DescriptionOptions descriptionOptions; VersionDescriptionInfo currentVersionDescriptionInfo; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadDescriptionOptions(data, descriptionOptions); int32_t ret = service->GetCurrentVersionDescription(upgradeInfo, descriptionOptions, currentVersionDescriptionInfo, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to GetCurrentVersionDescription"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteVersionDescriptionInfo(reply, currentVersionDescriptionInfo); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::GetTaskInfoStub(UpdateServiceStubPtr service, MessageParcel &data, MessageParcel &reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); TaskInfo taskInfo = {}; BusinessError businessError = {}; int32_t ret = service->GetTaskInfo(upgradeInfo, taskInfo, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to GetTaskInfo"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteTaskInfo(reply, taskInfo); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::CheckNewVersionStub(UpdateServiceStub::UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); BusinessError businessError; CheckResult checkResult; int res = service->CheckNewVersion(upgradeInfo, businessError, checkResult); ENGINE_CHECK(res == INT_CALL_SUCCESS, return res, "Failed to CheckNewVersion"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteCheckResult(reply, checkResult); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::DownloadVersionStub(UpdateServiceStubPtr service, MessageParcel &data, MessageParcel &reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; VersionDigestInfo versionDigestInfo; DownloadOptions downloadOptions; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadVersionDigestInfo(data, versionDigestInfo); MessageParcelHelper::ReadDownloadOptions(data, downloadOptions); int32_t ret = service->Download(upgradeInfo, versionDigestInfo, downloadOptions, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to DownloadVersion"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::PauseDownloadStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; VersionDigestInfo versionDigestInfo; PauseDownloadOptions pauseDownloadOptions; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadVersionDigestInfo(data, versionDigestInfo); MessageParcelHelper::ReadPauseDownloadOptions(data, pauseDownloadOptions); int32_t ret = service->PauseDownload(upgradeInfo, versionDigestInfo, pauseDownloadOptions, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to PauseDownload"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::ResumeDownloadStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; VersionDigestInfo versionDigestInfo; ResumeDownloadOptions resumeDownloadOptions; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadVersionDigestInfo(data, versionDigestInfo); MessageParcelHelper::ReadResumeDownloadOptions(data, resumeDownloadOptions); int32_t ret = service->ResumeDownload(upgradeInfo, versionDigestInfo, resumeDownloadOptions, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to ResumeDownload"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::DoUpdateStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; VersionDigestInfo versionDigestInfo; UpgradeOptions upgradeOptions; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadVersionDigestInfo(data, versionDigestInfo); MessageParcelHelper::ReadUpgradeOptions(data, upgradeOptions); int32_t ret = service->Upgrade(upgradeInfo, versionDigestInfo, upgradeOptions, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to Upgrade"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::ClearErrorStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; VersionDigestInfo versionDigestInfo; ClearOptions clearOptions; BusinessError businessError; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); MessageParcelHelper::ReadVersionDigestInfo(data, versionDigestInfo); MessageParcelHelper::ReadClearOptions(data, clearOptions); int32_t ret = service->ClearError(upgradeInfo, versionDigestInfo, clearOptions, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to ClearError"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::TerminateUpgradeStub(UpdateServiceStubPtr service, MessageParcel &data, MessageParcel &reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); BusinessError businessError; int32_t ret = service->TerminateUpgrade(upgradeInfo, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to TerminateUpgrade"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::SetUpgradePolicyStub(UpdateServiceStubPtr service, MessageParcel &data, MessageParcel &reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); UpgradePolicy policy = {}; MessageParcelHelper::ReadUpgradePolicy(data, policy); BusinessError businessError = {}; int32_t ret = service->SetUpgradePolicy(upgradeInfo, policy, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to SetUpgradePolicy"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::GetUpgradePolicyStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); UpgradePolicy policy = {}; BusinessError businessError = {}; int32_t ret = service->GetUpgradePolicy(upgradeInfo, policy, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to GetUpgradePolicy"); MessageParcelHelper::WriteBusinessError(reply, businessError); MessageParcelHelper::WriteUpgradePolicy(reply, policy); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::RegisterUpdateCallbackStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { ENGINE_LOGI("RegisterUpdateCallbackStub"); RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); auto remote = data.ReadRemoteObject(); ENGINE_CHECK(remote != nullptr, return INT_CALL_IPC_ERR, "Failed to read remote obj"); return service->RegisterUpdateCallback(upgradeInfo, iface_cast(remote)); } int32_t UpdateServiceStub::UnregisterUpdateCallbackStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); return service->UnregisterUpdateCallback(upgradeInfo); } int32_t UpdateServiceStub::CancelStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo {}; BusinessError businessError = {}; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); int32_t ret = service->Cancel(upgradeInfo, data.ReadInt32(), businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to cancel"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::FactoryResetStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); SYS_EVENT_SYSTEM_RESET(0, UpdateSystemEvent::RESET_START); BusinessError businessError; int32_t ret = service->FactoryReset(businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to FactoryReset"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::ApplyNewVersionStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); UpgradeInfo upgradeInfo; MessageParcelHelper::ReadUpgradeInfo(data, upgradeInfo); string miscFile = Str16ToStr8(data.ReadString16()); vector packageNames; int32_t size = data.ReadInt32(); if (size > MAX_VECTOR_SIZE) { ENGINE_LOGE("ReadComponentDescriptions size is over, size=%{public}d", size); return INT_CALL_FAIL; } for (size_t i = 0; i < static_cast(size); i++) { packageNames.emplace_back(Str16ToStr8(data.ReadString16())); } BusinessError businessError; int32_t ret = service->ApplyNewVersion(upgradeInfo, miscFile, packageNames, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to ApplyNewVersion"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } int32_t UpdateServiceStub::VerifyUpgradePackageStub(UpdateServiceStubPtr service, MessageParcel& data, MessageParcel& reply, MessageOption &option) { RETURN_FAIL_WHEN_SERVICE_NULL(service); string packagePath = Str16ToStr8(data.ReadString16()); string keyPath = Str16ToStr8(data.ReadString16()); BusinessError businessError; int32_t ret = service->VerifyUpgradePackage(packagePath, keyPath, businessError); ENGINE_CHECK(ret == INT_CALL_SUCCESS, return ret, "Failed to VerifyUpgradePackage"); MessageParcelHelper::WriteBusinessError(reply, businessError); return INT_CALL_SUCCESS; } bool UpdateServiceStub::IsCallerValid() { OHOS::Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID(); auto callerTokenType = OHOS::Security::AccessToken::AccessTokenKit::GetTokenType(callerToken); switch (callerTokenType) { case OHOS::Security::AccessToken::TypeATokenTypeEnum::TOKEN_HAP: { uint64_t callerFullTokenID = IPCSkeleton::GetCallingFullTokenID(); // hap进程只允许系统应用调用 return OHOS::Security::AccessToken::TokenIdKit::IsSystemAppByFullTokenID(callerFullTokenID); } case OHOS::Security::AccessToken::TypeATokenTypeEnum::TOKEN_NATIVE: { pid_t callerUid = IPCSkeleton::GetCallingUid(); // native进程只允许root权限和edm调用 return callerUid == ROOT_UID || callerUid == EDM_UID; } default: // 其他情况调用予以禁止 return false; } } bool UpdateServiceStub::IsPermissionGranted(uint32_t code) { Security::AccessToken::AccessTokenID callerToken = IPCSkeleton::GetCallingTokenID(); string permission = "ohos.permission.UPDATE_SYSTEM"; if (code == CAST_UINT(UpdaterSaInterfaceCode::FACTORY_RESET)) { permission = "ohos.permission.FACTORY_RESET"; } int verifyResult = Security::AccessToken::AccessTokenKit::VerifyAccessToken(callerToken, permission); bool isPermissionGranted = verifyResult == Security::AccessToken::PERMISSION_GRANTED; if (!isPermissionGranted) { ENGINE_LOGE("%{public}s not granted, code:%{public}d", permission.c_str(), code); } return isPermissionGranted; } int32_t UpdateServiceStub::OnRemoteRequest(uint32_t code, MessageParcel& data, MessageParcel& reply, MessageOption &option) { ENGINE_LOGI("UpdateServiceStub func code %{public}u", code); if (!ModuleManager::GetInstance().IsMapFuncExist(code)) { ENGINE_LOGE("UpdateServiceStub OnRemoteRequest code %{public}u not found", code); return IPCObjectStub::OnRemoteRequest(code, data, reply, option); } return ModuleManager::GetInstance().HandleFunc(code, data, reply, option); } int32_t UpdateServiceStub::HandleRemoteRequest(uint32_t code, MessageParcel &data, MessageParcel &reply, MessageOption &option) { if (data.ReadInterfaceToken() != GetDescriptor()) { ENGINE_LOGE("UpdateServiceStub ReadInterfaceToken fail"); return CALL_RESULT_TO_IPC_RESULT(INT_CALL_IPC_ERR); } if (!IsCallerValid()) { ENGINE_LOGE("UpdateServiceStub IsCallerValid false"); return CALL_RESULT_TO_IPC_RESULT(INT_NOT_SYSTEM_APP); } if (!IsPermissionGranted(code)) { ENGINE_LOGE("UpdateServiceStub code %{public}d IsPermissionGranted false", code); UpgradeInfo tmpInfo; MessageParcelHelper::ReadUpgradeInfo(data, tmpInfo); return CALL_RESULT_TO_IPC_RESULT(INT_APP_NOT_GRANTED); } auto iter = requestFuncMap_.find(code); return CALL_RESULT_TO_IPC_RESULT((this->*(iter->second))(this, data, reply, option)); } } // namespace UpdateEngine } // namespace OHOS