From 12d26cee7e32837d7acec44265fddf3f7b0e917b Mon Sep 17 00:00:00 2001 From: Alicja Kluczek Date: Thu, 4 Jul 2019 12:57:32 +0200 Subject: [PATCH] Add SM tests covering many apps in single request Add tests covering installation & updating many apps in single request. Add a function checking if an app has proper Smack policy. Add a function parsing smack rules template files. Add a function creating a new app in InstallRequest class. Modify ScopedInstaller class for many apps in single request compatibility. Change-Id: I35bb9757f54b111629d45b1769ca4e53ccccd017 --- src/common/scoped_installer.h | 36 ++++++++++-- src/common/sm_request.cpp | 14 +++-- src/common/sm_request.h | 5 +- src/security-manager-tests/CMakeLists.txt | 1 + src/security-manager-tests/common/sm_commons.cpp | 58 ++++++++++++++++--- src/security-manager-tests/common/sm_commons.h | 8 ++- .../common/template_parser.cpp | 34 +++++++++++ .../common/template_parser.h | 36 ++++++++++++ src/security-manager-tests/test_cases.cpp | 65 ++++++++++++++++++++++ 9 files changed, 234 insertions(+), 23 deletions(-) create mode 100644 src/security-manager-tests/common/template_parser.cpp create mode 100644 src/security-manager-tests/common/template_parser.h diff --git a/src/common/scoped_installer.h b/src/common/scoped_installer.h index 4a0ff06..82175ce 100644 --- a/src/common/scoped_installer.h +++ b/src/common/scoped_installer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ class ScopedInstaller { public: ScopedInstaller(const AppInstallHelper &app, bool requestUid = true) - : m_appId(app.getAppId()), + : m_appIds({app.getAppId()}), m_uid(app.getUID()), m_installType(app.getInstallType()), m_shouldUninstall(true), @@ -70,9 +70,30 @@ public: SecurityManagerTest::Api::install(instReq); } + ScopedInstaller(const std::vector &appIds, const std::string &pkgId) + : m_appIds(appIds), + m_uid(0), + m_installType(SM_APP_INSTALL_NONE), + m_shouldUninstall(true), + m_requestUid(false), + m_creatorPid(getpid()) + { + SecurityManagerTest::InstallRequest instReq; + + instReq.setPkgId(pkgId); + for (unsigned int i = 0; i < appIds.size(); i++) { + if (i > 0) + instReq.nextApp(); + + instReq.setAppId(appIds[i]); + } + + SecurityManagerTest::Api::install(instReq); + } + ScopedInstaller(const ScopedInstaller &) = delete; ScopedInstaller(ScopedInstaller &&other) - : m_appId(std::move(other.m_appId)), + : m_appIds(std::move(other.m_appIds)), m_uid(other.m_uid), m_installType(other.m_installType), m_shouldUninstall(other.m_shouldUninstall), @@ -97,7 +118,12 @@ public: if (!m_shouldUninstall) return; SecurityManagerTest::InstallRequest uninstReq; - uninstReq.setAppId(m_appId); + for (unsigned int i = 0; i < m_appIds.size(); i++) { + if (i > 0) + uninstReq.nextApp(); + + uninstReq.setAppId(m_appIds[i]); + } if (m_requestUid) uninstReq.setUid(m_uid); if (m_installType != SM_APP_INSTALL_NONE) @@ -107,7 +133,7 @@ public: } protected: - std::string m_appId; + std::vector m_appIds; uid_t m_uid; app_install_type m_installType; bool m_shouldUninstall; diff --git a/src/common/sm_request.cpp b/src/common/sm_request.cpp index 6e06150..b6fa1a1 100644 --- a/src/common/sm_request.cpp +++ b/src/common/sm_request.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -70,7 +70,6 @@ void InstallRequest::setAppId(std::string appId, lib_retcode expectedResult) << " App id: " << appId << ";" << " Result: " << result << ";" << " Expected result: " << expectedResult); - m_appId = std::move(appId); } void InstallRequest::setPkgId(std::string pkgId, lib_retcode expectedResult) @@ -167,10 +166,17 @@ void InstallRequest::setHybrid(lib_retcode expectedResult) << " Expected result: " << expectedResult); } +void InstallRequest::nextApp(lib_retcode expectedResult) +{ + int result = security_manager_app_inst_req_next(m_req); + RUNNER_ASSERT_MSG((lib_retcode)result == expectedResult, + "security_manager_app_inst_req_next() returned wrong value." + << " Result: " << result << ";" + << " Expected result: " << expectedResult); +} + std::ostream& operator<<(std::ostream &os, const InstallRequest &request) { - if (!request.m_appId.empty()) - os << "app id: " << request.m_appId << "; "; if (!request.m_pkgId.empty()) os << "pkg id: " << request.m_pkgId << "; "; if (!request.m_privileges.empty()) { diff --git a/src/common/sm_request.h b/src/common/sm_request.h index 4efb5c9..d58d43e 100644 --- a/src/common/sm_request.h +++ b/src/common/sm_request.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,7 +42,6 @@ public: InstallRequest& operator=(const InstallRequest&) = delete; InstallRequest(InstallRequest &&other) : m_req(std::move(other.m_req)), - m_appId(std::move(other.m_appId)), m_pkgId(std::move(other.m_pkgId)), m_authorId(std::move(other.m_authorId)), m_privileges(std::move(other.m_privileges)), @@ -67,6 +66,7 @@ public: void setAuthorId(std::string authorId, lib_retcode expectedResult= SECURITY_MANAGER_SUCCESS); void setInstallType(const enum app_install_type &type, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS); void setHybrid(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS); + void nextApp(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS); std::string getPkgId() const { return m_pkgId; } std::string getAppTizenVersion() const { return m_tizenVer; } app_inst_req *get() { return m_req; } @@ -77,7 +77,6 @@ private: app_inst_req *m_req; std::string m_tizenVer; - std::string m_appId; std::string m_pkgId; std::string m_authorId; PrivilegeVector m_privileges; diff --git a/src/security-manager-tests/CMakeLists.txt b/src/security-manager-tests/CMakeLists.txt index 46e51d8..cf08aa4 100644 --- a/src/security-manager-tests/CMakeLists.txt +++ b/src/security-manager-tests/CMakeLists.txt @@ -57,6 +57,7 @@ SET(SEC_MGR_SOURCES ${PROJECT_SOURCE_DIR}/src/security-manager-tests/security_manager_tests.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/policy_configuration.cpp ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/sm_commons.cpp + ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/template_parser.cpp ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp ${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_admin.cpp ${PROJECT_SOURCE_DIR}/src/cynara-tests/plugins/plugins.cpp diff --git a/src/security-manager-tests/common/sm_commons.cpp b/src/security-manager-tests/common/sm_commons.cpp index b8b389b..f70a825 100644 --- a/src/security-manager-tests/common/sm_commons.cpp +++ b/src/security-manager-tests/common/sm_commons.cpp @@ -27,7 +27,9 @@ #include #include +#include #include +#include #include #include @@ -47,9 +49,12 @@ #include #include "tzplatform.h" #include +#include using namespace SecurityManagerTest; +#define CONF_DIR "/usr/share/security-manager/policy/" + // Common DB/nftw checks // nftw doesn't allow passing user data to functions. Work around by using global variable @@ -181,7 +186,43 @@ void sm_app_has_privileges(const AppInstallHelper &app, } } -static void check_app(const std::string &appId, const std::string &pkgId, bool shouldBeInstalled) +static void check_app_smack_accesses(const std::string &appId, const std::string &pkgId, + bool isHybrid = false) +{ + static const std::vector rules[] = + {parseSmackRulesFile(CONF_DIR "pkg-rules-template.smack"), + parseSmackRulesFile(CONF_DIR "app-rules-template.smack")}; + + const std::pair switchAliases[] = + {std::make_pair("~PATH_RW~", generatePathRWLabel(pkgId)), + std::make_pair("~PATH_RO~", generatePathROLabel(pkgId)), + std::make_pair("~PATH_SHARED_RO~", generatePathSharedROLabel(pkgId)), + std::make_pair("~PROCESS~", generateProcessLabel(appId, pkgId, isHybrid))}; + + for (auto rule : rules[isHybrid]) { + if (rule.object == "~PATH_TRUSTED~") { + continue; + } + + for (const auto &alias : switchAliases) { + if (rule.subject == alias.first) { + rule.subject = alias.second; + } + if (rule.object == alias.first) { + rule.object = alias.second; + } + } + + if (rule.object == "_") { + rule.access = "rx" + rule.access; + } + + check_exact_smack_accesses(rule.subject, rule.object, rule.access); + } +} + +static void check_app(const std::string &appId, const std::string &pkgId, + bool shouldBeInstalled, bool isHybrid) { char *retPkgId; int ret = security_manager_get_app_pkgid(&retPkgId, appId.c_str()); @@ -194,14 +235,15 @@ static void check_app(const std::string &appId, const std::string &pkgId, bool s RUNNER_ASSERT_MSG(strcmp(pkgId.c_str(), retPkgId) == 0, "The given appId does not belong to the given pkgId."); } + check_app_smack_accesses(appId, pkgId, isHybrid); } else { RUNNER_ASSERT_MSG(ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT, "The given appId is installed."); } } -void check_app_after_install(const std::string &app_id, const std::string &pkg_id) +void check_app_after_install(const std::string &app_id, const std::string &pkg_id, bool isHybrid) { - check_app(app_id, pkg_id, true); + check_app(app_id, pkg_id, true, isHybrid); } static void check_app_gids(const std::string &app_id, const std::vector &allowed_gids) @@ -239,8 +281,7 @@ void check_app_after_install(const std::string &app_id, const std::string &pkg_i const privileges_t &denied_privs, bool isHybrid) { - check_app(app_id, pkg_id, true); - + check_app(app_id, pkg_id, true, isHybrid); /* Privileges should be granted to all users if root installs app */ check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, allowed_privs, denied_privs, isHybrid); @@ -270,15 +311,16 @@ void check_path(const std::string &path, const std::string &label, bool transmut RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path); } -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id) +void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, + bool isHybrid) { - check_app(app_id, pkg_id, false); + check_app(app_id, pkg_id, false, isHybrid); } void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, const privileges_t &privileges, bool isHybrid) { - check_app(app_id, pkg_id, false); + check_app(app_id, pkg_id, false, isHybrid); /* Privileges should not be granted anymore to any user */ check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, {}, privileges, isHybrid); diff --git a/src/security-manager-tests/common/sm_commons.h b/src/security-manager-tests/common/sm_commons.h index 902d70c..8cd7538 100644 --- a/src/security-manager-tests/common/sm_commons.h +++ b/src/security-manager-tests/common/sm_commons.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -45,14 +45,16 @@ void check_app_permissions(const std::string &app_id, const std::string &pkg_id, void sm_app_has_privileges(const AppInstallHelper &app, const std::vector &privileges, int result); -void check_app_after_install(const std::string &app_id, const std::string &pkg_id); +void check_app_after_install(const std::string &app_id, const std::string &pkg_id, + bool isHybrid = false); void check_app_after_install(const std::string &app_id, const std::string &pkg_id, const privileges_t &allowed_privs, const privileges_t &denied_privs, bool isHybrid = false); void check_path(const std::string &path, const std::string &label, bool transmute = true, bool execute = false); -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id); +void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, + bool isHybrid = false); void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, const privileges_t &privileges, bool isHybrid = false); diff --git a/src/security-manager-tests/common/template_parser.cpp b/src/security-manager-tests/common/template_parser.cpp new file mode 100644 index 0000000..83c5b46 --- /dev/null +++ b/src/security-manager-tests/common/template_parser.cpp @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ +/* + * @file template_parser.cpp + * @author Alicja Kluczek + * @brief Parsing function for smack rules templates + */ +#include "template_parser.h" +#include + +std::vector parseSmackRulesFile(const std::string &path) +{ + std::vector rules; + std::ifstream rulesFile(path); + std::string object, subject, access; + while (rulesFile >> subject >> object >> access) { + rules.emplace_back(std::move(subject), std::move(object), std::move(access)); + } + return rules; +} + diff --git a/src/security-manager-tests/common/template_parser.h b/src/security-manager-tests/common/template_parser.h new file mode 100644 index 0000000..81a3674 --- /dev/null +++ b/src/security-manager-tests/common/template_parser.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ +/* + * @file template_parser.h + * @author Alicja Kluczek + * @brief Parsing function for smack rules templates + */ +#include +#include + +struct AccessRequest { + AccessRequest(std::string sub, std::string obj, std::string acc) + : subject(std::move(sub)), + object(std::move(obj)), + access(std::move(acc)) + {} + std::string subject; + std::string object; + std::string access; +}; + +std::vector parseSmackRulesFile(const std::string &path); + diff --git a/src/security-manager-tests/test_cases.cpp b/src/security-manager-tests/test_cases.cpp index 5bde91d..3195de3 100644 --- a/src/security-manager-tests/test_cases.cpp +++ b/src/security-manager-tests/test_cases.cpp @@ -508,6 +508,71 @@ RUNNER_TEST(security_manager_09_app_install_constraint_check) install(users[0], pkgId[0], appId[0], version[0], author[1], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM); } +RUNNER_TEST(security_manager_09a_install_many_apps_in_single_request) +{ + const std::string pkgId = "sm_test_09a_pkg_id_0"; + const std::vector appIds = {"sm_test_09a_app_id_0", "sm_test_09a_app_id_1", "sm_test_09a_app_id_2"}; + + { + ScopedInstaller appsInstall(appIds, pkgId); + // Installing many applications in single request + for (const auto &appId : appIds) { + check_app_after_install(appId, pkgId); + } + } + + for (const auto &appId : appIds) { + check_app_after_uninstall(appId, pkgId); + } +} + +RUNNER_TEST(security_manager_09b_install_many_apps_in_single_request_duplicated_ids) +{ + const std::string pkgId = "sm_test_09b_pkg_id_0"; + const std::string appId = "sm_test_09b_app_id_0"; + + { + ScopedInstaller appsInstall({appId, appId}, pkgId); + check_app_after_install(appId, pkgId); + } + + check_app_after_uninstall(appId, pkgId); +} + +RUNNER_TEST(security_manager_09c_update_many_apps_in_single_request_hybrid_package) +{ + const std::vector appIds = {"sm_test_09c_app_id_0", "sm_test_09c_app_id_1", "sm_test_09c_app_id_2"}; + const std::string pkgId = "sm_test_09c_pkg_id_0"; + + { + ScopedInstaller appsInstall(appIds, pkgId); + // Package is not hybrid, every app has same policy. + for (const auto &appId : appIds) { + check_app_after_install(appId, pkgId); + } + + // Updating package -- changing set of apps in package and setting hybrid mode + InstallRequest updateRequest; + updateRequest.setPkgId(pkgId); + updateRequest.setAppId(appIds[0]); + updateRequest.nextApp(); + updateRequest.setAppId(appIds[1]); + updateRequest.setHybrid(); + + Api::update(updateRequest); + // Package became hybrid, so every app has its own Smack label + check_app_after_install(appIds[0], pkgId, true); + check_app_after_install(appIds[1], pkgId, true); + // Package became hybrid properly, + // so app not included in updated version of package was uninstalled. + check_app_after_uninstall(appIds[2], pkgId, false); + } + + for (const auto &appId : appIds) { + check_app_after_uninstall(appId, pkgId, true); + } +} + RUNNER_CHILD_TEST(security_manager_10_app_has_privilege) { const std::vector allowedPrivs = { -- 2.7.4