From 1eb32875dae72affc475bb52741e6328ca1584a3 Mon Sep 17 00:00:00 2001 From: wangchen Date: Wed, 3 Sep 2025 17:03:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=BF=80=E6=B4=BB=E9=97=AE=E9=A2=98=E6=95=B4?= =?UTF-8?q?=E6=94=B9=20close=20#ICW6ZS=20Signed-off-by:=20wangchen=20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../unittest/src/sandbox_manager_kit_test.cpp | 170 ++++++++++++++++- .../main/cpp/include/mac/mac_adapter.h | 5 + .../cpp/include/service/policy_info_manager.h | 8 - .../main/cpp/include/service/policy_trie.h | 3 +- .../main/cpp/src/mac/mac_adapter.cpp | 174 +++++++++++++++--- .../cpp/src/service/policy_info_manager.cpp | 89 +-------- .../main/cpp/src/service/policy_trie.cpp | 23 ++- services/sandbox_manager/test/BUILD.gn | 1 + .../unittest/policy_info_manager_test.cpp | 94 +++++++++- .../test/unittest/policy_trie_test.cpp | 68 +++++++ 10 files changed, 497 insertions(+), 138 deletions(-) create mode 100644 services/sandbox_manager/test/unittest/policy_trie_test.cpp diff --git a/frameworks/inner_api/sandbox_manager/test/unittest/src/sandbox_manager_kit_test.cpp b/frameworks/inner_api/sandbox_manager/test/unittest/src/sandbox_manager_kit_test.cpp index 8cb7cc0..c069c50 100644 --- a/frameworks/inner_api/sandbox_manager/test/unittest/src/sandbox_manager_kit_test.cpp +++ b/frameworks/inner_api/sandbox_manager/test/unittest/src/sandbox_manager_kit_test.cpp @@ -1487,7 +1487,7 @@ HWTEST_F(SandboxManagerKitTest, CheckPerformanceTest001, TestSize.Level0) { std::vector policy; uint64_t policySize = 50000; - + for (uint64_t i = 0;i < policySize; i++) { PolicyInfo info; info.mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE; @@ -1923,7 +1923,7 @@ HWTEST_F(SandboxManagerKitTest, CheckPolicyTest009, TestSize.Level0) ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::SetPolicy(g_mockToken, policyA, policyFlag, policyResult)); ASSERT_EQ(1, policyResult.size()); EXPECT_EQ(OPERATE_SUCCESSFULLY, policyResult[0]); - + std::vector result; std::vector policyB; policyB.emplace_back(infoParentA); @@ -3709,7 +3709,171 @@ HWTEST_F(SandboxManagerKitTest, SetPolicyByBundleNameTest003, TestSize.Level0) } #endif +/** + * @tc.name: TestAccessing001 + * @tc.desc: test accessing appdata + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(SandboxManagerKitTest, TestAccessingPolicy001, TestSize.Level0) +{ + std::vector policy; + uint64_t policyFlag = 1; + std::vector policyResult; + PolicyInfo info1 = { + .path = "/storage/Users/currentUser/", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + policy.emplace_back(info1); + ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::SetPolicy(g_mockToken, policy, policyFlag, policyResult)); + ASSERT_EQ(1, policyResult.size()); + EXPECT_EQ(OPERATE_SUCCESSFULLY, policyResult[0]); + + std::vector retType; + EXPECT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::PersistPolicy(g_mockToken, policy, retType)); + ASSERT_EQ(1, retType.size()); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType[0]); + + PolicyInfo info2 = { + .path = "/storage/Users/currentUser/appdata/el2/base/com.ohos.dlpmanager/haps/entry/files", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + PolicyInfo info3 = { + .path = "/storage/Users/currentUser/appdata/", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + std::vector accessPolicy; + accessPolicy.emplace_back(info2); + accessPolicy.emplace_back(info3); + + EXPECT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::StartAccessingPolicy(accessPolicy, retType)); + ASSERT_EQ(2, retType.size()); + EXPECT_EQ(POLICY_HAS_NOT_BEEN_PERSISTED, retType[0]); + EXPECT_EQ(POLICY_HAS_NOT_BEEN_PERSISTED, retType[1]); + + std::vector unPersistResult; + ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::UnPersistPolicy(g_mockToken, policy, unPersistResult)); + EXPECT_EQ(1, unPersistResult.size()); + EXPECT_EQ(OPERATE_SUCCESSFULLY, unPersistResult[0]); +} + +/** + * @tc.name: TestAccessing002 + * @tc.desc: test accessing appdata + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(SandboxManagerKitTest, TestAccessingPolicy002, TestSize.Level0) +{ + std::vector policy; + uint64_t policyFlag = 1; + std::vector policyResult; + PolicyInfo info1 = { + .path = "/storage/Users/currentUser/appdata/el2/base/com.ohos.dlpmanager/haps/entry", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + PolicyInfo info2 = { + .path = "/storage/Users/currentUser/appdata/", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + policy.emplace_back(info1); + policy.emplace_back(info2); + + PolicyInfo info3 = { + .path = "/storage/Users/currentUser/appdata/el2/base/com.ohos.dlpmanager/haps/entry/files", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + std::vector accessPolicy; + accessPolicy.emplace_back(info1); + accessPolicy.emplace_back(info2); + accessPolicy.emplace_back(info3); + + ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::SetPolicy(g_mockToken, policy, policyFlag, policyResult)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, policyResult[0]); + EXPECT_EQ(INVALID_PATH, policyResult[1]); + + std::vector retType; + EXPECT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::PersistPolicy(g_mockToken, policy, retType)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType[0]); + EXPECT_EQ(FORBIDDEN_TO_BE_PERSISTED, retType[1]); + + std::vector retType1; + EXPECT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::StartAccessingPolicy(accessPolicy, retType1)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType1[0]); + EXPECT_EQ(POLICY_HAS_NOT_BEEN_PERSISTED, retType1[1]); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType1[2]); + + std::vector unPersistResult; + ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::UnPersistPolicy(g_mockToken, policy, unPersistResult)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, unPersistResult[0]); + EXPECT_EQ(POLICY_HAS_NOT_BEEN_PERSISTED, unPersistResult[1]); +} + +/** + * @tc.name: TestAccessing003 + * @tc.desc: test accessing appdata + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(SandboxManagerKitTest, TestAccessingPolicy003, TestSize.Level0) +{ + std::vector policy; + uint64_t policyFlag = 1; + std::vector policyResult; + PolicyInfo info1 = { + .path = "/storage/Users/currentUser", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + PolicyInfo info2 = { + .path = "/storage/Users/currentUser/appdata/el2/base/com.ohos.dlpmanager", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + policy.emplace_back(info1); + policy.emplace_back(info2); + + PolicyInfo info3 = { + .path = "/storage/Users/currentUser/appdata", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + PolicyInfo info4 = { + .path = "/storage/Users/currentUser/appdata/el2/base/com.ohos.dlpmanager/haps", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + std::vector accessPolicy; + accessPolicy.emplace_back(info3); + accessPolicy.emplace_back(info4); + + ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::SetPolicy(g_mockToken, policy, policyFlag, policyResult)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, policyResult[0]); + EXPECT_EQ(OPERATE_SUCCESSFULLY, policyResult[1]); + + std::vector retType; + EXPECT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::PersistPolicy(g_mockToken, policy, retType)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType[0]); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType[1]); + + std::vector retType1; + EXPECT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::StartAccessingPolicy(accessPolicy, retType1)); + EXPECT_EQ(POLICY_HAS_NOT_BEEN_PERSISTED, retType1[0]); + EXPECT_EQ(OPERATE_SUCCESSFULLY, retType1[1]); + + std::vector unPersistResult; + ASSERT_EQ(SANDBOX_MANAGER_OK, SandboxManagerKit::UnPersistPolicy(g_mockToken, policy, unPersistResult)); + EXPECT_EQ(OPERATE_SUCCESSFULLY, unPersistResult[0]); + EXPECT_EQ(OPERATE_SUCCESSFULLY, unPersistResult[1]); +} + + #endif } // SandboxManager } // AccessControl -} // OHOS \ No newline at end of file +} // OHOS diff --git a/services/sandbox_manager/main/cpp/include/mac/mac_adapter.h b/services/sandbox_manager/main/cpp/include/mac/mac_adapter.h index 5fd4864..482b467 100644 --- a/services/sandbox_manager/main/cpp/include/mac/mac_adapter.h +++ b/services/sandbox_manager/main/cpp/include/mac/mac_adapter.h @@ -45,12 +45,17 @@ public: int32_t DestroySandboxPolicy(uint32_t tokenId, uint64_t timestamp); int32_t UnSetSandboxPolicyByUser(int32_t userId, const std::vector &policy, std::vector &result); void CheckResult(std::vector &result); + int32_t CheckPathIsBlocked(const std::string &path); #ifndef NOT_RESIDENT int32_t ReadDenyFile(const char *jsonPath, std::string& rawData); int32_t SetDenyCfg(std::string& json); void DenyInit(); #endif private: + std::vector splitPath(const std::string &path); + bool CheckPathWithinRule(const std::string &path); + int32_t SetSandboxPolicyInner(size_t offset, size_t curBatchSize, const std::vector &policy, + std::vector &result, struct SandboxPolicyInfo &info); int32_t fd_ = -1; bool isMacSupport_ = false; }; diff --git a/services/sandbox_manager/main/cpp/include/service/policy_info_manager.h b/services/sandbox_manager/main/cpp/include/service/policy_info_manager.h index 4072b9c..c54e697 100644 --- a/services/sandbox_manager/main/cpp/include/service/policy_info_manager.h +++ b/services/sandbox_manager/main/cpp/include/service/policy_info_manager.h @@ -232,12 +232,6 @@ private: * @return INVALID_PATH / INVALID_MODE / SANDBOX_MANAGER_OK */ int32_t CheckPolicyValidity(const PolicyInfo &policy); - /** - * @brief check path is in blocklist - * @param path input path - * @return INVALID_PATH / SANDBOX_MANAGER_OK - */ - int32_t CheckPathIsBlocked(const std::string &path); /** * @brief unset sandboxpolicy and record conditions * @param tokenId a given tokenId @@ -279,8 +273,6 @@ private: std::vector &results, std::vector &validIndex, std::vector &normalPolicy); uint32_t CheckBeforeSetPolicy(const std::vector &policy, std::vector &result, std::vector &validIndex, std::vector &validPolicies); - std::vector splitPath(const std::string &path); - bool CheckPathWithinRule(const std::string &path); int32_t CleanPolicyByPathlist(uint32_t tokenId, std::vector &list); }; } // namespace SandboxManager diff --git a/services/sandbox_manager/main/cpp/include/service/policy_trie.h b/services/sandbox_manager/main/cpp/include/service/policy_trie.h index 1825711..d172203 100644 --- a/services/sandbox_manager/main/cpp/include/service/policy_trie.h +++ b/services/sandbox_manager/main/cpp/include/service/policy_trie.h @@ -18,6 +18,7 @@ #include #include +#include #include #include @@ -33,7 +34,7 @@ private: inline static const uint64_t MODE_FILTER = 0b11; std::vector SplitPath(const std::string &path); bool IsPolicyMatch(uint64_t referMode, uint64_t searchMode); - + static const std::unordered_map DENIED_PATHS; std::unordered_map children_; bool isEndOfPath_ = false; uint64_t mode_ = 0; diff --git a/services/sandbox_manager/main/cpp/src/mac/mac_adapter.cpp b/services/sandbox_manager/main/cpp/src/mac/mac_adapter.cpp index ec142f8..c09d425 100644 --- a/services/sandbox_manager/main/cpp/src/mac/mac_adapter.cpp +++ b/services/sandbox_manager/main/cpp/src/mac/mac_adapter.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -289,6 +290,147 @@ void MacAdapter::CheckResult(std::vector &result) } } +// components num of "/storage/Users/currentUser/appdata/*/*" +#define MAX_CHECK_COM_NUM 6 +#define SECOND_PATH_SEGMENT 2 +const std::string ROOT_PATH = "/storage"; +const std::string APPDATA_PATH = "/storage/Users/currentUser/appdata"; +const std::string ROOT_PATH_WITH_SLASH = "/storage/"; +const std::string APPDATA_PATH_WITH_SLASH = "/storage/Users/currentUser/appdata/"; + +std::vector MacAdapter::splitPath(const std::string &path) +{ + std::vector components; + std::stringstream ss(path); + std::string component; + int comNum = 0; + while (std::getline(ss, component, '/')) { + if (!component.empty()) { + components.push_back(component); + } + if (comNum > MAX_CHECK_COM_NUM) { + break; + } + comNum++; + } + return components; +} + +bool MacAdapter::CheckPathWithinRule(const std::string &path) +{ + if ((path == ROOT_PATH) || (path == APPDATA_PATH)) { + return false; + } + + size_t ROOT_PATH_SIZE = ROOT_PATH_WITH_SLASH.length(); + // Check if the path starts with "/storage/" + if (path.substr(0, ROOT_PATH_SIZE) != ROOT_PATH_WITH_SLASH) { + return true; + } + + std::vector components = splitPath(path); + // check whether path is "/storage" or "/storage/*" + if (components.size() <= SECOND_PATH_SEGMENT) { + return false; + } + + // Check if the path is "/storage/Users/" and ensure it is followed by "currentUser" + if (components[0] == "storage" && components[1] == "Users") { + if (components[SECOND_PATH_SEGMENT] != "currentUser") { + return false; // such as "/storage/Users/a" + } + } + + // check whether path is longer than "/storage/Users/currentUser/appdata/*/*" + if (components.size() > MAX_CHECK_COM_NUM) { + return true; + } + + // Check if the path is /storage/Users/currentUser/appdata/ and ensure it has more than 2 levels + size_t APPDATA_PATH_SIZE = APPDATA_PATH_WITH_SLASH.length(); + if ((path.size() >= APPDATA_PATH_SIZE) && (path.substr(0, APPDATA_PATH_SIZE) == APPDATA_PATH_WITH_SLASH)) { + return false; + } + + return true; +} + +static std::string AdjustPath(const std::string &path) +{ + if (path.empty()) { + return path; + } + // delete '/' at the end of string + std::string retPath = path; + if (retPath.back() == '/') { + retPath.pop_back(); + } + return retPath; +} + +int32_t MacAdapter::CheckPathIsBlocked(const std::string &path) +{ + uint32_t length = path.length(); + const char *cStr = path.c_str(); + uint32_t cStrLength = strlen(cStr); + if (length != cStrLength) { + SANDBOXMANAGER_LOG_ERROR(LABEL, "path have a terminator: %{public}s, pathLen:%{public}u, cstrLen:%{public}u", + path.c_str(), length, cStrLength); + return SandboxRetType::INVALID_PATH; + } + + std::string pathTmp = AdjustPath(path); + int ret = CheckPathWithinRule(pathTmp); + if (ret != true) { + SANDBOXMANAGER_LOG_ERROR(LABEL, "path not allowed to set policy: %{public}s", path.c_str()); + return SandboxRetType::INVALID_PATH; + } + return SANDBOX_MANAGER_OK; +} + +int32_t MacAdapter::SetSandboxPolicyInner(size_t offset, size_t curBatchSize, const std::vector &policy, + std::vector &result, struct SandboxPolicyInfo &info) +{ + size_t validPathIndex = 0; + int32_t cmd = SET_POLICY_CMD; + std::vector validInd; + for (size_t i = 0; i < curBatchSize; ++i) { + if (CheckPathIsBlocked(policy[offset + i].path) != SANDBOX_MANAGER_OK) { + info.pathNum--; + result[offset + i] = INVALID_PATH; + continue; + } + validInd.emplace_back(offset + i); + info.pathInfos[validPathIndex].path = const_cast(policy[offset + i].path.c_str()); + info.pathInfos[validPathIndex].pathLen = policy[offset + i].path.length(); + info.pathInfos[validPathIndex].mode = policy[offset + i].mode; + if ((info.pathInfos[validPathIndex].mode & (OperateMode::DENY_READ_MODE | OperateMode::DENY_WRITE_MODE)) != 0) { + cmd = DENY_DEC_RULE_CMD; + } + std::string maskPath = SandboxManagerLog::MaskRealPath(info.pathInfos[validPathIndex].path); + SANDBOXMANAGER_LOG_INFO(LABEL, "Set policy paths path:%{public}s mode:%{public}u", + maskPath.c_str(), info.pathInfos[validPathIndex].mode); + validPathIndex++; + } + + if ((info.pathNum > 0) && (ioctl(fd_, cmd, &info) < 0)) { + SANDBOXMANAGER_LOG_ERROR(LABEL, "Set policy failed at batch %{public}zu, errno=%{public}d.", + offset / MAX_POLICY_NUM, errno); + return SANDBOX_MANAGER_MAC_IOCTL_ERR; + } + for (size_t i = 0; i < validPathIndex; ++i) { + size_t resultIndex = validInd[i]; + if (info.pathInfos[i].result == 0) { + std::string maskPath = SandboxManagerLog::MaskRealPath(info.pathInfos[i].path); + SANDBOXMANAGER_LOG_ERROR(LABEL, "Set policy failed at %{public}s", maskPath.c_str()); + result[resultIndex] = POLICY_MAC_FAIL; + } else { + result[resultIndex] = SANDBOX_MANAGER_OK; + } + } + return SANDBOX_MANAGER_OK; +} + int32_t MacAdapter::SetSandboxPolicy(const std::vector &policy, std::vector &result, MacParams &macParams) { @@ -301,43 +443,17 @@ int32_t MacAdapter::SetSandboxPolicy(const std::vector &policy, std: } size_t policyNum = policy.size(); - for (size_t offset = 0; offset < policyNum; offset += MAX_POLICY_NUM) { size_t curBatchSize = std::min(MAX_POLICY_NUM, policyNum - offset); - struct SandboxPolicyInfo info; info.tokenId = macParams.tokenId; info.pathNum = curBatchSize; info.persist = macParams.policyFlag == 1 ? true : false; info.timestamp = macParams.timestamp; info.userId = macParams.userId; - - int32_t cmd = SET_POLICY_CMD; - for (size_t i = 0; i < curBatchSize; ++i) { - info.pathInfos[i].path = const_cast(policy[offset + i].path.c_str()); - info.pathInfos[i].pathLen = policy[offset + i].path.length(); - info.pathInfos[i].mode = policy[offset + i].mode; - if ((info.pathInfos[i].mode & (OperateMode::DENY_READ_MODE | OperateMode::DENY_WRITE_MODE)) != 0) { - cmd = DENY_DEC_RULE_CMD; - } - std::string maskPath = SandboxManagerLog::MaskRealPath(info.pathInfos[i].path); - SANDBOXMANAGER_LOG_INFO(LABEL, "Set policy paths target:%{public}u path:%{public}s mode:%{public}d", - macParams.tokenId, maskPath.c_str(), info.pathInfos[i].mode); - } - - if (ioctl(fd_, cmd, &info) < 0) { - SANDBOXMANAGER_LOG_ERROR(LABEL, "Set policy failed at batch %{public}zu, errno=%{public}d.", - offset / MAX_POLICY_NUM, errno); - return SANDBOX_MANAGER_MAC_IOCTL_ERR; - } - for (size_t i = 0; i < curBatchSize; ++i) { - if (info.pathInfos[i].result == 0) { - std::string maskPath = SandboxManagerLog::MaskRealPath(info.pathInfos[i].path); - SANDBOXMANAGER_LOG_ERROR(LABEL, "Set policy failed at %{public}s", maskPath.c_str()); - result[offset + i] = POLICY_MAC_FAIL; - } else { - result[offset + i] = SANDBOX_MANAGER_OK; - } + int32_t ret = SetSandboxPolicyInner(offset, curBatchSize, policy, result, info); + if (ret != SANDBOX_MANAGER_OK) { + return ret; } } diff --git a/services/sandbox_manager/main/cpp/src/service/policy_info_manager.cpp b/services/sandbox_manager/main/cpp/src/service/policy_info_manager.cpp index 5171ae0..4a246a3 100644 --- a/services/sandbox_manager/main/cpp/src/service/policy_info_manager.cpp +++ b/services/sandbox_manager/main/cpp/src/service/policy_info_manager.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -360,6 +359,8 @@ int32_t PolicyInfoManager::MatchNormalPolicy(const uint32_t tokenId, const std:: if (trieTree.CheckPath(policy[i].path, policy[i].mode)) { result[i] = SandboxRetType::OPERATE_SUCCESSFULLY; } else { + std::string maskPath = SandboxManagerLog::MaskRealPath(policy[i].path.c_str()); + SANDBOXMANAGER_LOG_INFO(LABEL, "target:%{public}u path:%{public}s no persisted", tokenId, maskPath.c_str()); result[i] = SandboxRetType::POLICY_HAS_NOT_BEEN_PERSISTED; } } @@ -500,12 +501,7 @@ uint32_t PolicyInfoManager::CheckBeforeSetPolicy(const std::vector & ++invalidNum; continue; } - res = CheckPathIsBlocked(policy[index].path); - if (res != SANDBOX_MANAGER_OK) { - result[index] = static_cast(res); - ++invalidNum; - continue; - } + validIndex.emplace_back(index); validPolicies.emplace_back(policy[index]); } @@ -941,85 +937,6 @@ int32_t PolicyInfoManager::CheckPolicyValidity(const PolicyInfo &policy) return SANDBOX_MANAGER_OK; } -// components num of "/storage/Users/currentUser/appdata/*/*" -#define MAX_CHECK_COM_NUM 6 -#define SECOND_PATH_SEGMENT 2 -const std::string ROOT_PATH = "/storage"; -const std::string APPDATA_PATH = "/storage/Users/currentUser/appdata"; - -std::vector PolicyInfoManager::splitPath(const std::string &path) -{ - std::vector components; - std::stringstream ss(path); - std::string component; - int comNum = 0; - while (std::getline(ss, component, '/')) { - if (!component.empty()) { - components.push_back(component); - } - if (comNum > MAX_CHECK_COM_NUM) { - break; - } - comNum++; - } - return components; -} - -bool PolicyInfoManager::CheckPathWithinRule(const std::string &path) -{ - size_t ROOT_PATH_SIZE = ROOT_PATH.length(); - // Check if the path starts with "/storage" - if (path.substr(0, ROOT_PATH_SIZE) != ROOT_PATH) { - return true; - } - - std::vector components = splitPath(path); - // check whether path is "/storage" or "/storage/*" - if (components.size() <= SECOND_PATH_SEGMENT) { - return false; - } - - // Check if the path is "/storage/Users/" and ensure it is followed by "currentUser" - if (components[0] == "storage" && components[1] == "Users") { - if (components[SECOND_PATH_SEGMENT] != "currentUser") { - return false; // such as "/storage/Users/a" - } - } - - // check whether path is longer than "/storage/Users/currentUser/appdata/*/*" - if (components.size() > MAX_CHECK_COM_NUM) { - return true; - } - - // Check if the path is /storage/Users/currentUser/appdata and ensure it has more than 2 levels - size_t APPDATA_PATH_SIZE = APPDATA_PATH.length(); - if ((path.size() >= APPDATA_PATH_SIZE) && (path.substr(0, APPDATA_PATH_SIZE) == APPDATA_PATH)) { - return false; - } - - return true; -} - -int32_t PolicyInfoManager::CheckPathIsBlocked(const std::string &path) -{ - uint32_t length = path.length(); - const char *cStr = path.c_str(); - uint32_t cStrLength = strlen(cStr); - if (length != cStrLength) { - SANDBOXMANAGER_LOG_ERROR(LABEL, "path have a terminator: %{public}s, pathLen:%{public}u, cstrLen:%{public}u", - path.c_str(), length, cStrLength); - return SandboxRetType::INVALID_PATH; - } - - std::string pathTmp = AdjustPath(path); - int ret = CheckPathWithinRule(pathTmp); - if (ret != true) { - SANDBOXMANAGER_LOG_ERROR(LABEL, "path not allowed to set policy: %{public}s", path.c_str()); - return SandboxRetType::INVALID_PATH; - } - return SANDBOX_MANAGER_OK; -} - int32_t PolicyInfoManager::AddPolicy(const uint32_t tokenId, const std::vector &policy, std::vector &results, const uint32_t flag) { diff --git a/services/sandbox_manager/main/cpp/src/service/policy_trie.cpp b/services/sandbox_manager/main/cpp/src/service/policy_trie.cpp index 7c8df10..cb9099b 100644 --- a/services/sandbox_manager/main/cpp/src/service/policy_trie.cpp +++ b/services/sandbox_manager/main/cpp/src/service/policy_trie.cpp @@ -20,6 +20,11 @@ #include #include "policy_trie.h" +static const int DENIED_PATHS_DEEP = 4; +const std::unordered_map PolicyTrie::DENIED_PATHS = { + {"/storage/Users/currentUser/appdata", DENIED_PATHS_DEEP} +}; + void PolicyTrie::Clear() { PolicyTrie *root = this; @@ -92,15 +97,27 @@ bool PolicyTrie::CheckPath(const std::string &path, uint64_t mode) std::vector pathSegments = SplitPath(path); PolicyTrie *curNode = root; + int needLevel = 0; + for (auto &[denyPath, level] : DENIED_PATHS) { + if (path.compare(0, denyPath.length(), denyPath) == 0 && + (path.length() == denyPath.length() || path[denyPath.length()] == '/')) { + needLevel = level; + } + } + + int curLevel = 0; for (const std::string &segment : pathSegments) { if (curNode == nullptr || curNode->children_.count(segment) == 0) { return false; } + curLevel++; if (curNode->children_[segment]->isEndOfPath_) { - return IsPolicyMatch(curNode->children_[segment]->mode_, mode); - } else { - curNode = curNode->children_[segment]; + if (curLevel >= needLevel) { + return IsPolicyMatch(curNode->children_[segment]->mode_, mode); + } } + + curNode = curNode->children_[segment]; } return false; } \ No newline at end of file diff --git a/services/sandbox_manager/test/BUILD.gn b/services/sandbox_manager/test/BUILD.gn index 7bb5c6e..7bfb65d 100644 --- a/services/sandbox_manager/test/BUILD.gn +++ b/services/sandbox_manager/test/BUILD.gn @@ -70,6 +70,7 @@ ohos_unittest("libsandbox_manager_service_standard_test") { "unittest/sandbox_manager_rdb_test.cpp", "unittest/sandbox_manager_service_test.cpp", "unittest/media_path_mock_test.cpp", + "unittest/policy_trie_test.cpp", ] sources += sandbox_manager_service_src sources += sandbox_manager_service_mock_src diff --git a/services/sandbox_manager/test/unittest/policy_info_manager_test.cpp b/services/sandbox_manager/test/unittest/policy_info_manager_test.cpp index 52dd065..0cf097e 100644 --- a/services/sandbox_manager/test/unittest/policy_info_manager_test.cpp +++ b/services/sandbox_manager/test/unittest/policy_info_manager_test.cpp @@ -369,15 +369,54 @@ HWTEST_F(PolicyInfoManagerTest, PolicyInfoManagerTest008, TestSize.Level0) std::string path6 = "/storage/Users/currentUser/appdata/el6/test"; std::string path7 = "/storage/Users/currentUser/appdata/el1/base/test"; std::string path8 = "/storage/Users/currentUser/appdata/"; + std::string path9 = "/storage/Users/currentUser/appdataY"; + std::string pathA = "/storage/Users/currentUser/appdataY/"; + std::string pathB = "/storage/Users/currentUser/appdat"; + std::string pathC = "/storage/Users/currentUser/appdat/"; + + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path1)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path2)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path3)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path4)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path5)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path6)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path7)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path8)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path9)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(pathA)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(pathB)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(pathC)); +} + +/** + * @tc.name: PolicyInfoManagerTest009 + * @tc.desc: Test CheckPathIsBlocked + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PolicyInfoManagerTest, PolicyInfoManagerTest009, TestSize.Level0) +{ + std::string path1 = "/storage/"; + std::string path2 = "/storage/Users"; + std::string path3 = "/storage"; + + std::string path4 = "/storageY/"; + std::string path5 = "/storageY/Users"; + std::string path6 = "/storageY"; - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path1)); - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path2)); - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path3)); - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path4)); - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path5)); - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path6)); - EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path7)); - EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().CheckPathIsBlocked(path8)); + std::string path7 = "/storag/"; + std::string path8 = "/storag/Users"; + std::string path9 = "/storag"; + + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path1)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path2)); + EXPECT_EQ(SandboxRetType::INVALID_PATH, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path3)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path4)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path5)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path6)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path7)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path8)); + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().macAdapter_.CheckPathIsBlocked(path9)); } /** @@ -928,6 +967,45 @@ HWTEST_F(PolicyInfoManagerTest, PolicyInfoManagerTest012, TestSize.Level0) PolicyInfoManager::GetInstance().macAdapter_ = original; original = mockMacAdapter; } + +#ifdef DEC_ENABLED +/** + * @tc.name: PolicyInfoManagerTest014 + * @tc.desc: Test block list + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PolicyInfoManagerTest, PolicyInfoManagerTest014, TestSize.Level0) +{ + PolicyInfo info; + std::vector policy; + + PolicyInfo info1 = { + .path = "/storage/Users/currentUser/appdata/el2/base/test/haps/test1", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + PolicyInfo info2 = { + .path = "/storage/Users/currentUser/appdata/", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + PolicyInfo info3 = { + .path = "/storage/Users/currentUser/appdata/el2/base/test/haps/test2", + .mode = OperateMode::READ_MODE | OperateMode::WRITE_MODE + }; + + policy.emplace_back(info1); + policy.emplace_back(info2); + policy.emplace_back(info3); + std::vector setResult; + + EXPECT_EQ(SANDBOX_MANAGER_OK, PolicyInfoManager::GetInstance().SetPolicy(selfTokenId_, policy, 1, setResult)); + EXPECT_EQ(SandboxRetType::OPERATE_SUCCESSFULLY, setResult[0]); + EXPECT_EQ(SandboxRetType::INVALID_PATH, setResult[1]); + EXPECT_EQ(SandboxRetType::OPERATE_SUCCESSFULLY, setResult[2]); +} +#endif + } // SandboxManager } // AccessControl } // OHOS diff --git a/services/sandbox_manager/test/unittest/policy_trie_test.cpp b/services/sandbox_manager/test/unittest/policy_trie_test.cpp new file mode 100644 index 0000000..ff9eb1b --- /dev/null +++ b/services/sandbox_manager/test/unittest/policy_trie_test.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2023-2025 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 "sandbox_manager_log.h" +#include "policy_trie.h" +using namespace testing::ext; + +namespace OHOS { +namespace AccessControl { +namespace SandboxManager { +class PolicyTrieTest : public testing::Test { +public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); +}; + +static const int MODE_RW = 3; + +void PolicyTrieTest::SetUpTestCase(void) {} + +void PolicyTrieTest::TearDownTestCase(void) {} + +void PolicyTrieTest::SetUp(void) {} + +void PolicyTrieTest::TearDown(void) {} + +/** + * @tc.name: PolicyTrieTestInherit + * @tc.desc: Test add func + * @tc.type: FUNC + * @tc.require: + */ +HWTEST_F(PolicyTrieTest, PolicyTrieTestInherit, TestSize.Level0) +{ + PolicyTrie trie; + + trie.InsertPath("/storage/Users/currentUser/", MODE_RW); + EXPECT_EQ(trie.CheckPath("/storage/Users/currentUser/test", MODE_RW), true); + EXPECT_EQ(trie.CheckPath("/storage/Users/currentUser/appdata", MODE_RW), false); + EXPECT_EQ(trie.CheckPath("/storage/Users/currentUser/appdata/", MODE_RW), false); + EXPECT_EQ(trie.CheckPath("/storage/Users/currentUser/appdata123", MODE_RW), true); + trie.InsertPath("/storage/Users/currentUser/appdata", MODE_RW); + EXPECT_EQ(trie.CheckPath("/storage/Users/currentUser/appdata", MODE_RW), true); + EXPECT_EQ(trie.CheckPath("/storage/Users/currentUser/appdata/", MODE_RW), true); + EXPECT_EQ( + trie.CheckPath("/storage/Users/currentUser/appdata/el2/base/com.ohos.dlpmanager/haps/entry/files", MODE_RW), + true); + + trie.Clear(); +} +} // SandboxManager +} // AccessControl +} // OHOS \ No newline at end of file -- Gitee