Add mount namespace operations wrapper 79/153879/3
authorDariusz Michaluk <d.michaluk@samsung.com>
Mon, 2 Oct 2017 11:59:06 +0000 (13:59 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Mon, 9 Oct 2017 09:11:26 +0000 (11:11 +0200)
This commit adds:
 - mount namespace helper functions,
 - privilege to filesystem paths mapping,
 - application to mount namespace mapping.

Change-Id: I572b316297c7512455829305674fd1be2ea07656

packaging/security-manager.spec
src/common/CMakeLists.txt
src/common/include/mount-namespace.h [new file with mode: 0644]
src/common/mount-namespace.cpp [new file with mode: 0644]
src/include/security-manager-types.h

index bd3c692..059988d 100644 (file)
@@ -259,6 +259,8 @@ chsmack -a System %{db_test_dir}/.security-manager-test.db-journal
 %attr(755,root,root) %{_datadir}/%{name}/db/update.sh
 %attr(755,root,root) %{_sysconfdir}/opt/upgrade/240.security-manager.db-update.sh
 
+%dir %attr(700,root,root) %{_datadir}/%{name}/dummy/
+
 %files -n libsecurity-manager-client
 %manifest libsecurity-manager-client.manifest
 %license LICENSE
index c81f13c..7153956 100644 (file)
@@ -65,6 +65,7 @@ SET(COMMON_SOURCES
     ${COMMON_PATH}/privilege-info.cpp
     ${COMMON_PATH}/privilege-gids.cpp
     ${COMMON_PATH}/group2gid.cpp
+    ${COMMON_PATH}/mount-namespace.cpp
     )
 
 IF(DPL_WITH_DLOG)
@@ -100,4 +101,4 @@ TARGET_LINK_LIBRARIES(${TARGET_COMMON}
 INSTALL(TARGETS ${TARGET_COMMON} DESTINATION ${LIB_INSTALL_DIR})
 INSTALL(DIRECTORY DESTINATION ${LOCAL_STATE_DIR}/security-manager/rules)
 INSTALL(DIRECTORY DESTINATION ${LOCAL_STATE_DIR}/security-manager/rules-merged)
-
+INSTALL(DIRECTORY DESTINATION ${DATA_ROOT_DIR}/${PROJECT_NAME}/dummy)
diff --git a/src/common/include/mount-namespace.h b/src/common/include/mount-namespace.h
new file mode 100644 (file)
index 0000000..b4eb027
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Rafal Krypa <r.krypa@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        mount-namespace.h
+ * @author      Dariusz Michaluk <d.michaluk@samsung.com>
+ * @version     1.0
+ * @brief       Mount namespace utility.
+ *
+ */
+#pragma once
+
+#include <string>
+#include <map>
+#include <vector>
+
+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;
+
+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);
+
+bool isMountNamespaceEnabled(void);
+int createMountNamespace(void);
+bool enterMountNamespace(const Path &mntPath);
+int makeMountSlave(const Path &mountPoint);
+int makeMountPrivate(const Path &mountPoint);
+int bindMount(const Path &source, const Path &target);
+int uMount(const Path &target);
+bool isPathBound(const Path &what, const Path &where);
+
+} // namespace MountNS
+} // namespace SecurityManager
diff --git a/src/common/mount-namespace.cpp b/src/common/mount-namespace.cpp
new file mode 100644 (file)
index 0000000..01fbc14
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ *  Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  Contact: Rafal Krypa <r.krypa@samsung.com>
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License
+ */
+/**
+ * @file        mount-namespace.cpp
+ * @author      Dariusz Michaluk <d.michaluk@samsung.com>
+ * @version     1.0
+ * @brief       Mount namespace utility.
+ *
+ */
+
+#include <pwd.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <mount-namespace.h>
+#include <filesystem.h>
+#include <tzplatform-config.h>
+#include <dpl/log/log.h>
+#include <dpl/errno_string.h>
+#include <security-manager.h>
+
+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 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";
+
+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}}};
+}
+
+std::string getUsersAppsMountPointsPath(void)
+{
+    return TizenPlatformConfig::makePath(TZ_SYS_RUN, "user");
+}
+
+std::string getUserAppsMountPointsPath(uid_t uid)
+{
+    return TizenPlatformConfig::makePath(TZ_SYS_RUN, "user", std::to_string(uid), "apps");
+}
+
+std::string getUserAppMountPointPath(uid_t uid, const std::string &appName)
+{
+    return getUserAppsMountPointsPath(uid) + "/" + appName;
+}
+
+bool isMountNamespaceEnabled(void)
+{
+    auto getStatus = []() -> bool {
+        return (access("/proc/self/ns/mnt", F_OK) != -1) ? true : false;
+    };
+
+    static bool isMountNamespaceEnabled = getStatus();
+
+    return isMountNamespaceEnabled;
+}
+
+int createMountNamespace(void)
+{
+    int ret = unshare(CLONE_NEWNS);
+    if (ret != 0) {
+        LogError("Failed to unshare mount namespace: " << GetErrnoString(errno));
+        return SECURITY_MANAGER_ERROR_MOUNT_ERROR;
+    }
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+bool enterMountNamespace(const Path &mntPath)
+{
+    int fd = open(mntPath.c_str(), O_RDONLY);
+    if (-1 == fd)
+        return false;
+
+    // 0 == allow any type of namespace
+    int ret = setns(fd, 0);
+    close(fd);
+
+    return ret != -1;
+}
+
+int makeMountSlave(const Path &mountPoint)
+{
+    int ret = mount("none", mountPoint.c_str(), NULL, MS_REC|MS_SLAVE, NULL);
+    if (ret != 0) {
+        LogError("Failed to make mount point " << mountPoint << " slave: " << GetErrnoString(errno));
+        return SECURITY_MANAGER_ERROR_MOUNT_ERROR;
+    }
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+int makeMountPrivate(const Path &mountPoint)
+{
+    int ret = mount("none", mountPoint.c_str(), NULL, MS_PRIVATE, NULL);
+    if (ret != 0) {
+        LogError("Failed to make mount point " << mountPoint << " private: " << GetErrnoString(errno));
+        return SECURITY_MANAGER_ERROR_MOUNT_ERROR;
+    }
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+int bindMount(const Path &source, const Path &target)
+{
+    int ret = mount(source.c_str(), target.c_str(), NULL, MS_BIND, NULL);
+    if (ret != 0) {
+        LogError("Failed to bind directory " << source << "to " << target << " " << GetErrnoString(errno));
+        return SECURITY_MANAGER_ERROR_MOUNT_ERROR;
+    }
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+int uMount(const Path &target)
+{
+    int ret = umount(target.c_str());
+    if (ret != 0) {
+        LogWarning("Failed to umount: "  << target << " " << GetErrnoString(errno));
+        return SECURITY_MANAGER_ERROR_MOUNT_ERROR;
+    }
+    return SECURITY_MANAGER_SUCCESS;
+}
+
+bool isPathBound(const Path &what, const Path &where)
+{
+    std::string line = what + " " + where;
+    std::string mountinfo = FS::getTextFileContents("/proc/self/mountinfo");
+    return std::string::npos != mountinfo.find(line);
+}
+
+} // namespace MountNS
+} // namespace SecurityManager
index 89f99c8..c28a9f4 100644 (file)
@@ -52,6 +52,7 @@ enum lib_retcode {
     SECURITY_MANAGER_ERROR_NOT_INITIALIZED,
     SECURITY_MANAGER_ERROR_FILE_CREATE_FAILED,
     SECURITY_MANAGER_ERROR_FILE_DELETE_FAILED,
+    SECURITY_MANAGER_ERROR_MOUNT_ERROR,
 };
 
 /*! \brief accesses types for application installation paths*/