From: Dariusz Michaluk Date: Wed, 2 Aug 2017 10:50:08 +0000 (+0200) Subject: Add security_manager_prepare_app() tests X-Git-Tag: security-manager_5.5_testing~7^3~17 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0cb02322cf32cbbf4393a717bc116cff3005b8fa;p=platform%2Fcore%2Ftest%2Fsecurity-tests.git Add security_manager_prepare_app() tests Check app running in mount namespace. Change-Id: I4577197ea3f10f714c67619e371ebdf75a08979a --- diff --git a/src/security-manager-tests/test_cases_prepare_app.cpp b/src/security-manager-tests/test_cases_prepare_app.cpp index 9ddddf1..f883656 100644 --- a/src/security-manager-tests/test_cases_prepare_app.cpp +++ b/src/security-manager-tests/test_cases_prepare_app.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -41,6 +42,14 @@ const size_t THREADS = 10; const std::string APP_TEST_USER = "app_test_user"; +const std::string EXTERNAL_STORAGE_PRIVILEGE = "http://tizen.org/privilege/externalstorage"; +const std::string MEDIA_STORAGE_PRIVILEGE = "http://tizen.org/privilege/mediastorage"; + +const std::string ACCESS_DENIED_DIR_PATH = "/usr/share/security-manager/dummy"; +const std::string EXTERNAL_STORAGE_DIR_PATH = "/opt/media"; +const std::string MEDIA_STORAGE_RW_DIR_PATH = "/opt/usr/media"; +const std::string MEDIA_STORAGE_RO_DIR_PATH = "/opt/usr/home/app_test_user/media"; + typedef std::unique_ptr<_cap_struct, decltype(&cap_free)> CapPtr; std::string thread_errors; @@ -131,6 +140,34 @@ int setLauncherSecurityAttributes(TemporaryTestUser &user) return ret; } +ino_t getFileInode(const std::string &path) +{ + struct stat st; + if (stat(path.c_str(), &st) != 0) + return 0; + + return st.st_ino; +} + +std::string getTextFileContents(const std::string &path) +{ + std::ifstream in(path.c_str()); + if (in.fail()) + return std::string(); + std::stringstream ss; + ss << in.rdbuf(); + return ss.str(); +} + +bool isPathBound(const std::string &what, const std::string &where, pid_t pid = 1) +{ + std::string mountinfoPath = std::string("/proc/") + std::to_string(pid) + "/mountinfo"; + std::string mountinfo = getTextFileContents(mountinfoPath); + std::string line = what + " " + where; + + return std::string::npos != mountinfo.find(line); +} + } // anonymous namespace RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_PREPARE_APP) @@ -163,3 +200,162 @@ RUNNER_CHILD_TEST(security_manager_100_synchronize_credentials_test) waitPid(pid); } } + +RUNNER_CHILD_TEST(security_manager_101_create_namespace_test) +{ + TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false); + tmpUser.create(); + + AppInstallHelper app("app101", tmpUser.getUid()); + ScopedInstaller appInstall(app); + + SynchronizationPipe synchPipe; + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed"); + if (pid == 0) { + synchPipe.claimParentEp(); + RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); + + Api::prepareApp(app.getAppId().c_str()); + synchPipe.post(); + synchPipe.wait(); + + exit(0); + } else { + synchPipe.claimChildEp(); + synchPipe.wait(); + + std::string appBindPath = std::string("/var/run/user/") + std::to_string(tmpUser.getUid()) + + "/apps/" + app.getAppId(); + std::string appProcPath = std::string("/proc/") + std::to_string(pid) + "/ns/mnt"; + std::string launcherProcPath = std::string("/proc/") + std::to_string(getpid()) + "/ns/mnt"; + + ino_t appBindInode = getFileInode(appBindPath); + ino_t appProcInode = getFileInode(appProcPath); + ino_t launcherProcInode = getFileInode(launcherProcPath); + + RUNNER_ASSERT_ERRNO_MSG(appBindInode != 0, "get inode failed"); + RUNNER_ASSERT_ERRNO_MSG(appProcInode != 0, "get inode failed"); + RUNNER_ASSERT_ERRNO_MSG(launcherProcInode != 0, "get inode failed"); + + RUNNER_ASSERT_ERRNO_MSG(launcherProcInode != appProcInode, "create mount namespace failed"); + RUNNER_ASSERT_ERRNO_MSG(appBindInode == appProcInode, "bind namespace failed"); + + synchPipe.post(); + waitPid(pid); + } +} + +RUNNER_CHILD_TEST(security_manager_102_check_propagation_test) +{ + TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false); + tmpUser.create(); + + AppInstallHelper app("app102", tmpUser.getUid()); + ScopedInstaller appInstall(app); + + SynchronizationPipe synchPipe; + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed"); + if (pid == 0) { + synchPipe.claimParentEp(); + RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); + + Api::prepareApp(app.getAppId().c_str()); + synchPipe.post(); + synchPipe.wait(); + + exit(0); + } else { + synchPipe.claimChildEp(); + synchPipe.wait(); + + bool result = isPathBound(ACCESS_DENIED_DIR_PATH, EXTERNAL_STORAGE_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RW_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RO_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); + + result = isPathBound(ACCESS_DENIED_DIR_PATH, EXTERNAL_STORAGE_DIR_PATH); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RW_DIR_PATH); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RO_DIR_PATH); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + + synchPipe.post(); + waitPid(pid); + } +} + +RUNNER_CHILD_TEST(security_manager_103_policy_change_test) +{ + TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false); + tmpUser.create(); + + AppInstallHelper app("app103", tmpUser.getUid()); + app.addPrivilege(EXTERNAL_STORAGE_PRIVILEGE); + app.addPrivilege(MEDIA_STORAGE_PRIVILEGE); + ScopedInstaller appInstall(app); + + SynchronizationPipe synchPipe; + pid_t pid = fork(); + RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed"); + if (pid == 0) { + synchPipe.claimParentEp(); + RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed"); + + Api::prepareApp(app.getAppId().c_str()); + synchPipe.post(); + synchPipe.wait(); + + exit(0); + } else { + synchPipe.claimChildEp(); + synchPipe.wait(); + + bool result = isPathBound(ACCESS_DENIED_DIR_PATH, EXTERNAL_STORAGE_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RW_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RO_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + + PolicyRequest policyRequest; + PolicyEntry policyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), EXTERNAL_STORAGE_PRIVILEGE); + policyEntry.setLevel("Deny"); + policyRequest.addEntry(policyEntry); + + policyEntry = PolicyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), MEDIA_STORAGE_PRIVILEGE); + policyEntry.setLevel("Deny"); + policyRequest.addEntry(policyEntry); + Api::sendPolicy(policyRequest); + + result = isPathBound(ACCESS_DENIED_DIR_PATH, EXTERNAL_STORAGE_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RW_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RO_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == true, "path is not bound"); + + policyEntry = PolicyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), EXTERNAL_STORAGE_PRIVILEGE); + policyEntry.setLevel("Allow"); + policyRequest.addEntry(policyEntry); + + policyEntry = PolicyEntry(app.getAppId(), std::to_string(tmpUser.getUid()), MEDIA_STORAGE_PRIVILEGE); + policyEntry.setLevel("Allow"); + policyRequest.addEntry(policyEntry); + Api::sendPolicy(policyRequest); + + result = isPathBound(ACCESS_DENIED_DIR_PATH, EXTERNAL_STORAGE_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RW_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + result = isPathBound(ACCESS_DENIED_DIR_PATH, MEDIA_STORAGE_RO_DIR_PATH, pid); + RUNNER_ASSERT_ERRNO_MSG(result == false, "path is bound"); + + synchPipe.post(); + waitPid(pid); + } +}