Use mount namespace mount points to find running apps 49/230849/5
authorZofia Abramowska <z.abramowska@samsung.com>
Tue, 14 Apr 2020 16:49:34 +0000 (18:49 +0200)
committerZofia Abramowska <z.abramowska@samsung.com>
Mon, 20 Apr 2020 11:23:51 +0000 (13:23 +0200)
Change-Id: Ifef7a3aa2fb9666e20f428270c41850ce7319208

packaging/security-manager.spec
src/client/CMakeLists.txt
src/common/CMakeLists.txt
src/common/include/mount-namespace.h
src/common/include/service_impl.h
src/common/mount-namespace.cpp
src/common/service_impl.cpp
src/server/CMakeLists.txt

index d489f227ee68a4b9aca8ce72106fc428ae124f24..0d50227c30105ad5cc722ba14df10e20fab1c979 100644 (file)
@@ -37,7 +37,6 @@ BuildRequires: pkgconfig(cynara-client-async)
 BuildRequires: pkgconfig(security-privilege-manager)
 BuildRequires: pkgconfig(openssl1.1)
 BuildRequires: pkgconfig(mount)
-BuildRequires: pkgconfig(capi-appfw-app-manager)
 BuildRequires: boost-devel
 %{?systemd_requires}
 
index 4dfe61c2474d8b5f21295cd2f999dd9ae603972b..8862ca0bb8f4d9ba0cc69c285307154a76dbc512 100644 (file)
@@ -1,6 +1,5 @@
 PKG_CHECK_MODULES(CLIENT_DEP
     REQUIRED
-    capi-appfw-app-manager
     cynara-client-async
     libsmack
     libcap
index b37a53e4c6250dffdc905c8170a3bc79f22492ee..e978a4f606a7363754c144c455f5fd536dc954d0 100644 (file)
@@ -11,7 +11,6 @@ PKG_CHECK_MODULES(COMMON_DEP
     libtzplatform-config
     security-privilege-manager
     mount
-    capi-appfw-app-manager
     )
 
 IF(DPL_WITH_DLOG)
@@ -110,6 +109,8 @@ SET_TARGET_PROPERTIES(${TARGET_COMMON}
 TARGET_LINK_LIBRARIES(${TARGET_COMMON}
     ${COMMON_DEP_LIBRARIES}
     ${DLOG_DEP_LIBRARIES}
+    boost_filesystem
+    boost_regex
     -lcrypt
     rt
     )
index 49b5587edb36002095f52742dfe5346c373b8574..2f4bd21d40f010e8f71196c335b251def97497d7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2017-2020 Samsung Electronics Co., Ltd. All rights reserved
  *
  *  Contact: Rafal Krypa <r.krypa@samsung.com>
  *
@@ -28,6 +28,8 @@
 #include <map>
 #include <vector>
 
+#include <smack-common.h>
+
 namespace SecurityManager {
 namespace MountNS {
 
@@ -60,5 +62,12 @@ int bindMountRO(const Path &source, const Path &target);
 int uMount(const Path &target);
 bool isPathBound(const Path &what, const Path &where);
 
+struct AppContext {
+    Smack::Label appProcessLabel;
+    std::string uidStr;
+};
+
+std::vector<AppContext> getMountNSApps();
+
 } // namespace MountNS
 } // namespace SecurityManager
index 7e63ba37acf0c4925646283719c8c9d17b1f8ec5..248989d5a9a18ee4961e1422be4753f86b568155 100644 (file)
 
 #include <vector>
 
-#include <app_context.h>
-
 #include "channel.h"
 #include "credentials.h"
 #include "cynara.h"
+#include "mount-namespace.h"
 #include "nsmount-logic.h"
 #include "security-manager.h"
 #include "smack-common.h"
@@ -188,6 +187,8 @@ public:
      */
     int getAppAllowedPrivileges(const Smack::Label &appProcessLabel, uid_t uid,
                                 std::vector<std::string> &allowedPrivileges);
+    int getAppAllowedPrivileges(const Smack::Label &appProcessLabel, const std::string &uid,
+                                std::vector<std::string> &allowedPrivileges);
 
     /**
     * Process query for resources group list and supplementary groups allowed for the application.
@@ -442,8 +443,9 @@ private:
                               const Smack::Label &targetAppLabel,
                               const std::string &path);
 
-    static bool updateRunningAppSmackPolicy(app_context_h app_context, void *user_data);
-    static bool checkRunningApps(app_context_h app_context, void *user_data);
+    void updateRunningAppSmackPolicy(
+        const MountNS::AppContext &appContext,
+        const std::map<std::string, std::vector<std::string>> &appsAllowedPrivileges);
 
     void updatePermissibleSet(uid_t uid, int type);
 
index f9a48ea51a04329f97b82ea99a0855a6d0aa0ad2..21a3ed7cca9e88f386b139812ae0e8eee731881d 100644 (file)
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <boost/filesystem.hpp>
+#include <boost/regex.hpp>
+#include <string>
+
 #include <mount-namespace.h>
 #include <config.h>
 #include <config-file.h>
@@ -253,5 +257,41 @@ bool isPathBound(const Path &what, const Path &where)
     return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
 }
 
+std::vector<AppContext> getMountNSApps()
+{
+    const static std::string rootDir = getUsersAppsMountPointsPath();
+    const static std::string regexp =
+        rootDir + "/(\\d*)/apps/(User::Pkg::[^/]*)|(User::Pkg::User::App::[^/]*)";
+
+
+    boost::system::error_code ec;
+    boost::filesystem::path root(rootDir);
+    boost::regex mountNSAppFilter(regexp);
+
+    std::vector<AppContext> apps;
+    for (boost::filesystem::recursive_directory_iterator it(root, ec), eit;
+         it != eit;
+         it.increment(ec))
+    {
+        if (ec) {
+            LogWarning("Failed to process " + it->path().string());
+            it.pop();
+            continue;
+        }
+
+        boost::smatch matches;
+        std::string path = it->path().string();
+        if (boost::regex_match(path, matches, mountNSAppFilter)) {
+            if (matches.size() < 4) {
+                LogError("Failed to properly process regexp " << regexp);
+                return {};
+            }
+            apps.push_back({matches[2], matches[1]});
+        }
+    }
+
+    return apps;
+}
+
 } // namespace MountNS
 } // namespace SecurityManager
index 5308991cdef05bf2ee758f3822ae957f9957064f..4e0ee6de08816f0052ac1bfd4da8fc2cde3421af 100644 (file)
@@ -39,7 +39,6 @@
 #include <dpl/log/log.h>
 #include <dpl/errno_string.h>
 
-#include <app_manager.h>
 #include <sys/smack.h>
 
 #include <config.h>
@@ -1085,58 +1084,23 @@ int ServiceImpl::userDelete(const Credentials &creds, uid_t uidDeleted)
 }
 typedef std::map<std::string, std::vector<std::string>> AppsAllowedPrivilegesMap;
 
-namespace {
-
-struct AppManagerCallbackContext {
-    ServiceImpl *impl;
-    AppsAllowedPrivilegesMap *appsAllowedPrivileges;
-};
-
-std::string getAppIdFromContext(app_context_h app_context)
+void ServiceImpl::updateRunningAppSmackPolicy(
+    const MountNS::AppContext &appContext,
+    const std::map<std::string, std::vector<std::string>> &appsAllowedPrivileges)
 {
-    char *appId;
-    int ret = app_context_get_app_id (app_context, &appId);
-    if (ret != APP_MANAGER_ERROR_NONE) {
-        LogError("Failed to get appId from app_context: " << ret);
-        return "";
-    }
-    std::unique_ptr<char, decltype(std::free) *> appIdPtr(appId, std::free);
-    std::string appIdStr(appId);
-    appIdPtr.release();
-    return appIdStr;
-}
+    LogDebug("Updateing privilege Smack policy for: " << appContext.appProcessLabel);
 
-} // namespace anonymous
 
-bool ServiceImpl::updateRunningAppSmackPolicy(app_context_h app_context, void *user_data) {
-    AppManagerCallbackContext *context = reinterpret_cast<AppManagerCallbackContext*>(user_data);
-
-    std::string appId = getAppIdFromContext(app_context);
-    if (appId.empty()) {
-        LogDebug("No appId from running context");
-        return true;
+    auto it = appsAllowedPrivileges.find(appContext.appProcessLabel);
+    if (it == appsAllowedPrivileges.end()) {
+        LogError("No allowed privileges set for " << appContext.appProcessLabel);
+        return;
     }
+    auto oldAllowedPrivs = it->second;
 
-    LogDebug("Found " << appId << " running");
-
-    std::string pkgName;
-    context->impl->getPkgName(appId, pkgName);
-
-    bool isPkgHybrid = context->impl->m_privilegeDb.IsPackageHybrid(pkgName);
-
-    auto oldAllowedPrivs = context->appsAllowedPrivileges->operator[](appId);
-
-    auto it = context->impl->m_appIdUidMap.find(appId);
-    if (it == context->impl->m_appIdUidMap.end()) {
-        LogError("THIS IS VERY VERY BAD. RUNNING APPLICATION HAS NO SAVED UID!!!");
-        return true;
-    }
-    uid_t uid = it->second;
     std::vector<std::string> newAllowedPrivs;
-    auto appProcessLabel = SmackLabels::generateProcessLabel(appId, pkgName, isPkgHybrid);
-    context->impl->getAppAllowedPrivileges(appProcessLabel, uid, newAllowedPrivs);
+    getAppAllowedPrivileges(appContext.appProcessLabel, appContext.uidStr, newAllowedPrivs);
 
-    std::vector<std::string> inter;
     std::sort(oldAllowedPrivs.begin(), oldAllowedPrivs.end());
     std::sort(newAllowedPrivs.begin(), newAllowedPrivs.end());
 
@@ -1149,13 +1113,24 @@ bool ServiceImpl::updateRunningAppSmackPolicy(app_context_h app_context, void *u
     std::set_difference(newAllowedPrivs.begin(), newAllowedPrivs.end(),
                         oldAllowedPrivs.begin(), oldAllowedPrivs.end(),
                         std::back_inserter(allowed));
+
+    std::string appName, pkgName;
+    SmackLabels::generateAppPkgNameFromLabel(appContext.appProcessLabel, appName, pkgName);
+
     int authorId;
-    context->impl->m_privilegeDb.GetPkgAuthorId(pkgName, authorId);
+    m_privilegeDb.GetPkgAuthorId(pkgName, authorId);
 
-    context->impl->m_smackRules.disablePrivilegeRules(appProcessLabel, pkgName, authorId, denied);
-    context->impl->m_smackRules.enablePrivilegeRules(appProcessLabel, pkgName, authorId, allowed);
+    m_smackRules.disablePrivilegeRules(appContext.appProcessLabel, pkgName, authorId, denied);
+    m_smackRules.enablePrivilegeRules(appContext.appProcessLabel, pkgName, authorId, allowed);
+}
 
-    return true;
+bool isMultiUser(const MountNS::AppContext &app, const std::vector<MountNS::AppContext> &runningApps)
+{
+    for (auto &runningApp: runningApps) {
+        if (runningApp.appProcessLabel == app.appProcessLabel && runningApp.uidStr != app.uidStr)
+            return true;
+    }
+    return false;
 }
 
 int ServiceImpl::policyUpdate(const Credentials &creds, const std::vector<policy_entry> &policyEntries)
@@ -1180,26 +1155,12 @@ int ServiceImpl::policyUpdate(const Credentials &creds, const std::vector<policy
         std::map<std::string, std::vector<std::string>> appsAllowedPrivileges;
         std::vector<std::string> allPackages;
 
-        // TODO: Can this be optimized to: if policy entries contain either wildcard
-        // in place of privilege or if any of the privileges has smack mapping?
         if (m_smackRules.isPrivilegeMappingEnabled()) {
-            // Get policy of all installed application so we can recalculate it after update
-            m_privilegeDb.GetAllPackages(allPackages);
-            for (auto &package : allPackages) {
-                std::vector<std::string> packageApps;
-                m_privilegeDb.GetPkgApps(package, packageApps);
-                bool isPkgHybrid = m_privilegeDb.IsPackageHybrid(package);
-                for (auto &app : packageApps) {
-                    auto it = m_appIdUidMap.find(app);
-                    if (it == m_appIdUidMap.end()) {
-                        // TODO: Move app -> uid mapping to database
-                        LogDebug("App " << app << " has never been run in security-manager instance");
-                        continue;
-                    }
-                    uid_t uid = it->second;
-                    auto appProcessLabel = SmackLabels::generateProcessLabel(app, package, isPkgHybrid);
-                    getAppAllowedPrivileges(appProcessLabel, uid, appsAllowedPrivileges[app]);
-                }
+            for (auto &appKnownContext: m_appIdUidMap) {
+                auto appProcessLabel = appKnownContext.first;
+                auto uid = appKnownContext.second;
+
+                getAppAllowedPrivileges(appProcessLabel, uid, appsAllowedPrivileges[appProcessLabel]);
             }
         }
         // Apply updates
@@ -1207,11 +1168,19 @@ int ServiceImpl::policyUpdate(const Credentials &creds, const std::vector<policy
 
         if (m_smackRules.isPrivilegeMappingEnabled()) {
             LogDebug("Updating privilege related Smack rules");
-            AppManagerCallbackContext context{this, &appsAllowedPrivileges};
-            int ret = app_manager_foreach_running_app_context(&ServiceImpl::updateRunningAppSmackPolicy,
-                                                              &context);
-            if (ret != APP_MANAGER_ERROR_NONE) {
-                LogError("Failed to update Smack policy for running apps");
+            auto runningApps = MountNS::getMountNSApps();
+            for (auto &appContext : runningApps) {
+                if (isMultiUser(appContext, runningApps)) {
+                    LogError("Detected multiuser launch for " << appContext.appProcessLabel
+                             << ", policy won't be updated for its context.");
+                } else {
+                    try {
+                        updateRunningAppSmackPolicy(appContext, appsAllowedPrivileges);
+                    } catch (const SmackException::InvalidLabel &e) {
+                        LogError("AppContext: " << appContext.appProcessLabel
+                                 << " doesn't describe an application");
+                    }
+                }
             }
         }
 
@@ -1510,16 +1479,21 @@ int ServiceImpl::policyGetDesc(std::vector<std::string> &levels)
 
     return ret;
 }
-
 int ServiceImpl::getAppAllowedPrivileges(const Smack::Label &appProcessLabel,
     uid_t uid, std::vector<std::string> &allowedPrivileges)
+
+{
+    return getAppAllowedPrivileges(appProcessLabel, std::to_string(uid), allowedPrivileges);
+}
+
+int ServiceImpl::getAppAllowedPrivileges(const Smack::Label &appProcessLabel,
+    const std::string &uid, std::vector<std::string> &allowedPrivileges)
 {
     try {
         LogDebug("Getting allowed privileges for " << appProcessLabel << " and user " << uid);
-        std::string uidStr = std::to_string(uid);
 
         std::vector<std::string> privileges;
-        m_cynaraAdmin.getAppPolicy(appProcessLabel, uidStr, privileges);
+        m_cynaraAdmin.getAppPolicy(appProcessLabel, uid, privileges);
         m_cynaraAdmin.getAppPolicy(appProcessLabel, CYNARA_ADMIN_WILDCARD, privileges);
         m_cynaraAdmin.getAppPolicy(CYNARA_ADMIN_WILDCARD, CYNARA_ADMIN_WILDCARD, privileges);
 
@@ -1527,7 +1501,7 @@ int ServiceImpl::getAppAllowedPrivileges(const Smack::Label &appProcessLabel,
         for (auto &privilege : privileges) {
             int result = CYNARA_ADMIN_DENY;
             std::string resultExtra;
-            m_cynaraAdmin.check(appProcessLabel, uidStr, privilege, CynaraAdmin::Buckets[Bucket::PRIVACY_MANAGER], result, resultExtra, true);
+            m_cynaraAdmin.check(appProcessLabel, uid, privilege, CynaraAdmin::Buckets[Bucket::PRIVACY_MANAGER], result, resultExtra, true);
             if (result == CYNARA_ADMIN_ALLOW) {
                 LogDebug("Application " << appProcessLabel << " has " << privilege << " allowed");
                 allowedPrivileges.push_back(privilege);
@@ -2254,23 +2228,6 @@ Smack::Label ServiceImpl::getProcessLabel(const std::string &appName)
     return getAppProcessLabel(appName);
 }
 
-struct AppMgrCheckAppsCbContext {
-    std::string appName;
-    bool isRunning;
-};
-
-bool ServiceImpl::checkRunningApps(app_context_h app_context, void *user_data)
-{
-    AppMgrCheckAppsCbContext *context = reinterpret_cast<AppMgrCheckAppsCbContext*>(user_data);
-    std::string appId = getAppIdFromContext(app_context);
-    if (appId == context->appName) {
-        context->isRunning = true;
-        return false;
-    }
-
-    return true;
-}
-
 int ServiceImpl::prepareApp(const Credentials &creds, const std::string &appName, const std::vector<std::string> &privPathsVector,
         Smack::Label &label, std::string &pkgName, bool &enabledSharedRO,
         std::vector<gid_t> &forbiddenGroups, std::vector<gid_t> &allowedGroups, std::vector<bool> &privPathsStatusVector)
@@ -2297,9 +2254,9 @@ int ServiceImpl::prepareApp(const Credentials &creds, const std::string &appName
 
     if (m_smackRules.isPrivilegeMappingEnabled()) {
         uid_t savedUid;
-        auto it = m_appIdUidMap.find(appName);
+        auto it = m_appIdUidMap.find(label);
         if (it == m_appIdUidMap.end()) {
-            m_appIdUidMap[appName] = creds.uid;
+            m_appIdUidMap[label] = creds.uid;
             savedUid = creds.uid;
         } else {
             savedUid = it->second;
@@ -2313,17 +2270,22 @@ int ServiceImpl::prepareApp(const Credentials &creds, const std::string &appName
         if (savedUid != creds.uid) {
             LogDebug("Possible second instance detected. Checking all running apps");
 
-            AppMgrCheckAppsCbContext context{appName, false};
-            int ret = app_manager_foreach_running_app_context(&ServiceImpl::checkRunningApps,
-                                                              &context);
-            if (ret != APP_MANAGER_ERROR_NONE) {
-                LogError("Couldn't check running apps. No Smack policy will be applied for "
-                         << appName);
-            } else if (context.isRunning) {
-                LogError("Application is already running! No Smack policy will be applied for "
-                         << appName);
-            } else {
+            auto runningApps = MountNS::getMountNSApps();
+            auto it = std::find_if(runningApps.begin(), runningApps.end(),
+                                   [&] (const MountNS::AppContext &app) {
+                                       return app.appProcessLabel == label;
+                                   });
+            if (it == runningApps.end()) {
+                LogDebug("Second instance of " << appName << " is not currently running");
+                m_smackRules.enablePrivilegeRules(label, pkgName, authorId, allowedPrivileges);
+            } else if (it->uidStr == std::to_string(creds.uid)){
+                LogWarning("Second instance of " << appName
+                           << " detected, but for the same uid as requested");
                 m_smackRules.enablePrivilegeRules(label, pkgName, authorId, allowedPrivileges);
+            } else {
+                LogWarning("Second instance of " << appName
+                           << " detected runnign with " << it->uidStr << ". "
+                           << " No privilege related Smack rules will be applied");
             }
             m_appIdUidMap[appName] = creds.uid;
         } else {
index 97f596e53e9e69190fac5992f74a5b7c2f49a5ff..7f0ce3fc598fb7be003332866de45860f921c864 100644 (file)
@@ -1,7 +1,6 @@
 PKG_CHECK_MODULES(SERVER_DEP
     REQUIRED
     libsystemd
-    capi-appfw-app-manager
     cynara-client
     mount
     )