2 * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License version 2.1 as published by the Free Software Foundation.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 * @author Jan Olszak (j.olszak@samsung.com)
21 * @brief Implementation of attaching to a container
24 #include "lxcpp/commands/attach-manager.hpp"
25 #include "lxcpp/exception.hpp"
26 #include "lxcpp/process.hpp"
27 #include "lxcpp/filesystem.hpp"
28 #include "lxcpp/namespace.hpp"
29 #include "lxcpp/capability.hpp"
30 #include "lxcpp/environment.hpp"
32 #include "utils/exception.hpp"
35 #include <sys/mount.h>
43 void setupMountPoints()
45 /* TODO: Uncomment when preparing the final attach() version
47 // TODO: This unshare should be optional only if we attach to PID/NET namespace, but not MNT.
48 // Otherwise container already has remounted /proc /sys
49 lxcpp::unshare(Namespace::MNT);
51 if (isMountPointShared("/")) {
52 // TODO: Handle case when the container rootfs or mount location is MS_SHARED, but not '/'
53 lxcpp::mount(nullptr, "/", nullptr, MS_SLAVE | MS_REC, nullptr);
56 if(isMountPoint("/proc")) {
57 lxcpp::umount("/proc", MNT_DETACH);
58 lxcpp::mount("none", "/proc", "proc", 0, nullptr);
61 if(isMountPoint("/sys")) {
62 lxcpp::umount("/sys", MNT_DETACH);
63 lxcpp::mount("none", "/sys", "sysfs", 0, nullptr);
69 int execFunction(void* call)
72 return (*static_cast<AttachManager::Call*>(call))();
74 return -1; // Non-zero on failure
81 AttachManager::AttachManager(lxcpp::ContainerImpl& container)
82 : mContainer(container)
86 AttachManager::~AttachManager()
90 void AttachManager::attach(Container::AttachCall& userCall,
92 const std::string& workDirInContainer,
93 const std::vector<std::string>& envToKeep,
94 const std::vector<std::pair<std::string, std::string>>& envToSet)
96 // Channels for setup synchronization
97 utils::Channel intermChannel;
99 Call call = std::bind(&AttachManager::child,
102 std::move(envToKeep),
103 std::move(envToSet));
105 const pid_t interPid = lxcpp::fork();
107 intermChannel.setLeft();
108 parent(intermChannel, interPid);
109 intermChannel.shutdown();
111 intermChannel.setRight();
112 interm(intermChannel, workDirInContainer, call);
113 intermChannel.shutdown();
118 int AttachManager::child(const Container::AttachCall& call,
119 const int capsToKeep,
120 const std::vector<std::string>& envToKeep,
121 const std::vector<std::pair<std::string, std::string>>& envToSet)
123 // Setup capabilities
124 dropCapsFromBoundingExcept(capsToKeep);
126 // Setup /proc /sys mount
129 // Setup environment variables
130 clearenvExcept(envToKeep);
137 void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid)
139 // TODO: Setup cgroups etc
140 const pid_t childPid = intermChannel.read<pid_t>();
142 // Wait for all processes
143 lxcpp::waitpid(interPid);
144 lxcpp::waitpid(childPid);
147 void AttachManager::interm(utils::Channel& intermChannel,
148 const std::string& workDirInContainer,
151 lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces());
153 // Change the current work directory
154 // workDirInContainer is a path relative to the container's root
155 lxcpp::chdir(workDirInContainer);
157 // PID namespace won't affect the returned pid
158 // CLONE_PARENT: Child's PPID == Caller's PID
159 const pid_t childPid = lxcpp::clone(execFunction,
162 intermChannel.write(childPid);