diff options
author | Rafal Krypa <r.krypa@samsung.com> | 2017-11-28 13:01:38 +0100 |
---|---|---|
committer | Rafal Krypa <r.krypa@samsung.com> | 2017-11-28 14:46:54 +0100 |
commit | eae7a6eaf06fc33ed7b5b093795adbacd028cb3d (patch) | |
tree | a8d26a111357ea19448764caea14fcf20369c059 | |
parent | e3fb8faa3aef9b2616a98743383ca5959d77c2dc (diff) | |
download | security-manager-eae7a6eaf06fc33ed7b5b093795adbacd028cb3d.tar.gz security-manager-eae7a6eaf06fc33ed7b5b093795adbacd028cb3d.tar.bz2 security-manager-eae7a6eaf06fc33ed7b5b093795adbacd028cb3d.zip |
Allow privilege enforcement with bind mounts to be configured
Add configuration file describing which privileges are to be enforced
with bind mounts and how. New config privilege-mount.list now assigns
privileges to their mount points and specifies source directory to bind
mount.
Change-Id: I7e2fb7a483803d0a8877d142b8e1df7a37ae18e3
Signed-off-by: Rafal Krypa <r.krypa@samsung.com>
-rw-r--r-- | policy/CMakeLists.txt | 1 | ||||
-rw-r--r-- | policy/privilege-mount.list | 17 | ||||
-rw-r--r-- | src/client/client-security-manager.cpp | 10 | ||||
-rw-r--r-- | src/common/config.cpp | 1 | ||||
-rw-r--r-- | src/common/include/config.h | 1 | ||||
-rw-r--r-- | src/common/include/mount-namespace.h | 17 | ||||
-rw-r--r-- | src/common/include/tzplatform-config.h | 1 | ||||
-rw-r--r-- | src/common/mount-namespace.cpp | 71 | ||||
-rw-r--r-- | src/common/tzplatform-config.cpp | 5 | ||||
-rw-r--r-- | src/common/worker.cpp | 16 |
10 files changed, 99 insertions, 41 deletions
diff --git a/policy/CMakeLists.txt b/policy/CMakeLists.txt index c0dbb485..a4ed18d6 100644 --- a/policy/CMakeLists.txt +++ b/policy/CMakeLists.txt @@ -10,6 +10,7 @@ INSTALL(FILES "pkg-rules-template.smack" DESTINATION ${POLICY_DIR}) INSTALL(FILES "author-rules-template.smack" DESTINATION ${POLICY_DIR}) INSTALL(FILES "sharedro-rules-template.smack" DESTINATION ${POLICY_DIR}) INSTALL(FILES "privilege-group.list" DESTINATION ${POLICY_DIR}) +INSTALL(FILES "privilege-mount.list" DESTINATION ${POLICY_DIR}) INSTALL(PROGRAMS "update.sh" DESTINATION ${POLICY_DIR}) INSTALL(DIRECTORY "updates" USE_SOURCE_PERMISSIONS DESTINATION ${POLICY_DIR}) INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/security-manager-policy-reload DESTINATION ${BIN_INSTALL_DIR}) diff --git a/policy/privilege-mount.list b/policy/privilege-mount.list new file mode 100644 index 00000000..61aa2e7a --- /dev/null +++ b/policy/privilege-mount.list @@ -0,0 +1,17 @@ +# Configuration of groups assignment to mount points. +# Format: +# - Each line of "<PRIVILEGE> <MOUNT_POINT> <ALLOW_SRC> <DENY_SRC>" describes single mapping +# * <PRIVILEGE>: name of enforced privilege +# * <MOUNT_POINT>: mount point location +# * <ALLOW_SRC>: source directory to bind mount when privilege is allowed +# * <DENY_SRC>: source directory to bind mount when privilege is denied +# - <ALLOW_SRC> and <DENY_SRC> may be set to special value "-". In such case no +# mount will be performed. +# - Values starting with TZ_ will be treated as tizen-platform-config variables, converted +# to respective values +# - Elements in line are separated by white space +# - Lines starting with '#' and empty lines are ignored + +http://tizen.org/privilege/externalstorage TZ_SYS_STORAGE - /usr/share/security-manager/dummy +http://tizen.org/privilege/mediastorage TZ_USER_CONTENT - /usr/share/security-manager/dummy +http://tizen.org/privilege/mediastorage /opt/usr/media - /usr/share/security-manager/dummy diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index dd2abf31..076ae49c 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -828,12 +828,10 @@ static inline int security_manager_create_namespace_internal(const char *app_nam return ret; } - if (result == 0) { // access denied - for (auto &path : it.second) { - ret = MountNS::bindMount(MountNS::ACCESS_DENIED_DIR_PATH, path); - if (ret != SECURITY_MANAGER_SUCCESS) - return ret; - } + for (auto &privilegePath : it.second) { + ret = MountNS::applyPrivilegePath(result, privilegePath); + if (ret != SECURITY_MANAGER_SUCCESS) + return ret; } } diff --git a/src/common/config.cpp b/src/common/config.cpp index 4a58718e..2064b6e6 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -43,6 +43,7 @@ const std::string APPS_LABELS_FILE = "apps-labels"; const std::string SKEL_DIR = "/etc/skel"; const std::string PRIVILEGE_GROUP_LIST_FILE = POLICY_DIR "/privilege-group.list"; +const std::string PRIVILEGE_MOUNT_LIST_FILE = POLICY_DIR "/privilege-mount.list"; const std::string PRIVACY_POLICY_DESC = "Ask user"; #ifdef ASKUSER_ENABLED diff --git a/src/common/include/config.h b/src/common/include/config.h index 61a77478..bce8020f 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -48,6 +48,7 @@ extern const std::string APPS_LABELS_FILE; /* Policy files */ extern const std::string PRIVILEGE_GROUP_LIST_FILE; +extern const std::string PRIVILEGE_MOUNT_LIST_FILE; extern const std::string SKEL_DIR; diff --git a/src/common/include/mount-namespace.h b/src/common/include/mount-namespace.h index b4eb0277..e95ec4be 100644 --- a/src/common/include/mount-namespace.h +++ b/src/common/include/mount-namespace.h @@ -32,24 +32,23 @@ namespace SecurityManager { namespace MountNS { typedef std::string Path; -typedef std::vector<Path> PathVector; -typedef std::map<std::string, PathVector> PrivilegePathsMap; - -extern const std::string EXTERNAL_STORAGE_PRIVILEGE; -extern const std::string MEDIA_STORAGE_PRIVILEGE; +typedef struct { + std::string dstPath; + std::string allowSrcPath; + std::string denySrcPath; +} PrivilegePath; +typedef std::vector<PrivilegePath> PrivilegePathVector; +typedef std::map<std::string, PrivilegePathVector> PrivilegePathsMap; extern const std::string MAIN_MOUNT_NAMESPACE; -extern const std::string ACCESS_DENIED_DIR_PATH; -extern const std::string EXTERNAL_STORAGE_DIR_PATH; -extern const std::string MEDIA_STORAGE_DIR_PATH; - PrivilegePathsMap getPrivilegePathMap(uid_t uid); std::string getUsersAppsMountPointsPath(void); std::string getUserAppsMountPointsPath(uid_t uid); std::string getUserAppMountPointPath(uid_t uid, const std::string &appName); +int applyPrivilegePath(bool allow, const PrivilegePath &privilegePath); bool isMountNamespaceEnabled(void); int createMountNamespace(void); bool enterMountNamespace(const Path &mntPath); diff --git a/src/common/include/tzplatform-config.h b/src/common/include/tzplatform-config.h index f9458cb6..7ffecc1a 100644 --- a/src/common/include/tzplatform-config.h +++ b/src/common/include/tzplatform-config.h @@ -50,6 +50,7 @@ public: std::string ctxMakePath(enum tzplatform_variable id, const std::string &p1, const std::string &p2, const std::string &p3); + static enum tzplatform_variable getId(const std::string &name); static std::string getEnv(enum tzplatform_variable id); diff --git a/src/common/mount-namespace.cpp b/src/common/mount-namespace.cpp index 01fbc14d..63f9dc61 100644 --- a/src/common/mount-namespace.cpp +++ b/src/common/mount-namespace.cpp @@ -30,6 +30,8 @@ #include <unistd.h> #include <mount-namespace.h> +#include <config.h> +#include <config-file.h> #include <filesystem.h> #include <tzplatform-config.h> #include <dpl/log/log.h> @@ -39,22 +41,65 @@ namespace SecurityManager { namespace MountNS { -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 EMPTY_MOUNT_DIR = "-"; const std::string MAIN_MOUNT_NAMESPACE = "/proc/1/ns/mnt"; - -const std::string ACCESS_DENIED_DIR_PATH = TizenPlatformConfig::makePath( - TZ_SYS_RO_SHARE, "security-manager", "dummy"); -const std::string EXTERNAL_STORAGE_DIR_PATH = TizenPlatformConfig::getEnv(TZ_SYS_STORAGE); -const std::string MEDIA_STORAGE_DIR_PATH = "/opt/usr/media"; +const std::string SELF_MOUNT_NAMESPACE = "/proc/self/ns/mnt"; PrivilegePathsMap getPrivilegePathMap(uid_t uid) { - return - {{EXTERNAL_STORAGE_PRIVILEGE, {EXTERNAL_STORAGE_DIR_PATH}}, - {MEDIA_STORAGE_PRIVILEGE, {TizenPlatformConfig(uid).ctxGetEnv(TZ_USER_CONTENT), - MEDIA_STORAGE_DIR_PATH}}}; + PrivilegePathsMap map; + TizenPlatformConfig tpcUser(uid); + + auto conf = ConfigFile(Config::PRIVILEGE_MOUNT_LIST_FILE).read(); + for (auto &confEntry : conf) { + if (confEntry.size() != 4) + continue; + + for (int i = 1; i <= 3; ++i) + if (confEntry[i] == EMPTY_MOUNT_DIR) + confEntry[i].clear(); + else if (!strncmp(confEntry[i].c_str(), "TZ_SYS_", 7)) + confEntry[i] = TizenPlatformConfig::getEnv(TizenPlatformConfig::getId(confEntry[i])); + else if (!strncmp(confEntry[i].c_str(), "TZ_USER_", 8)) + confEntry[i] = tpcUser.ctxGetEnv(TizenPlatformConfig::getId(confEntry[i])); + + std::string &privilege = confEntry[0]; + std::string &dstPath = confEntry[1]; + std::string &allowSrcPath = confEntry[2]; + std::string &denySrcPath = confEntry[3]; + + auto it = map.find(privilege); + if (it == map.end()) + it = map.emplace(privilege, PrivilegePathVector()).first; + it->second.push_back({dstPath, allowSrcPath, denySrcPath}); + } + + return map; +} + +int applyPrivilegePath(bool allow, const PrivilegePath &privilegePath) +{ + const std::string &srcPath = allow ? privilegePath.allowSrcPath : privilegePath.denySrcPath; + const std::string &otherSrcPath = allow ? privilegePath.denySrcPath : privilegePath.allowSrcPath; + + LogDebug("Applying privilege mount enforcement:" << + " allow = " << allow << " dstPath = " << privilegePath.dstPath << + " allowSrcPath = " << privilegePath.allowSrcPath << + " denySrcPath = " << privilegePath.denySrcPath); + + if (srcPath.empty()) { + if (!otherSrcPath.empty() && isPathBound(otherSrcPath, privilegePath.dstPath)) { + LogDebug("Unmounting " << otherSrcPath << " from " << privilegePath.dstPath); + return uMount(privilegePath.dstPath); + } + return 0; + } + + if (isPathBound(srcPath, privilegePath.dstPath)) + return 0; + + LogDebug("Bind mounting " << srcPath << " to " << privilegePath.dstPath); + return bindMount(srcPath, privilegePath.dstPath); } std::string getUsersAppsMountPointsPath(void) @@ -75,7 +120,7 @@ std::string getUserAppMountPointPath(uid_t uid, const std::string &appName) bool isMountNamespaceEnabled(void) { auto getStatus = []() -> bool { - return (access("/proc/self/ns/mnt", F_OK) != -1) ? true : false; + return (access(SELF_MOUNT_NAMESPACE.c_str(), F_OK) != -1) ? true : false; }; static bool isMountNamespaceEnabled = getStatus(); diff --git a/src/common/tzplatform-config.cpp b/src/common/tzplatform-config.cpp index 31e421ff..d553b9f9 100644 --- a/src/common/tzplatform-config.cpp +++ b/src/common/tzplatform-config.cpp @@ -57,6 +57,11 @@ static uid_t validate(uid_t uid) return uid; } +enum tzplatform_variable TizenPlatformConfig::getId(const std::string &name) +{ + return tzplatform_getid(name.c_str()); +} + std::string TizenPlatformConfig::ctxGetEnv(enum tzplatform_variable id) { return validate(tzplatform_context_getenv(m_ctx, id)); diff --git a/src/common/worker.cpp b/src/common/worker.cpp index 414947ab..38cbf1ac 100644 --- a/src/common/worker.cpp +++ b/src/common/worker.cpp @@ -65,24 +65,14 @@ int Worker::doWork(const NSMountLogic::EntryVector &entries) for (auto &privStatus : entry.privilegeStatusVector) { auto &privName = privStatus.first; - auto &result = privStatus.second; + auto &allowed = privStatus.second; auto mapIter = storagePrivilegePathMap.find(privName); if (mapIter == storagePrivilegePathMap.end()) continue; - MountNS::PathVector pathVector = mapIter->second; - for (auto &path : pathVector) { - bool allowed = !MountNS::isPathBound(MountNS::ACCESS_DENIED_DIR_PATH, path); - - if (allowed == result) - continue; - - if (result) - MountNS::uMount(path); // allow access to path - else - MountNS::bindMount(MountNS::ACCESS_DENIED_DIR_PATH, path); // forbid access - } + for (auto &privilegePath : mapIter->second) + applyPrivilegePath(allowed, privilegePath); } } catch (...) { status = -1; |