From: Jan Olszak Date: Mon, 24 Aug 2015 09:13:05 +0000 (+0200) Subject: lxcpp: Remounting /proc and /sys on attach X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F41%2F46641%2F5;p=platform%2Fcore%2Fsecurity%2Fvasum.git lxcpp: Remounting /proc and /sys on attach [Feature] Remounting /proc /sys Filesystem handling functions [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I8015b7a66c1fabab9133ad360e9e7a45c069082c --- diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index 6fd9775..2ac232f 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -24,10 +24,14 @@ #include "lxcpp/container-impl.hpp" #include "lxcpp/exception.hpp" #include "lxcpp/process.hpp" +#include "lxcpp/filesystem.hpp" +#include "lxcpp/namespace.hpp" #include "utils/exception.hpp" #include +#include + namespace lxcpp { @@ -99,9 +103,37 @@ std::string ContainerImpl::getRootPath() throw NotImplementedException(); } +namespace { +void setupMountPoints() +{ + /* TODO: Uncomment when preparing the final attach() version + + // TODO: This unshare should be optional only if we attach to PID/NET namespace, but not MNT. + // Otherwise container already has remounted /proc /sys + lxcpp::unshare(Namespace::MNT); + + if (isMountPointShared("/")) { + // TODO: Handle case when the container rootfs or mount location is MS_SHARED, but not '/' + lxcpp::mount(nullptr, "/", nullptr, MS_SLAVE | MS_REC, nullptr); + } + + if(isMountPoint("/proc")) { + lxcpp::umount("/proc", MNT_DETACH); + lxcpp::mount("none", "/proc", "proc", 0, nullptr); + } + + if(isMountPoint("/sys")) { + lxcpp::umount("/sys", MNT_DETACH); + lxcpp::mount("none", "/sys", "sysfs", 0, nullptr); + } + + */ +} +} // namespace int ContainerImpl::attachChild(void* data) { try { + setupMountPoints(); return (*static_cast(data))(); } catch(...) { return -1; // Non-zero on failure diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index 12ae299..bdb56f7 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -46,6 +46,11 @@ struct ProcessSetupException: public Exception { : Exception(message) {} }; +struct FileSystemSetupException: public Exception { + FileSystemSetupException(const std::string& message = "Error during a file system operation") + : Exception(message) {} +}; + struct BadArgument: public Exception { BadArgument(const std::string& message = "Bad argument passed") : Exception(message) {} diff --git a/libs/lxcpp/filesystem.cpp b/libs/lxcpp/filesystem.cpp new file mode 100644 index 0000000..c085861 --- /dev/null +++ b/libs/lxcpp/filesystem.cpp @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief file system handling routines + */ + +#include "lxcpp/filesystem.hpp" +#include "lxcpp/exception.hpp" +#include "lxcpp/process.hpp" + +#include "utils/paths.hpp" +#include "utils/exception.hpp" +#include "logger/logger.hpp" + +#include +#include +#include +#include +#include + + +namespace lxcpp { + +void mount(const std::string& source, + const std::string& target, + const std::string& filesystemtype, + unsigned long mountflags, + const std::string& data) +{ + if (-1 == ::mount(source.c_str(), + target.c_str(), + filesystemtype.c_str(), + mountflags, + data.c_str())) { + const std::string msg = "mount() failed: src:" + source + + ", tgt: " + target + + ", filesystemtype: " + filesystemtype + + ", mountflags: " + std::to_string(mountflags) + + ", data: " + data + + ", msg: " + utils::getSystemErrorMessage(); + LOGE(msg); + throw FileSystemSetupException(msg); + } +} + +void umount(const std::string& path, const int flags) +{ + if (-1 == ::umount2(path.c_str(), flags)) { + const std::string msg = "umount() failed: '" + path + "': " + utils::getSystemErrorMessage(); + LOGD(msg); + throw FileSystemSetupException(msg); + } +} + +bool isMountPoint(const std::string& path) +{ + std::string parentPath = utils::dirName(path); + + struct stat s1, s2; + if (-1 == ::stat(path.c_str(), &s1)) { + const std::string msg = "stat() failed: " + path + ": " + utils::getSystemErrorMessage(); + LOGE(msg); + throw FileSystemSetupException(msg); + } + + if (-1 == ::stat(parentPath.c_str(), &s2)) { + const std::string msg = "stat() failed: " + parentPath + ": " + utils::getSystemErrorMessage(); + LOGE(msg); + throw FileSystemSetupException(msg); + } + + return s1.st_dev != s2.st_dev; +} + +bool isMountPointShared(const std::string& path) +{ + std::ifstream fileStream("/proc/self/mountinfo"); + if (!fileStream.good()) { + const std::string msg = "Failed to open /proc/self/mountinfo"; + LOGE(msg); + throw FileSystemSetupException(msg); + } + + // Find the line corresponding to the path + std::string line; + while (std::getline(fileStream, line).good()) { + std::istringstream iss(line); + auto it = std::istream_iterator(iss); + std::advance(it, 4); + + if (it->compare(path)) { + // Wrong line, different path + continue; + } + + // Right line, check if mount point shared + std::advance(it, 2); + return it->find("shared:") != std::string::npos; + } + + // Path not found + return false; +} + +} // namespace lxcpp \ No newline at end of file diff --git a/libs/lxcpp/filesystem.hpp b/libs/lxcpp/filesystem.hpp new file mode 100644 index 0000000..6833ffc --- /dev/null +++ b/libs/lxcpp/filesystem.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief file system handling routines + */ + +#ifndef LXCPP_FILESYSTEM_HPP +#define LXCPP_FILESYSTEM_HPP + +#include + +namespace lxcpp { + +void mount(const std::string& source, + const std::string& target, + const std::string& filesystemtype, + unsigned long mountflags, + const std::string& data); + +void umount(const std::string& path, const int flags); + +bool isMountPoint(const std::string& path); + +/** + * Detect whether path is mounted as MS_SHARED. + * Parses /proc/self/mountinfo + * + * @param path mount point + * @return is the mount point shared + */ +bool isMountPointShared(const std::string& path); + +} // namespace lxcpp + +#endif // LXCPP_FILESYSTEM_HPP \ No newline at end of file diff --git a/libs/lxcpp/process.cpp b/libs/lxcpp/process.cpp index b707353..96475d5 100644 --- a/libs/lxcpp/process.cpp +++ b/libs/lxcpp/process.cpp @@ -154,4 +154,12 @@ int waitpid(const pid_t pid) throw ProcessSetupException(msg); } +void unshare(const Namespace ns) +{ + if(-1 == ::unshare(toFlag(ns))) { + const std::string msg = "unshare() failed: " + utils::getSystemErrorMessage(); + LOGE(msg); + throw ProcessSetupException(msg); + } +} } // namespace lxcpp \ No newline at end of file diff --git a/libs/lxcpp/process.hpp b/libs/lxcpp/process.hpp index a640e1a..869e3d6 100644 --- a/libs/lxcpp/process.hpp +++ b/libs/lxcpp/process.hpp @@ -47,6 +47,8 @@ void setns(const pid_t pid, int waitpid(const pid_t pid); +void unshare(const Namespace ns); + } // namespace lxcpp #endif // LXCPP_PROCESS_HPP \ No newline at end of file