Add security_manager_prepare_app() tests 08/142608/9
authorDariusz Michaluk <d.michaluk@samsung.com>
Wed, 2 Aug 2017 10:50:08 +0000 (12:50 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Fri, 20 Oct 2017 08:39:29 +0000 (10:39 +0200)
Check app running in mount namespace.

Change-Id: I4577197ea3f10f714c67619e371ebdf75a08979a

src/security-manager-tests/test_cases_prepare_app.cpp

index 9ddddf1..f883656 100644 (file)
@@ -22,6 +22,7 @@
 #include <string>
 #include <memory>
 #include <mutex>
+#include <fstream>
 
 #include <dpl/test/test_runner_child.h>
 #include <dpl/test/test_runner.h>
@@ -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);
+    }
+}