summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafal Krypa <r.krypa@samsung.com>2017-11-28 13:01:38 +0100
committerRafal Krypa <r.krypa@samsung.com>2017-11-28 14:46:54 +0100
commiteae7a6eaf06fc33ed7b5b093795adbacd028cb3d (patch)
treea8d26a111357ea19448764caea14fcf20369c059
parente3fb8faa3aef9b2616a98743383ca5959d77c2dc (diff)
downloadsecurity-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.txt1
-rw-r--r--policy/privilege-mount.list17
-rw-r--r--src/client/client-security-manager.cpp10
-rw-r--r--src/common/config.cpp1
-rw-r--r--src/common/include/config.h1
-rw-r--r--src/common/include/mount-namespace.h17
-rw-r--r--src/common/include/tzplatform-config.h1
-rw-r--r--src/common/mount-namespace.cpp71
-rw-r--r--src/common/tzplatform-config.cpp5
-rw-r--r--src/common/worker.cpp16
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;