X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fsecurity-manager-tests%2Fcommon%2Fsm_commons.cpp;h=b8b389b07313f27e53979776712064bf8c8fe07a;hb=73f509909a3e4942cc60efbe5963e3bcac9cd7d4;hp=586d82562b7b328361223fd5575114a4eaad8ab1;hpb=e8a9e5908a0d090a8c8ad65d489b902eb47b7689;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git diff --git a/src/security-manager-tests/common/sm_commons.cpp b/src/security-manager-tests/common/sm_commons.cpp index 586d825..b8b389b 100644 --- a/src/security-manager-tests/common/sm_commons.cpp +++ b/src/security-manager-tests/common/sm_commons.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 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. @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -23,110 +24,32 @@ #include #include #include +#include #include #include #include #include +#include #include +#include +#include #include #include #include #include #include -#include #include #include #include +#include #include "tzplatform.h" +#include using namespace SecurityManagerTest; -// Common const values - -const privileges_t SM_ALLOWED_PRIVILEGES = { - "http://tizen.org/privilege/display", - "http://tizen.org/privilege/nfc" -}; - -const privileges_t SM_DENIED_PRIVILEGES = { - "http://tizen.org/privilege/bluetooth", - "http://tizen.org/privilege/power" -}; - -const privileges_t SM_NO_PRIVILEGES = { -}; - -const std::vector SM_ALLOWED_GROUPS = {"db_browser", "db_alarm"}; - -const std::string uidToStr(const uid_t uid) -{ - return std::to_string(static_cast(uid)); -} - -// Common implementation details - -std::string generateProcessLabel(const std::string &appId, const std::string &pkgId, bool isHybrid) -{ - std::string label = "User::Pkg::" + pkgId; - if (isHybrid) { - label += "::App::" + appId; - } - return label; -} - -std::string generatePathRWLabel(const std::string &pkgId) -{ - return "User::Pkg::" + pkgId; -} - -std::string generatePathROLabel(const std::string &pkgId) -{ - return generatePathRWLabel(pkgId) + "::RO"; -} - -std::string generatePathSharedROLabel(const std::string &pkgId) -{ - return generatePathRWLabel(pkgId) + "::SharedRO"; -} - -std::string generatePathTrustedLabel(int64_t authorId) -{ - return "User::Author::" + std::to_string(authorId); -} - -std::string getPublicPathLabel() -{ - return "User::Home"; -} - -static std::string genPath(int app_num, const char *postfix) { - char buf[16]; - sprintf(buf, "%02d", app_num); - return TzPlatformConfig::globalAppDir() + "/sm_test_" + std::string(buf) + "_pkg_id_full/" + std::string(postfix); -} - -std::string genRWPath(int app_num) { - return genPath(app_num, "app_dir"); -} -std::string genROPath(int app_num) { - return genPath(app_num, "app_dir_ro"); -} -std::string genPublicROPath(int app_num) { - return genPath(app_num, "app_dir_public_ro"); -} - -std::string genOwnerRWOthersROPath(int app_num) { - return genPath(app_num, "app_dir_rw_others_ro"); -} - -static std::string generatePkgLabelOwnerRWothersRO(const std::string &pkgId) -{ - return "User::Pkg::" + pkgId + "::SharedRO"; -} - // Common DB/nftw checks // nftw doesn't allow passing user data to functions. Work around by using global variable @@ -217,16 +140,6 @@ int nftw_check_labels_non_app_dir(const char *fpath, const struct stat* /*sb*/, return 0; } -static int nftw_set_labels_non_app_dir(const char *fpath, const struct stat* /*sb*/, - int /*typeflag*/, struct FTW* /*ftwbuf*/) -{ - smack_lsetlabel(fpath, "canary_label", SMACK_LABEL_ACCESS); - smack_lsetlabel(fpath, "canary_label", SMACK_LABEL_EXEC); - smack_lsetlabel(fpath, nullptr, SMACK_LABEL_TRANSMUTE); - - return 0; -} - int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/, int /*typeflag*/, struct FTW* /*ftwbuf*/) { @@ -237,8 +150,6 @@ int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/, return 0; } -static const std::string SM_DENIED_PATH = TzPlatformConfig::globalAppDir() + "/non_app_dir"; - void check_app_permissions(const std::string &app_id, const std::string &pkg_id, const std::string &user, const privileges_t &allowed_privs, const privileges_t &denied_privs, bool isHybrid) @@ -270,10 +181,27 @@ void sm_app_has_privileges(const AppInstallHelper &app, } } +static void check_app(const std::string &appId, const std::string &pkgId, bool shouldBeInstalled) +{ + char *retPkgId; + int ret = security_manager_get_app_pkgid(&retPkgId, appId.c_str()); + + if (shouldBeInstalled) { + RUNNER_ASSERT_MSG(ret == SECURITY_MANAGER_SUCCESS, "The given appId is not installed."); + + if (ret == SECURITY_MANAGER_SUCCESS) { + CStringPtr retPkgIdPtr(retPkgId); + RUNNER_ASSERT_MSG(strcmp(pkgId.c_str(), retPkgId) == 0, + "The given appId does not belong to the given pkgId."); + } + } 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) { - TestSecurityManagerDatabase dbtest; - dbtest.test_db_after__app_install(app_id, pkg_id); + check_app(app_id, pkg_id, true); } static void check_app_gids(const std::string &app_id, const std::vector &allowed_gids) @@ -309,23 +237,19 @@ static const char *const ANY_USER_REPRESENTATION = "anyuser";/*this may be actua 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, - const std::vector &allowed_groups, bool isHybrid) { - TestSecurityManagerDatabase dbtest; - dbtest.test_db_after__app_install(app_id, pkg_id); + check_app(app_id, pkg_id, true); - /*Privileges should be granted to all users if root installs app*/ + /* 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); - /* Setup mapping of gids to privileges */ - /* Do this for each privilege for extra check */ - for (const auto &privilege : allowed_privs) { - dbtest.setup_privilege_groups(privilege, allowed_groups); - } + PolicyConfiguration policy; + const PolicyConfiguration::GroupVector allowed_groups = policy.privToGroup(allowed_privs); + RUNNER_ASSERT_MSG(allowed_groups.size() == allowed_privs.size(), + "Some privileges given were not found in the policy"); std::vector allowed_gids; - for (const auto &groupName : allowed_groups) { errno = 0; struct group* grp = getgrnam(groupName.c_str()); @@ -346,72 +270,24 @@ 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_path_after_install(int app_num, const char *pkgId, bool others_enabled) -{ - std::string SM_RW_PATH = genRWPath(app_num); - std::string SM_RO_PATH = genROPath(app_num); - std::string SM_PUBLIC_RO_PATH = genPublicROPath(app_num); - int result; - - nftw_expected_label = generatePathRWLabel(pkgId); - nftw_expected_transmute = true; - nftw_expected_exec = false; - - result = nftw(SM_RW_PATH.c_str(), &nftw_check_sm_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_RW_PATH); - - nftw_expected_label = generatePathRWLabel(pkgId) + "::RO"; - nftw_expected_transmute = false; - nftw_expected_exec = false; - - result = nftw(SM_RO_PATH.c_str(), &nftw_check_sm_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_RO_PATH); - - nftw_expected_label = "User::Home"; - nftw_expected_transmute = true; - nftw_expected_exec = false; - - result = nftw(SM_PUBLIC_RO_PATH.c_str(), &nftw_check_sm_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_PUBLIC_RO_PATH); - - result = nftw(SM_DENIED_PATH.c_str(), &nftw_check_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_DENIED_PATH); - - // owner RW, others RO - if(others_enabled) { - std::string SM_OWNER_RW_OTHERS_RO_PATH = genOwnerRWOthersROPath(app_num); - nftw_expected_label = generatePkgLabelOwnerRWothersRO(pkgId); - nftw_expected_transmute = true; - nftw_expected_exec = false; - - result = nftw(SM_OWNER_RW_OTHERS_RO_PATH.c_str(), &nftw_check_sm_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << SM_OWNER_RW_OTHERS_RO_PATH); - } -} - -void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, - const bool is_pkg_removed) +void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id) { - TestSecurityManagerDatabase dbtest; - dbtest.test_db_after__app_uninstall(app_id, pkg_id, is_pkg_removed); + check_app(app_id, pkg_id, false); } void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id, - const privileges_t &privileges, const bool is_pkg_removed, - bool isHybrid) + const privileges_t &privileges, bool isHybrid) { - TestSecurityManagerDatabase dbtest; - dbtest.test_db_after__app_uninstall(app_id, pkg_id, is_pkg_removed); - + check_app(app_id, pkg_id, false); - /*Privileges should not be granted anymore to any user*/ - check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, SM_NO_PRIVILEGES, privileges, isHybrid); + /* Privileges should not be granted anymore to any user */ + check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, {}, privileges, isHybrid); } std::string access_opposite(std::string &access) { static const std::map access_mapping = {{'r', 0}, {'w', 1}, {'x', 2}, {'a', 3}, {'t', 4}, {'l', 5}}; - //May write implies may lock + // May write implies may lock if (access.find('w') != std::string::npos && access.find('l') == std::string::npos) { access.append("l"); } @@ -455,157 +331,101 @@ CapsSetsUniquePtr setCaps(const char *cap_string) return caps; } -static void prepare_app_path(int app_num, bool others_enabled = false) -{ - std::string SM_RW_PATH = genRWPath(app_num); - std::string SM_RO_PATH = genROPath(app_num); - std::string SM_PUBLIC_RO_PATH = genPublicROPath(app_num); - int result; - - result = nftw(SM_RW_PATH.c_str(), &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to clean Smack labels in " << SM_RW_PATH); - - result = nftw(SM_RO_PATH.c_str(), &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to clean Smack labels in " << SM_RO_PATH); - - result = nftw(SM_PUBLIC_RO_PATH.c_str(), &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to clean Smack labels in " << SM_PUBLIC_RO_PATH); - - if(others_enabled) { - std::string SM_OWNER_RW_OTHERS_RO_PATH = genOwnerRWOthersROPath(app_num); - result = nftw(SM_OWNER_RW_OTHERS_RO_PATH.c_str(), &nftw_remove_labels, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to clean Smack labels in " << SM_OWNER_RW_OTHERS_RO_PATH); - } - - result = nftw(SM_DENIED_PATH.c_str(), &nftw_set_labels_non_app_dir, FTW_MAX_FDS, FTW_PHYS); - RUNNER_ASSERT_MSG(result == 0, "Unable to set Smack labels in " << SM_DENIED_PATH); +static int getOppositeAccessType(int accessType) { + return accessType ^ (R_OK | W_OK | X_OK); } -void prepare_app_env(int app_num, bool others_enabled) -{ - prepare_app_path(app_num, others_enabled); -} +static const std::unordered_map accessTypeToString { + std::make_pair(0, "F_OK"), + std::make_pair(1, "X_OK"), + std::make_pair(2, "W_OK"), + std::make_pair(3, "W_OK|X_OK"), + std::make_pair(4, "R_OK"), + std::make_pair(5, "R_OK|X_OK"), + std::make_pair(6, "R_OK|W_OK"), + std::make_pair(7, "R_OK|W_OK|X_OK") +}; -void install_app(const std::string &app_id, const std::string &pkg_id, uid_t uid, app_install_type type, - bool check_after) +void accessCheck(const std::string &id, const std::string &path, int accessType, + int expected) { - InstallRequest request; - request.setAppId(app_id); - request.setPkgId(pkg_id); - request.setUid(uid); - if (type != SM_APP_INSTALL_NONE) - request.setInstallType(type); - Api::install(request); - - if (check_after) - check_app_after_install(app_id, pkg_id); + RUNNER_ASSERT_MSG(::access(path.c_str(), accessType) == expected, + "access from " << id << " to path " << path + << (expected == 0 ? " not granted" : " unnecessarily granted") + << " (" << accessTypeToString.at(accessType) << ")"); } -void uninstall_app(const std::string &app_id, const std::string &pkg_id, bool expect_pkg_removed, - app_install_type type, bool check_after) -{ - InstallRequest request; - request.setAppId(app_id); - if (type != SM_APP_INSTALL_NONE) - request.setInstallType(type); - Api::uninstall(request); - - if (check_after) - check_app_after_uninstall(app_id, pkg_id, expect_pkg_removed); -} +void runAccessTest(const std::string &label, uid_t uid, gid_t gid, + const std::string &testPath, int accessType) { + auto fun = [&](){ + int oppositeAccessType = getOppositeAccessType(accessType); + ScopedProcessLabel spl(label, false); + RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(uid, gid), + "drop_root_privileges failed."); -static const std::string EXEC_FILE("exec"); -static const std::string NORMAL_FILE("normal"); -static const std::string LINK_PREFIX("link_to_"); + if (accessType != 0) + accessCheck(label, testPath, accessType, 0); + if (oppositeAccessType != 0) { + std::vector singleAccessTypes = {R_OK, W_OK, X_OK}; + for (auto singleAccessType : singleAccessTypes) + if (oppositeAccessType & singleAccessType) + accessCheck(label, testPath, singleAccessType, -1); + } + }; -static void createTestDir(const std::string &dir) -{ - mode_t dirMode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; - mode_t execFileMode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; - mode_t normalFileMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH; - - mktreeSafe(dir, dirMode); - creatSafe(dir + "/" + EXEC_FILE, execFileMode); - creatSafe(dir + "/" + NORMAL_FILE, normalFileMode); - symlinkSafe(dir + "/" + EXEC_FILE, dir + "/" + LINK_PREFIX + EXEC_FILE); - symlinkSafe(dir + "/" + NORMAL_FILE, dir + "/" + LINK_PREFIX + NORMAL_FILE); + runInChildParentWait(fun); } -static void createInnerAppDir(const std::string &dir, const std::string &nonAppDir) -{ - createTestDir(dir); +void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType) { + auto fun = [&](){ + int oppositeAccessType = getOppositeAccessType(accessType); + Api::setProcessLabel(app.getAppId()); + RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(app.getUID(), app.getGID()), + "drop_root_privileges failed."); + if (accessType != 0) + accessCheck(app.getAppId(), testPath, accessType, 0); + if (oppositeAccessType != 0) { + std::vector singleAccessTypes = {R_OK, W_OK, X_OK}; + for (auto singleAccessType : singleAccessTypes) + if (oppositeAccessType & singleAccessType) + accessCheck(app.getAppId(), testPath, singleAccessType, -1); + } + }; - symlinkSafe(nonAppDir, dir + "/" + LINK_PREFIX + "non_app_dir"); - symlinkSafe(nonAppDir + "/" + EXEC_FILE, - dir + "/" + LINK_PREFIX + "non_app_" + EXEC_FILE); - symlinkSafe(nonAppDir + "/" + NORMAL_FILE, - dir + "/" + LINK_PREFIX + "non_app_" + NORMAL_FILE); + runInChildParentWait(fun); } -static const std::string nonAppDirPath(const TemporaryTestUser &user) -{ - return TMP_DIR + "/" + user.getUserName(); +static const std::vector SM_SYSTEM_LABELS = {"System", "System::Privileged", "User"}; + +void runSystemAccessTest(uid_t uid, gid_t gid, const std::string &testPath, int accessType) { + for (const auto &label : SM_SYSTEM_LABELS) + runAccessTest(label, uid, gid, testPath, accessType); } -static void generateAppDir(const TemporaryTestUser &user, - const std::string &appId, const std::string &pkgId) -{ - const std::string dir = TzPlatformConfig::appDirPath(user, appId, pkgId); - const std::string nonAppDir = nonAppDirPath(user); +bool isAskuserDisabled() { + static bool isAskuserDisabled = false; + static bool isChecked = false; - createInnerAppDir(dir, nonAppDir); - createInnerAppDir(dir + "/.inner_dir", nonAppDir); - createInnerAppDir(dir + "/inner_dir", nonAppDir); -} + if (isChecked) + return isAskuserDisabled; -static void generateNonAppDir(const TemporaryTestUser &user) -{ - const std::string dir = nonAppDirPath(user); + std::string sysShare = TzPlatformConfig::getPath(TZ_SYS_SHARE); + std::string askDisableFile = sysShare + "/askuser_disable"; - createTestDir(dir); - createTestDir(dir + "/.inner_dir"); - createTestDir(dir + "/inner_dir"); + isAskuserDisabled = (access(askDisableFile.c_str(), F_OK) != -1); + isChecked = true; + return isAskuserDisabled; } -void createTestDirs(const TemporaryTestUser &user, - const std::string &appId, const std::string &pkgId) -{ - generateAppDir(user, appId, pkgId); - generateNonAppDir(user); +bool isPrivilegePrivacy(const std::string &priv) { + return (1 == privilege_info_is_privacy(priv.c_str())); } -void removeTestDirs(const TemporaryTestUser &user, - const std::string &appId, const std::string &pkgId) -{ - removeDir(TzPlatformConfig::appDirPath(user, appId, pkgId)); - removeDir(nonAppDirPath(user)); +int countPrivacyPrivileges(const PrivilegeVector &privs) { + return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy); } -pid_t runInChild(const std::function &process) { - pid_t pid = fork(); - RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "fork failed"); - - if (pid == 0) { - process(); - exit(EXIT_SUCCESS); - } - return pid; +int countPrivacyPrivileges(const std::vector &privs) { + return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy); } -void runInChildParentWait(const std::function &process) { - SynchronizationPipe pipe; - pid_t pid = fork(); - RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "fork failed"); - - if (pid == 0) { - pipe.claimChildEp(); - - process(); - - pipe.post(); - exit(EXIT_SUCCESS); - } else { - pipe.claimParentEp(); - pipe.wait(); - } -}