Refactor security_manager_create_namespace_internal() 57/166757/4
authorDariusz Michaluk <d.michaluk@samsung.com>
Thu, 11 Jan 2018 15:39:44 +0000 (16:39 +0100)
committerDariusz Michaluk <d.michaluk@samsung.com>
Wed, 17 Jan 2018 18:08:30 +0000 (19:08 +0100)
This change reduces the number of IPCs and SQL queries needed to setup mount namespace.
The goal is to reduce the application start time.

Change-Id: Ib6ee820f097f07add9228346cd9a191abb16a97c

src/client/client-security-manager.cpp
src/common/include/protocols.h
src/common/include/service_impl.h
src/common/service_impl.cpp
src/server/service/include/service.h
src/server/service/service.cpp

index 92fad32..672bc43 100644 (file)
@@ -774,25 +774,22 @@ int security_manager_drop_process_privileges(void)
     return SECURITY_MANAGER_SUCCESS;
 }
 
-static inline int security_manager_bind_namespace_internal(const char *app_name)
+static int setupMountNamespace(const std::string appName, std::vector<std::pair<std::string, bool>> &privilegeStatusVector)
 {
-    using namespace SecurityManager;
-    return try_catch([&]() -> int {
-        ClientRequest request(SecurityModuleCall::APP_BIND_NAMESPACE);
-        return request.send(std::string(app_name)).getStatus();
-    });
+    ClientRequest request(SecurityModuleCall::APP_SETUP_NAMESPACE);
+    if (request.send(appName).failed())
+        return request.getStatus();
+
+    request.recv(privilegeStatusVector);
+    return SECURITY_MANAGER_SUCCESS;
 }
 
 static inline int security_manager_create_namespace_internal(const char *app_name)
 {
-    int ret, result;
-
-    if (app_name == nullptr) {
-        LogError("app_name is NULL");
-        return SECURITY_MANAGER_ERROR_INPUT_PARAM;
-    }
+    if (!MountNS::isMountNamespaceEnabled())
+        return SECURITY_MANAGER_SUCCESS;
 
-    ret = MountNS::createMountNamespace();
+    int ret = MountNS::createMountNamespace();
     if (ret != SECURITY_MANAGER_SUCCESS)
         return ret;
 
@@ -800,33 +797,32 @@ static inline int security_manager_create_namespace_internal(const char *app_nam
     if (ret != SECURITY_MANAGER_SUCCESS)
         return ret;
 
+    std::vector<std::pair<std::string, bool>> privilegeStatusVector;
+    ret = setupMountNamespace(app_name, privilegeStatusVector);
+    if (ret != SECURITY_MANAGER_SUCCESS) {
+        LogError("Failed to setup app namespace: " << security_manager_strerror(static_cast<lib_retcode>(ret)) << " App name:" << app_name);
+        return ret;
+    }
+
     auto storagePrivilegePathMap = MountNS::getPrivilegePathMap(getuid());
-    for (auto &it : storagePrivilegePathMap) {
-        ret = security_manager_app_has_privilege(app_name, it.first.c_str(), getuid(), &result);
-        if (ret != SECURITY_MANAGER_SUCCESS) {
-            LogError("Error: " << security_manager_strerror(static_cast<lib_retcode>(ret)) << " App name: " << app_name << ", " << it.first);
-            return ret;
-        }
+    for (auto &privilegeStatus : privilegeStatusVector) {
+        auto it = storagePrivilegePathMap.find(privilegeStatus.first);
+        if (it == storagePrivilegePathMap.end())
+            continue;
 
-        for (auto &privilegePath : it.second) {
+        for (auto &privilegePath : it->second) {
             if (FS::directoryStatus(privilegePath.dstPath) == 0) {
-                LogWarning("Not enforcing privilege " << it.first << " for application " << app_name << " : " <<
-                    "directory " << privilegePath.dstPath << " doesn't exist");
+                LogWarning("Not enforcing privilege " << it->first << " for application " << app_name << " : " <<
+                           "directory " << privilegePath.dstPath << " doesn't exist");
                 continue;
             }
 
-            ret = MountNS::applyPrivilegePath(result, privilegePath);
+            ret = MountNS::applyPrivilegePath(privilegeStatus.second, privilegePath);
             if (ret != SECURITY_MANAGER_SUCCESS)
                 return ret;
         }
     }
 
-    ret = security_manager_bind_namespace_internal(app_name);
-    if (ret != SECURITY_MANAGER_SUCCESS) {
-        LogError("Failed to bind app namespace: " << security_manager_strerror(static_cast<lib_retcode>(ret)) << " App name:" << app_name);
-        return ret;
-    }
-
     return SECURITY_MANAGER_SUCCESS;
 }
 
@@ -847,12 +843,10 @@ int security_manager_prepare_app(const char *app_name)
             return ret;
         }
 
-        if (MountNS::isMountNamespaceEnabled()) {
-            ret = security_manager_create_namespace_internal(app_name);
-            if (ret != SECURITY_MANAGER_SUCCESS) {
-                LogError("Unable to setup namespace for application " << app_name);
-                return ret;
-            }
+        ret = security_manager_create_namespace_internal(app_name);
+        if (ret != SECURITY_MANAGER_SUCCESS) {
+            LogError("Unable to setup namespace for application " << app_name);
+            return ret;
         }
 
         ret = security_manager_sync_threads_internal(app_name);
index dd4a29e..ad4faf7 100644 (file)
@@ -126,7 +126,7 @@ enum class SecurityModuleCall
     GET_APP_DEFINED_PRIVILEGE_PROVIDER,
     GET_APP_DEFINED_PRIVILEGE_LICENSE,
     GET_CLIENT_PRIVILEGE_LICENSE,
-    APP_BIND_NAMESPACE,
+    APP_SETUP_NAMESPACE,
     APP_CLEAN_NAMESPACE,
     NOOP = 0x90,
 };
index 5a27a7c..f9b941b 100644 (file)
@@ -293,14 +293,16 @@ public:
                                   std::string &license);
 
     /**
-     * Bind app namespace to file
+     * Setup app namespace
      *
      * @param[in]  creds    credentials of the requesting process
      * @param[in]  appName  application identifier
+     * @param[out] privilegeStatusVector returned vector of privilege-status pair
      *
      * @return API return code, as defined in protocols.h
      */
-    int appBindNamespace(const Credentials &creds, const std::string &appName);
+    int appSetupNamespace(const Credentials &creds, const std::string &appName,
+        std::vector<std::pair<std::string, bool>> &privilegeStatusVector);
 
     /**
      * Register channel for communication with worker process.
index 12f1e6b..8c669d9 100644 (file)
@@ -1973,53 +1973,74 @@ int ServiceImpl::getClientPrivilegeLicense(
     return SECURITY_MANAGER_SUCCESS;
 }
 
-int ServiceImpl::appBindNamespace(const Credentials &creds, const std::string &appName)
+int ServiceImpl::appSetupNamespace(const Credentials &creds, const std::string &appName,
+    std::vector<std::pair<std::string, bool>> &privilegeStatusVector)
 {
     int ret;
-
     if (!authenticate(creds, Config::PRIVILEGE_APP_NAMESPACE)) {
-        LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << " for app bind denied");
+        LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << " for setup app namespace denied");
         return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
     }
 
-    const std::string appProcessLabel = getAppProcessLabel(appName);
-    const std::string appsDir = MountNS::getUserAppsMountPointsPath(creds.uid);
-    const std::string appFile = MountNS::getUserAppMountPointPath(creds.uid, appProcessLabel);
-    const std::string procFile = "/proc/" + std::to_string(creds.pid) + "/ns/mnt";
+    try {
+        const std::string appProcessLabel = getAppProcessLabel(appName);
+        const std::string uidStr = std::to_string(creds.uid);
+        const std::string appsDir = MountNS::getUserAppsMountPointsPath(creds.uid);
+        const std::string appFile = MountNS::getUserAppMountPointPath(creds.uid, appProcessLabel);
+        const std::string procFile = "/proc/" + std::to_string(creds.pid) + "/ns/mnt";
+
+        if (FS::directoryStatus(appsDir) == 0) { // directory does not exist
+            ret = FS::createDirectory(appsDir);
+            if (ret != SECURITY_MANAGER_SUCCESS)
+                return ret;
 
-    if (FS::directoryStatus(appsDir) == 0) { // directory does not exist
-        ret = FS::createDirectory(appsDir);
-        if (ret != SECURITY_MANAGER_SUCCESS)
-            return ret;
+            ret = MountNS::bindMount(appsDir, appsDir);
+            if (ret != SECURITY_MANAGER_SUCCESS) {
+                FS::removeDirectory(appsDir);
+                return ret;
+            }
 
-        ret = MountNS::bindMount(appsDir, appsDir);
-        if (ret != SECURITY_MANAGER_SUCCESS) {
-            FS::removeDirectory(appsDir);
-            return ret;
+            ret = MountNS::makeMountPrivate(appsDir);
+            if (ret != SECURITY_MANAGER_SUCCESS) {
+                MountNS::uMount(appsDir);
+                FS::removeDirectory(appsDir);
+                return ret;
+            }
+        }
+
+        if (FS::fileStatus(appFile) == 0) { // file does not exist
+            ret = FS::createFile(appFile);
+            if (ret != SECURITY_MANAGER_SUCCESS)
+                return ret;
+        } else {
+            MountNS::uMount(appFile);
         }
 
-        ret = MountNS::makeMountPrivate(appsDir);
+        ret = MountNS::bindMount(procFile, appFile);
         if (ret != SECURITY_MANAGER_SUCCESS) {
-            MountNS::uMount(appsDir);
-            FS::removeDirectory(appsDir);
+            FS::removeFile(appFile);
             return ret;
         }
-    }
 
-    if (FS::fileStatus(appFile) == 0) { // file does not exist
-        ret = FS::createFile(appFile);
-        if (ret != SECURITY_MANAGER_SUCCESS)
-            return ret;
-    } else {
-        MountNS::uMount(appFile);
-    }
+        auto storagePrivilegePathMap = MountNS::getPrivilegePathMap(creds.uid);
+        for (auto &it : storagePrivilegePathMap) {
+            bool result = m_cynara.check(appProcessLabel, it.first.c_str(), uidStr, "");
+            privilegeStatusVector.push_back(make_pair(it.first, result));
+        }
 
-    ret = MountNS::bindMount(procFile, appFile);
-    if (ret != SECURITY_MANAGER_SUCCESS) {
-        FS::removeFile(appFile);
-        return ret;
+    } catch (const CynaraException::Base &e) {
+        LogError("Error while querying Cynara for permissions: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    } catch (const SmackException::InvalidLabel &e) {
+        LogError("Error while generating Smack labels: " << e.DumpToString());
+        return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+    } catch (const std::bad_alloc &e) {
+        LogError("Memory allocation failed: " << e.what());
+        return SECURITY_MANAGER_ERROR_MEMORY;
+    } catch (...) {
+        LogError("Unknown exception thrown");
+        return SECURITY_MANAGER_ERROR_UNKNOWN;
     }
-
     return SECURITY_MANAGER_SUCCESS;
 }
 
index 412f13c..1188935 100644 (file)
@@ -231,13 +231,13 @@ private:
     void processGetClientPrivilegeLicense(MessageBuffer &buffer, MessageBuffer &send);
 
     /**
-     * Process bind namespace to file
+     * Process setup app namespace
      *
      * @param  buffer Raw received data buffer
      * @param  send   Raw data buffer to be sent
      * @param  creds  credentials of the requesting process
      */
-    void processAppBindNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds);
+    void processAppSetupNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds);
 
     /**
      * Process clean app namespace
index 498d413..04dff6d 100644 (file)
@@ -161,9 +161,9 @@ bool Service::processOne(const ConnectionID &conn, MessageBuffer &buffer,
                     LogDebug("call_type: SecurityModuleCall::GET_CLIENT_PRIVILEGE_PROVIDER");
                     processGetClientPrivilegeLicense(buffer, send);
                     break;
-                case SecurityModuleCall::APP_BIND_NAMESPACE:
-                    LogDebug("call_type: SecurityModuleCall::APP_BIND_NAMESPACE");
-                    processAppBindNamespace(buffer, send, creds);
+                case SecurityModuleCall::APP_SETUP_NAMESPACE:
+                    LogDebug("call_type: SecurityModuleCall::APP_SETUP_NAMESPACE");
+                    processAppSetupNamespace(buffer, send, creds);
                     break;
                 case SecurityModuleCall::APP_CLEAN_NAMESPACE:
                     LogDebug("call_type: SecurityModuleCall::APP_CLEAN_NAMESPACE");
@@ -460,12 +460,16 @@ void Service::processGetClientPrivilegeLicense(MessageBuffer &buffer, MessageBuf
         Serialization::Serialize(send, license);
 }
 
-void Service::processAppBindNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)
+void Service::processAppSetupNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)
 {
     std::string appName;
+    std::vector<std::pair<std::string, bool>> privilegeStatusVector;
+
     Deserialization::Deserialize(buffer, appName);
-    int ret = serviceImpl.appBindNamespace(creds, appName);
+    int ret = serviceImpl.appSetupNamespace(creds, appName, privilegeStatusVector);
     Serialization::Serialize(send, ret);
+    if (ret == SECURITY_MANAGER_SUCCESS)
+        Serialization::Serialize(send, privilegeStatusVector);
 }
 
 void Service::processAppCleanNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)