SET(GUARD_CODENAME "${PROJECT_NAME}-guard")
ADD_SUBDIRECTORY(guard)
+SET(ATTACH_CODENAME "${PROJECT_NAME}-attach")
+ADD_SUBDIRECTORY(attach)
+
MESSAGE(STATUS "")
MESSAGE(STATUS "Generating makefile for the liblxcpp...")
FILE(GLOB HEADERS *.hpp)
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
SOVERSION ${_LIB_SOVERSION_}
VERSION ${_LIB_VERSION_}
- COMPILE_DEFINITIONS GUARD_PATH="${LIBEXEC_DIR}/${GUARD_CODENAME}"
+)
+
+TARGET_COMPILE_DEFINITIONS(${PROJECT_NAME}
+ PRIVATE GUARD_PATH="${LIBEXEC_DIR}/${GUARD_CODENAME}"
+ PRIVATE ATTACH_PATH="${LIBEXEC_DIR}/${ATTACH_CODENAME}"
)
ADD_DEPENDENCIES(${PROJECT_NAME} Common Logger)
--- /dev/null
+# 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 CMakeLists.txt
+# @author Jan Olszak (j.olszak@samsung.com)
+#
+
+MESSAGE(STATUS "")
+MESSAGE(STATUS "Generating makefile for the Attach...")
+FILE(GLOB attach_SRCS *.cpp *.hpp)
+
+
+## Setup target ################################################################
+ADD_EXECUTABLE(${ATTACH_CODENAME} ${attach_SRCS})
+
+
+## Link libraries ##############################################################
+PKG_CHECK_MODULES(ATTACH_DEPS REQUIRED glib-2.0)
+INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER})
+INCLUDE_DIRECTORIES(SYSTEM ${ATTACH_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS})
+TARGET_LINK_LIBRARIES(${ATTACH_CODENAME} Common lxcpp Config)
+
+
+## Install #####################################################################
+INSTALL(TARGETS ${ATTACH_CODENAME} DESTINATION ${LIBEXEC_DIR})
--- /dev/null
+/*
+ * 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 Internal structure sent between Attach command and AttachHelper
+ */
+
+#ifndef LXCPP_ATTACH_ATTACH_CONFIG_HPP
+#define LXCPP_ATTACH_ATTACH_CONFIG_HPP
+
+#include "lxcpp/namespace.hpp"
+
+#include <config/config.hpp>
+#include <config/fields.hpp>
+
+#include <sys/types.h>
+
+#include <string>
+#include <vector>
+
+namespace lxcpp {
+
+struct AttachConfig {
+
+ /// Arguments passed by user, argv[0] is the binary's path in container
+ std::vector<const char*> argv;
+
+ /// PID of the container's init process
+ pid_t initPid;
+
+ /// Namespaces to which we'll attach
+ std::vector<Namespace> namespaces;
+
+ /// User ID to set
+ uid_t uid;
+
+ /// Group ID to set
+ gid_t gid;
+
+ /// PTS that will become the control terminal for the attached process
+ int ttyFD;
+
+ /// Supplementary groups to set
+ std::vector<gid_t> supplementaryGids;
+
+ /// Mask of capabilities that will be available
+ int capsToKeep;
+
+ /// Work directory for the attached process
+ std::string workDirInContainer;
+
+ /// Environment variables that will be kept
+ std::vector<std::string> envToKeep;
+
+ /// Environment variables that will be set/updated for the attached process
+ std::vector<std::pair<std::string, std::string>> envToSet;
+
+ AttachConfig() = default;
+
+ AttachConfig(const std::vector<const char*>& argv,
+ const pid_t initPid,
+ const std::vector<Namespace>& namespaces,
+ const uid_t uid,
+ const gid_t gid,
+ const std::vector<gid_t>& supplementaryGids,
+ const int capsToKeep,
+ const std::string& workDirInContainer,
+ const std::vector<std::string>& envToKeep,
+ const std::vector<std::pair<std::string, std::string>>& envToSet)
+ : argv(argv),
+ initPid(initPid),
+ namespaces(namespaces),
+ uid(uid),
+ gid(gid),
+ ttyFD(-1),
+ supplementaryGids(supplementaryGids),
+ capsToKeep(capsToKeep),
+ workDirInContainer(workDirInContainer),
+ envToKeep(envToKeep),
+ envToSet(envToSet)
+ {}
+
+ CONFIG_REGISTER
+ (
+ //TODO: Uncomment and fix cstring serialization
+ // argv,
+ initPid,
+ //TODO: Uncomment and fix Namespace serialization (or remove Namespace)
+ // namespaces,
+ uid,
+ gid,
+ ttyFD,
+ supplementaryGids,
+ capsToKeep,
+ workDirInContainer,
+ envToKeep
+ //TODO: Uncomment and fix std::pair serialization
+ // envToSet
+ )
+};
+
+} // namespace lxcpp
+
+#endif // LXCPP_ATTACH_ATTACH_CONFIG_HPP
\ No newline at end of file
--- /dev/null
+/*
+ * 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 Implementation of attaching to a container
+ */
+
+#include "lxcpp/attach/attach-helper.hpp"
+#include "lxcpp/exception.hpp"
+#include "lxcpp/process.hpp"
+#include "lxcpp/filesystem.hpp"
+#include "lxcpp/namespace.hpp"
+#include "lxcpp/capability.hpp"
+#include "lxcpp/environment.hpp"
+#include "lxcpp/credentials.hpp"
+#include "lxcpp/utils.hpp"
+
+#include "utils/exception.hpp"
+#include "utils/fd-utils.hpp"
+#include "logger/logger.hpp"
+#include "config/manager.hpp"
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <fcntl.h>
+
+#include <string>
+
+namespace lxcpp {
+
+namespace {
+
+int child(void* data)
+{
+ AttachConfig& config = *static_cast<AttachConfig*>(data);
+
+ // Setup /proc /sys mount
+ setupMountPoints();
+
+ // Setup capabilities
+ dropCapsFromBoundingExcept(config.capsToKeep);
+
+ // Setup environment variables
+ clearenvExcept(config.envToKeep);
+ setenv(config.envToSet);
+
+ // Set uid/gids
+ lxcpp::setgid(config.gid);
+ setgroups(config.supplementaryGids);
+ lxcpp::setuid(config.uid);
+
+ // Set control TTY
+ if(!setupControlTTY(config.ttyFD)) {
+ ::_exit(EXIT_FAILURE);
+ }
+
+ // Run user's binary
+ ::execve(config.argv[0], const_cast<char *const*>(config.argv.data()), nullptr);
+ return EXIT_FAILURE;
+}
+
+} // namespace
+
+AttachHelper::AttachHelper(const int channelFD)
+ : mChannel(channelFD)
+{
+ mChannel.setCloseOnExec(true);
+ config::loadFromFD(mChannel.getFD(), mConfig);
+}
+
+AttachHelper::~AttachHelper()
+{
+ utils::close(mConfig.ttyFD);
+}
+
+void AttachHelper::execute()
+{
+ // Move to the right namespaces
+ lxcpp::setns(mConfig.initPid, mConfig.namespaces);
+
+ // Change the current work directory
+ // workDirInContainer is a path relative to the container's root
+ lxcpp::chdir(mConfig.workDirInContainer);
+
+ // Unsharing PID namespace won't affect the returned childPid
+ // CLONE_PARENT: Child's PPID == Caller's PID
+ const pid_t childPid = lxcpp::clone(child,
+ &mConfig,
+ CLONE_PARENT);
+ mChannel.write(childPid);
+}
+
+} // namespace lxcpp
--- /dev/null
+/*
+ * 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 Implementation of attaching to a container
+ */
+
+#ifndef LXCPP_ATTACH_ATTACH_HELPER_HPP
+#define LXCPP_ATTACH_ATTACH_HELPER_HPP
+
+#include "lxcpp/attach/attach-config.hpp"
+
+#include "utils/channel.hpp"
+
+namespace lxcpp {
+
+/**
+ * Implementation of the Intermediate helper process.
+ * @see Attach
+ */
+class AttachHelper {
+public:
+ AttachHelper(const int channelFD);
+ ~AttachHelper();
+
+ void execute();
+
+private:
+ utils::Channel mChannel;
+ AttachConfig mConfig;
+};
+
+} // namespace lxcpp
+
+#endif // LXCPP_ATTACH_ATTACH_HELPER_HPP
\ No newline at end of file
--- /dev/null
+/*
+ * 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 Main file for the Intermediate process (libexec)
+ */
+
+#include "lxcpp/attach/attach-helper.hpp"
+
+#include "utils/fd-utils.hpp"
+#include "utils/typeinfo.hpp"
+
+// TODO: Implement passing logger configuration and uncomment this.
+// #include "logger/logger.hpp"
+
+#include <iostream>
+#include <unistd.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc == 1) {
+ std::cout << "This file should not be executed by hand" << std::endl;
+ ::_exit(EXIT_FAILURE);
+ }
+
+ // NOTE: this might not be required now, but I leave it here not to forget.
+ // We need to investigate this with vasum and think about possibility of
+ // poorly written software that leaks file descriptors and might use LXCPP.
+#if 0
+ for(int fd = 3; fd < ::sysconf(_SC_OPEN_MAX); ++fd) {
+ if(fd != std::stoi(argv[1])) {
+ utils::close(fd);
+ }
+ }
+#endif
+
+ try {
+ int fd = std::stoi(argv[1]);
+ lxcpp::AttachHelper attachHelper(fd);
+ attachHelper.execute();
+ return EXIT_SUCCESS;
+ } catch(std::exception& e) {
+ // TODO: Implement passing logger configuration and uncomment this.
+ // LOGE("Unexpected: " << utils::getTypeName(e) << ": " << e.what());
+ return EXIT_FAILURE;
+ }
+}
#include "lxcpp/commands/attach.hpp"
#include "lxcpp/exception.hpp"
#include "lxcpp/process.hpp"
-#include "lxcpp/filesystem.hpp"
-#include "lxcpp/namespace.hpp"
-#include "lxcpp/capability.hpp"
-#include "lxcpp/environment.hpp"
-#include "lxcpp/credentials.hpp"
#include "utils/exception.hpp"
#include "utils/fd-utils.hpp"
#include "logger/logger.hpp"
#include <unistd.h>
-#include <sys/mount.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-#include <functional>
namespace lxcpp {
-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);
- }
-
- */
-}
-
-bool setupControlTTY(const int ttyFD)
-{
- if (!::isatty(ttyFD)) {
- return false;
- }
-
- if (::setsid() < 0) {
- return false;
- }
-
- if (::ioctl(ttyFD, TIOCSCTTY, NULL) < 0) {
- return false;
- }
-
- if (::dup2(ttyFD, STDIN_FILENO) < 0) {
- return false;
- }
-
- if (::dup2(ttyFD, STDOUT_FILENO) < 0) {
- return false;
- }
-
- if (::dup2(ttyFD, STDERR_FILENO) < 0) {
- return false;
- }
-
- return true;
-}
-
-int execFunction(void* call)
-{
- try {
- return (*static_cast<Attach::Call*>(call))();
- } catch(...) {
- return -1; // Non-zero on failure
- }
- return 0; // Success
-}
-
-} // namespace
-
-Attach::Attach(lxcpp::ContainerImpl& container,
- Container::AttachCall& userCall,
+Attach::Attach(const lxcpp::ContainerImpl& container,
+ const std::vector<const char*>& argv,
const uid_t uid,
const gid_t gid,
const std::string& ttyPath,
const std::string& workDirInContainer,
const std::vector<std::string>& envToKeep,
const std::vector<std::pair<std::string, std::string>>& envToSet)
- : mContainer(container),
- mUserCall(userCall),
- mUid(uid),
- mGid(gid),
- mSupplementaryGids(supplementaryGids),
- mCapsToKeep(capsToKeep),
- mWorkDirInContainer(workDirInContainer),
- mEnvToKeep(envToKeep),
- mEnvToSet(envToSet)
+ : mIntermChannel(false),
+ mConfig(argv,
+ container.getInitPid(),
+ container.getNamespaces(),
+ uid,
+ gid,
+ supplementaryGids,
+ capsToKeep,
+ workDirInContainer,
+ envToKeep,
+ envToSet)
{
- mTTYFD = utils::open(ttyPath, O_RDWR | O_NOCTTY);
+ // Set TTY
+ if (ttyPath.empty()) {
+ mConfig.ttyFD = -1;
+ } else {
+ mConfig.ttyFD = utils::open(ttyPath, O_RDWR | O_NOCTTY);
+ }
}
Attach::~Attach()
{
- utils::close(mTTYFD);
+ utils::close(mConfig.ttyFD);
}
void Attach::execute()
{
- // Channels for setup synchronization
- utils::Channel intermChannel;
-
- Call call = std::bind(&Attach::child,
- mUserCall,
- mUid,
- mGid,
- mTTYFD,
- mSupplementaryGids,
- mCapsToKeep,
- mEnvToKeep,
- mEnvToSet);
+ // Channels for passing configuration and synchronization
+ const std::string mIntermChannelFDStr = std::to_string(mIntermChannel.getRightFD());
const pid_t interPid = lxcpp::fork();
if (interPid > 0) {
- intermChannel.setLeft();
- parent(intermChannel, interPid);
- intermChannel.shutdown();
- } else {
- // TODO: only safe functions mentioned in signal(7) should be used below.
- // This is not the case now, needs fixing.
- intermChannel.setRight();
- interm(intermChannel, call);
- intermChannel.shutdown();
- ::_exit(EXIT_SUCCESS);
- }
-}
-
-int Attach::child(const Container::AttachCall& call,
- const uid_t uid,
- const gid_t gid,
- const int ttyFD,
- const std::vector<gid_t>& supplementaryGids,
- const int capsToKeep,
- const std::vector<std::string>& envToKeep,
- const std::vector<std::pair<std::string, std::string>>& envToSet)
-{
- // Setup /proc /sys mount
- setupMountPoints();
+ mIntermChannel.setLeft();
- // Setup capabilities
- dropCapsFromBoundingExcept(capsToKeep);
+ parent(interPid);
- // Setup environment variables
- clearenvExcept(envToKeep);
- setenv(envToSet);
-
- // Set uid/gids
- lxcpp::setgid(gid);
- setgroups(supplementaryGids);
-
- lxcpp::setuid(uid);
+ } else {
+ mIntermChannel.setRight();
- // Set control TTY
- if(!setupControlTTY(ttyFD)) {
+ const char *argv[] = {ATTACH_PATH,
+ mIntermChannelFDStr.c_str(),
+ NULL
+ };
+ ::execve(argv[0], const_cast<char *const*>(argv), nullptr);
::_exit(EXIT_FAILURE);
}
-
- // Run user's code
- return call();
}
-void Attach::parent(utils::Channel& intermChannel, const pid_t interPid)
+void Attach::parent(const pid_t interPid)
{
// TODO: Setup cgroups etc
- const pid_t childPid = intermChannel.read<pid_t>();
+ const pid_t childPid = mIntermChannel.read<pid_t>();
// Wait for all processes
lxcpp::waitpid(interPid);
lxcpp::waitpid(childPid);
}
-void Attach::interm(utils::Channel& intermChannel, Call& call)
-{
- lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces());
-
- // Change the current work directory
- // workDirInContainer is a path relative to the container's root
- lxcpp::chdir(mWorkDirInContainer);
-
- // PID namespace won't affect the returned pid
- // CLONE_PARENT: Child's PPID == Caller's PID
- const pid_t childPid = lxcpp::clone(execFunction,
- &call,
- CLONE_PARENT);
- intermChannel.write(childPid);
-}
-
} // namespace lxcpp
#define LXCPP_COMMANDS_ATTACH_HPP
#include "lxcpp/commands/command.hpp"
+#include "lxcpp/attach/attach-config.hpp"
#include "lxcpp/container-impl.hpp"
#include "utils/channel.hpp"
class Attach final: Command {
public:
- typedef std::function<int(void)> Call;
/**
* Runs call in the container's context
* It will not be stored for future use like most other commands.
*
* @param container container to which it attaches
- * @param userCall user's function to run
+ * @param argv path and arguments for the user's executable
* @param uid uid in the container
* @param gid gid in the container
+ * @param ttyPath path of the TTY in the host
* @param supplementaryGids supplementary groups in container
* @param capsToKeep capabilities that will be kept
* @param workDirInContainer work directory set for the new process
* @param envToKeep environment variables that will be kept
* @param envToSet new environment variables that will be set
*/
- Attach(lxcpp::ContainerImpl& container,
- Container::AttachCall& userCall,
+ Attach(const lxcpp::ContainerImpl& container,
+ const std::vector<const char*>& argv,
const uid_t uid,
const gid_t gid,
const std::string& ttyPath,
void execute();
private:
- const lxcpp::ContainerImpl& mContainer;
- const Container::AttachCall& mUserCall;
- const uid_t mUid;
- const gid_t mGid;
- int mTTYFD;
- const std::vector<gid_t>& mSupplementaryGids;
- const int mCapsToKeep;
- const std::string& mWorkDirInContainer;
- const std::vector<std::string>& mEnvToKeep;
- const std::vector<std::pair<std::string, std::string>>& mEnvToSet;
+ utils::Channel mIntermChannel;
+ AttachConfig mConfig;
- // Methods for different stages of setting up the attachment
- static int child(const Container::AttachCall& call,
- const uid_t uid,
- const gid_t gid,
- const int ttyFD,
- const std::vector<gid_t>& supplementaryGids,
- const int capsToKeep,
- const std::vector<std::string>& envToKeep,
- const std::vector<std::pair<std::string, std::string>>& envToSet);
+ void parent(const pid_t pid);
- void parent(utils::Channel& intermChannel,
- const pid_t pid);
-
- void interm(utils::Channel& intermChannel,
- Call& call);
};
} // namespace lxcpp
--- /dev/null
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact: Lukasz Pawelczyk (l.pawelczyk@partner.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
+ * @author Lukasz Pawelczyk (l.pawelczyk@partner.samsung.com)
+ * @brief Configuration file for the code
+ */
+
+
+#ifndef COMMON_CONFIG_HPP
+#define COMMON_CONFIG_HPP
+
+
+#ifdef __clang__
+#define CLANG_VERSION (__clang__major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
+#endif // __clang__
+
+#if defined __GNUC__ && !defined __clang__ // clang also defines GCC versions
+#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif // __GNUC__
+
+
+#ifdef GCC_VERSION
+
+#if GCC_VERSION < 40800
+// GCC 4.8 is the first where those defines are not required for
+// std::this_thread::sleep_for() and ::yield(). They might exist though
+// in previous versions depending on the build configuration of the GCC.
+#ifndef _GLIBCXX_USE_NANOSLEEP
+#define _GLIBCXX_USE_NANOSLEEP
+#endif // _GLIBCXX_USE_NANOSLEEP
+#ifndef _GLIBCXX_USE_SCHED_YIELD
+#define _GLIBCXX_USE_SCHED_YIELD
+#endif // _GLIBCXX_USE_SCHED_YIELD
+#endif // GCC_VERSION < 40800
+
+#if GCC_VERSION < 40700
+// Those appeared in 4.7 with full c++11 support
+#define final
+#define override
+#define thread_local __thread // use GCC extension instead of C++11
+#define steady_clock monotonic_clock
+#endif // GCC_VERSION < 40700
+
+#endif // GCC_VERSION
+
+// Variadic macros support for boost preprocessor should be enabled
+// manually for clang since they are marked as untested feature
+// (boost trunk if fixed but the latest 1.55 version is not,
+// see boost/preprocessor/config/config.hpp)
+#ifdef __clang__
+#define BOOST_PP_VARIADICS 1
+#endif
+
+// This has to be defined always when the boost has not been compiled
+// using C++11. Headers detect that you are compiling using C++11 and
+// blindly and wrongly assume that boost has been as well.
+#ifndef BOOST_NO_CXX11_SCOPED_ENUMS
+#define BOOST_NO_CXX11_SCOPED_ENUMS 1
+#endif
+
+#endif // COMMON_CONFIG_HPP
throw NotImplementedException();
}
-void ContainerImpl::attach(Container::AttachCall& call,
+void ContainerImpl::attach(const std::vector<const char*>& argv,
const std::string& cwdInContainer)
{
Attach attach(*this,
- call,
+ argv,
/*uid in container*/ 0,
/*gid in container*/ 0,
"/dev/tty",
/*capsToKeep*/ 0,
cwdInContainer,
/*envToKeep*/ {},
- /*envInContainer*/ {{"container","lxcpp"}});
+ /*envInContainer*/ {{"container","lxcpp"}});
// TODO: Env variables should agree with the ones already in the container
attach.execute();
}
void reboot();
// Other
- void attach(Container::AttachCall& attachCall,
+ void attach(const std::vector<const char*>& argv,
const std::string& cwdInContainer);
// Network interfaces setup/config
class Container {
public:
- typedef std::function<int(void)> AttachCall;
-
virtual ~Container() {};
// Configuration
virtual void reboot() = 0;
// Other
- virtual void attach(AttachCall& attachCall,
+ virtual void attach(const std::vector<const char*>& argv,
const std::string& cwdInContainer) = 0;
// Network interfaces setup/config
#endif
#include "lxcpp/exception.hpp"
+#include "lxcpp/namespace.hpp"
+#include "lxcpp/filesystem.hpp"
+#include "lxcpp/process.hpp"
#include "logger/logger.hpp"
#include "utils/fd-utils.hpp"
#include <iterator>
#include <unistd.h>
#include <string.h>
+
#include <sys/prctl.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
namespace lxcpp {
::strcpy(mem, title.c_str());
}
+void setupMountPoints()
+{
+#if 0
+ // 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);
+ }
+#endif
+}
+
+bool setupControlTTY(const int ttyFD)
+{
+ if (ttyFD != -1) {
+ return true;
+ }
+
+ if (!::isatty(ttyFD)) {
+ return false;
+ }
+
+ if (::setsid() < 0) {
+ return false;
+ }
+
+ if (::ioctl(ttyFD, TIOCSCTTY, NULL) < 0) {
+ return false;
+ }
+
+ if (::dup2(ttyFD, STDIN_FILENO) < 0) {
+ return false;
+ }
+
+ if (::dup2(ttyFD, STDOUT_FILENO) < 0) {
+ return false;
+ }
+
+ if (::dup2(ttyFD, STDERR_FILENO) < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+
} // namespace lxcpp
*/
void setProcTitle(const std::string &title);
+void setupMountPoints();
+
+bool setupControlTTY(const int ttyFD);
+
} // namespace lxcpp
%defattr(644,root,root,755)
%{_libdir}/liblxcpp.so.0
%attr(755,root,root) %{_libexecdir}/lxcpp-guard
+%attr(755,root,root) %{_libexecdir}/lxcpp-attach
%attr(755,root,root) %{_libdir}/liblxcpp.so.%{version}
%package -n liblxcpp-devel