From b30843e110b22836b125c12aaabbb74b5d687a4e Mon Sep 17 00:00:00 2001 From: yang1946 Date: Wed, 22 Nov 2023 16:37:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=AD=BE=E5=90=8D=E6=80=A7?= =?UTF-8?q?=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: yang1946 --- interfaces/innerkits/code_sign_utils/BUILD.gn | 1 + .../include/code_sign_multi_task.h | 66 ++++++++++++++ .../code_sign_utils/include/code_sign_utils.h | 9 +- .../src/code_sign_multi_task.cpp | 89 +++++++++++++++++++ .../code_sign_utils/src/code_sign_utils.cpp | 88 +++++++++++------- interfaces/innerkits/common/include/errcode.h | 3 +- test/unittest/code_sign_utils_test.cpp | 35 ++++++-- 7 files changed, 249 insertions(+), 42 deletions(-) create mode 100644 interfaces/innerkits/code_sign_utils/include/code_sign_multi_task.h create mode 100644 interfaces/innerkits/code_sign_utils/src/code_sign_multi_task.cpp diff --git a/interfaces/innerkits/code_sign_utils/BUILD.gn b/interfaces/innerkits/code_sign_utils/BUILD.gn index 88817b0..674445f 100644 --- a/interfaces/innerkits/code_sign_utils/BUILD.gn +++ b/interfaces/innerkits/code_sign_utils/BUILD.gn @@ -22,6 +22,7 @@ ohos_shared_library("libcode_sign_utils") { sources = [ "${code_signature_root_dir}/utils/src/code_sign_block.cpp", "${code_signature_root_dir}/utils/src/file_helper.cpp", + "src/code_sign_multi_task.cpp", "src/code_sign_utils.cpp", "src/stat_utils.cpp", ] diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_multi_task.h b/interfaces/innerkits/code_sign_utils/include/code_sign_multi_task.h new file mode 100644 index 0000000..e477330 --- /dev/null +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_multi_task.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 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. + */ + +#ifndef CODE_SIGN_MULTI_TASK_H +#define CODE_SIGN_MULTI_TASK_H + +#include +#include +#include +#include +#include +#include +#include + +#include "thread_pool.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { + +typedef int32_t CallbackFunc(const std::string &path, const struct code_sign_enable_arg &arg); + +class CodeSignMultiTask { +public: + CodeSignMultiTask(); + ~CodeSignMultiTask(); + /** + * @brief Add task data for code signing + * @param targetFile hap or so real path on disk + * @param code_sign_enable_arg arg + */ + void AddTaskData(const std::string &targetFile, const struct code_sign_enable_arg &arg); + /** + * @brief Execute code signature addition task + * @param taskRet Returned execution results + * @param func Callback enable function + * @return Timed out or not + */ + bool ExecuteEnableCodeSignTask(int32_t &taskRet, CallbackFunc &func); +private: + void SortTaskData(); + void ExecuteEnableCodeSignTask(int32_t &index, int32_t &taskRet, CallbackFunc &func); +private: + std::mutex cvLock_; + std::condition_variable taskfinish_; + std::vector> enableData_; + OHOS::ThreadPool enableCodeSignTaskWorker_; + int taskCallBack_; +}; +} +} +} + +#endif \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h index 1fa5e67..681ee76 100644 --- a/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h +++ b/interfaces/innerkits/code_sign_utils/include/code_sign_utils.h @@ -54,7 +54,7 @@ public: * @param type signature file type * @return err code, see err_code.h */ - static int32_t EnforceCodeSignForApp(const std::string &path, const EntryMap &entryPathMap, FileType type); + int32_t EnforceCodeSignForApp(const std::string &path, const EntryMap &entryPathMap, FileType type); /** * @brief Enforce code signature for app with ownerID @@ -64,7 +64,7 @@ public: * @param type signature file type * @return err code, see err_code.h */ - static int32_t EnforceCodeSignForAppWithOwnerId(std::string ownerId, const std::string &path, + int32_t EnforceCodeSignForAppWithOwnerId(std::string ownerId, const std::string &path, const EntryMap &entryPathMap, FileType type); /** @@ -108,6 +108,11 @@ private: static int32_t IsFsVerityEnabled(int fd); static int32_t EnableCodeSignForFile(const std::string &path, const struct code_sign_enable_arg &arg); static void ShowCodeSignInfo(const std::string &path, const struct code_sign_enable_arg &arg); + static int32_t PathToRealPath(const std::string &path, std::string& realPath, FileType type); + static int32_t CheckOwnerId(const std::string &path, const std::string &ownerId, + const uint8_t *sigPtr, uint32_t sigSize); +private: + EntryMap storedEntryMap_; }; } } diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_multi_task.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_multi_task.cpp new file mode 100644 index 0000000..736b66a --- /dev/null +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_multi_task.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 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 "code_sign_multi_task.h" + +#include "errcode.h" +#include "log.h" + +namespace OHOS { +namespace Security { +namespace CodeSign { +constexpr uint32_t CODE_SIGN_TASK_TIMEOUT_MS = 300000;//300s +constexpr uint32_t DEFAULT_THREADS_NUM = 8; + +CodeSignMultiTask::CodeSignMultiTask(): enableCodeSignTaskWorker_("EnableCodeSign"), taskCallBack_(0) +{ +} + +CodeSignMultiTask::~CodeSignMultiTask() +{ + enableCodeSignTaskWorker_.Stop(); +} + +void CodeSignMultiTask::AddTaskData(const std::string &targetFile, const struct code_sign_enable_arg &arg) +{ + enableData_.push_back(std::pair(targetFile, arg)); +} + +bool CodeSignMultiTask::ExecuteEnableCodeSignTask(int32_t &taskRet, CallbackFunc &func) +{ + SortTaskData(); + for (int32_t i = 0; i < enableData_.size(); i++) { + LOG_DEBUG(LABEL, "index: %{public}d, name:%{public}s, %{public}lld", + i, enableData_[i].first.c_str(), enableData_[i].second.data_size); + ExecuteEnableCodeSignTask(i, taskRet, func); + } + enableCodeSignTaskWorker_.Start(DEFAULT_THREADS_NUM); + + std::unique_lock lock(cvLock_); + auto waitStatus = taskfinish_.wait_for(lock, std::chrono::milliseconds(CODE_SIGN_TASK_TIMEOUT_MS), + [this]() { return this->enableData_.size() == this->taskCallBack_; }); + return waitStatus; +} + +bool cmp(const std::pair &a, const std::pair &b) +{ + return a.second.data_size > b.second.data_size; +} + +void CodeSignMultiTask::SortTaskData() +{ + sort(enableData_.begin(), enableData_.end(), cmp); +} + +void CodeSignMultiTask::ExecuteEnableCodeSignTask(int32_t &index, int32_t &taskRet, CallbackFunc &func) +{ + auto enableCodeSignTask = [this, &index, &func, &taskRet]() { + LOG_DEBUG(LABEL, "ExecuteEnableCodeSignTask task called"); + if (taskRet != CS_SUCCESS) { + std::unique_lock lock(cvLock_); + this->taskCallBack_++; + return; + } + + int32_t enableRet = func(this->enableData_[index].first, this->enableData_[index].second); + + std::unique_lock lock(cvLock_); + taskRet = taskRet | enableRet; + if (++this->taskCallBack_ == this->enableData_.size()) { + this->taskfinish_.notify_one(); + } + }; + enableCodeSignTaskWorker_.AddTask(enableCodeSignTask); +} +} +} +} \ No newline at end of file diff --git a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp index efdc273..2b2cca1 100644 --- a/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp +++ b/interfaces/innerkits/code_sign_utils/src/code_sign_utils.cpp @@ -31,6 +31,7 @@ #include "cs_hisysevent.h" #include "cs_hitrace.h" #include "constants.h" +#include "code_sign_multi_task.h" #include "directory_ex.h" #include "extractor.h" #include "file_helper.h" @@ -227,31 +228,53 @@ void CodeSignUtils::ShowCodeSignInfo(const std::string &path, const struct code_ rootHashPtr[0], rootHashPtr[1], rootHashPtr[2], rootHashPtr[32], rootHashPtr[63]); // 2, 32, 63 data index } -int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(std::string ownerId, const std::string &path, - const EntryMap &entryPathMap, FileType type) +int32_t CodeSignUtils::CheckOwnerId(const std::string &path, const std::string &ownerId, + const uint8_t *sigPtr, uint32_t sigSize) { - int32_t ret; - std::string realPath; - - if (!OHOS::PathToRealPath(path, realPath)) { - return CS_ERR_FILE_PATH; + if (ownerId.empty()) { + return CS_SUCCESS; } - if (type >= FILE_TYPE_MAX) { - return CS_ERR_PARAM_INVALID; + int32_t ret; + ByteBuffer sigBuffer; + sigBuffer.CopyFrom(reinterpret_cast(sigPtr), sigSize); + std::string retId; + ret = SignerInfo::ParseOwnerIdFromSignature(sigBuffer, retId); + if (ret != CS_SUCCESS) { + ReportInvalidOwner(path, ownerId, "invalid"); + LOG_ERROR(LABEL, "get ownerId from signature failed, ret %{public}d", ret); + } else if (retId != ownerId) { + ret = CS_ERR_INVALID_OWNER_ID; + ReportInvalidOwner(path, ownerId, retId); + LOG_ERROR(LABEL, "invalid ownerId retId %{public}s ownerId %{public}s", retId.c_str(), ownerId.c_str()); } + return ret; +} - ret = IsSupportFsVerity(realPath); +int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(std::string ownerId, const std::string &path, + const EntryMap &entryPathMap, FileType type) +{ + std::string realPath; + int32_t ret = PathToRealPath(path, realPath, type); if (ret != CS_SUCCESS) { return ret; } - + if (type == FILE_ENTRY_ONLY || type == FILE_ALL) { + storedEntryMap_.insert(entryPathMap.begin(), entryPathMap.end()); + if (type == FILE_ENTRY_ONLY) { + return ret; + } + } CodeSignBlock codeSignBlock; - ret = codeSignBlock.ParseCodeSignBlock(realPath, entryPathMap, type); + ret = codeSignBlock.ParseCodeSignBlock(realPath, storedEntryMap_, FILE_ALL); + storedEntryMap_.clear(); if (ret != CS_SUCCESS) { + if (ret != CS_CODE_SIGN_NOT_EXISTS) { + ReportParseCodeSig(realPath, ret); + } return ret; } - + CodeSignMultiTask multiTask; do { std::string targetFile; struct code_sign_enable_arg arg = {0}; @@ -262,29 +285,21 @@ int32_t CodeSignUtils::EnforceCodeSignForAppWithOwnerId(std::string ownerId, con } else if (ret != CS_SUCCESS) { return ret; } - - if (!ownerId.empty()) { - ByteBuffer sigBuffer; - sigBuffer.CopyFrom(reinterpret_cast(arg.sig_ptr), arg.sig_size); - std::string retId; - ret = SignerInfo::ParseOwnerIdFromSignature(sigBuffer, retId); - if (ret != CS_SUCCESS) { - LOG_ERROR(LABEL, "get ownerId from signature failed, ret %{public}d", ret); - break; - } else if (retId != ownerId) { - ret = CS_ERR_INVALID_OWNER_ID; - LOG_ERROR(LABEL, "invalid ownerId retId %{public}s ownerId %{public}s", retId.c_str(), ownerId.c_str()); - break; - } + ret = CheckOwnerId(path, ownerId, reinterpret_cast(arg.sig_ptr), arg.sig_size); + if (ret != CS_SUCCESS) { + return ret; } - ShowCodeSignInfo(targetFile, arg); - if (!CheckFilePathValid(targetFile, Constants::ENABLE_APP_BASE_PATH)) { return CS_ERR_TARGET_FILE_PATH; } - ret = EnableCodeSignForFile(targetFile, arg); + multiTask.AddTaskData(targetFile, arg); } while (ret == CS_SUCCESS); + bool waitStatus = multiTask.ExecuteEnableCodeSignTask(ret, EnableCodeSignForFile); + if (!waitStatus) { + LOG_ERROR(LABEL, "enable code sign timeout"); + return CS_ERR_TIMEOUT; + } return ret; } @@ -293,6 +308,19 @@ int32_t CodeSignUtils::EnforceCodeSignForApp(const std::string &path, const Entr return EnforceCodeSignForAppWithOwnerId("", path, entryPathMap, type); } +int32_t CodeSignUtils::PathToRealPath(const std::string &path, std::string& realPath, FileType type) +{ + if (!OHOS::PathToRealPath(path, realPath)) { + return CS_ERR_FILE_PATH; + } + + if (type >= FILE_TYPE_MAX) { + return CS_ERR_PARAM_INVALID; + } + + return IsSupportFsVerity(realPath); +} + int32_t CodeSignUtils::EnableKeyInProfile(const std::string &bundleName, const ByteBuffer &profileBuffer) { int ret = EnableKeyInProfileByRust(bundleName.c_str(), profileBuffer.GetBuffer(), profileBuffer.GetSize()); diff --git a/interfaces/innerkits/common/include/errcode.h b/interfaces/innerkits/common/include/errcode.h index 290090b..5725bf1 100644 --- a/interfaces/innerkits/common/include/errcode.h +++ b/interfaces/innerkits/common/include/errcode.h @@ -24,7 +24,8 @@ enum CommonErrCode { CS_ERR_MEMORY = -0x1, CS_ERR_NO_PERMISSION = -0x2, CS_ERR_NO_SIGNATURE = -0x3, - CS_ERR_INVALID_SIGNATURE = -0x4 + CS_ERR_INVALID_SIGNATURE = -0x4, + CS_ERR_TIMEOUT = -0x5 }; enum FileOperationErrCode { diff --git a/test/unittest/code_sign_utils_test.cpp b/test/unittest/code_sign_utils_test.cpp index b5ead8e..21926bd 100644 --- a/test/unittest/code_sign_utils_test.cpp +++ b/test/unittest/code_sign_utils_test.cpp @@ -442,8 +442,20 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0016, TestSize.Level0) { std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/demo_with_code_sign_block.hap"; EntryMap entryMap; + std::string profileEnablePath = PROFILE_BASE_PATH + "/demo_cert/pkcs7/verify_test_profile.p7b"; + ByteBuffer buffer; + bool flag = ReadSignatureFromFile(profileEnablePath, buffer); + EXPECT_EQ(flag, true); - int32_t ret = CodeSignUtils::EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF); + string bundlName = "CodeSignUtilsTest"; + int32_t ret = CodeSignUtils::EnableKeyInProfile(bundlName, buffer); + EXPECT_EQ(ret, CS_SUCCESS); + + CodeSignUtils utils; + ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_SELF); + EXPECT_EQ(ret, CS_SUCCESS); + + ret = CodeSignUtils::RemoveKeyInProfile(bundlName); EXPECT_EQ(ret, CS_SUCCESS); std::string filePath1("libs/arm64-v8a/libc++_shared.so"); @@ -453,10 +465,10 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0016, TestSize.Level0) std::string targetPath2 = TEST_APP_DTAT_DIR + "libs/arm64/libentry.so"; entryMap.emplace(filePath2, targetPath2); - ret = CodeSignUtils::EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ONLY); - EXPECT_EQ(ret, CS_ERR_TARGET_FILE_PATH); + ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ENTRY_ONLY); + EXPECT_EQ(ret, CS_SUCCESS); - ret = CodeSignUtils::EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ALL); + ret = utils.EnforceCodeSignForApp(hapRealPath, entryMap, FILE_ALL); EXPECT_EQ(ret, CS_ERR_TARGET_FILE_PATH); } @@ -470,7 +482,8 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0017, TestSize.Level0) { std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap"; EntryMap entryMap; - int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID", hapRealPath, entryMap, FILE_SELF); + CodeSignUtils utils; + int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("DEBUG_LIB_ID", hapRealPath, entryMap, FILE_SELF); EXPECT_EQ(ret, CS_SUCCESS); } @@ -484,7 +497,8 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0018, TestSize.Level0) { std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap"; EntryMap entryMap; - int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("test-app-identifier", + CodeSignUtils utils; + int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("test-app-identifier", hapRealPath, entryMap, FILE_SELF); EXPECT_EQ(ret, CS_SUCCESS); } @@ -499,7 +513,8 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0019, TestSize.Level0) { std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-debug.hap"; EntryMap entryMap; - int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF); + CodeSignUtils utils; + int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF); EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID); } @@ -513,7 +528,8 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0020, TestSize.Level0) { std::string hapRealPath = APP_BASE_PATH + "/demo_with_multi_lib/entry-default-signed-release.hap"; EntryMap entryMap; - int32_t ret = CodeSignUtils::EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF); + CodeSignUtils utils; + int32_t ret = utils.EnforceCodeSignForAppWithOwnerId("INVALID_ID", hapRealPath, entryMap, FILE_SELF); EXPECT_EQ(ret, CS_ERR_INVALID_OWNER_ID); } @@ -536,7 +552,8 @@ HWTEST_F(CodeSignUtilsTest, CodeSignUtilsTest_0021, TestSize.Level0) EXPECT_EQ(ret, CS_SUCCESS); EntryMap entryMap; - ret = CodeSignUtils::EnforceCodeSignForApp(hapEnablePath, entryMap, FILE_SELF); + CodeSignUtils utils; + ret = utils.EnforceCodeSignForApp(hapEnablePath, entryMap, FILE_SELF); EXPECT_EQ(ret, CS_SUCCESS); } -- Gitee