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.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<Attach::Call*>(call))();
74 return -1; // Non-zero on failure
81 Attach::Attach(lxcpp::ContainerImpl& container,
82 Container::AttachCall& userCall,
84 const std::string& workDirInContainer,
85 const std::vector<std::string>& envToKeep,
86 const std::vector<std::pair<std::string, std::string>>& envToSet)
87 : mContainer(container),
89 mCapsToKeep(capsToKeep),
90 mWorkDirInContainer(workDirInContainer),
91 mEnvToKeep(envToKeep),
100 void Attach::execute()
102 // Channels for setup synchronization
103 utils::Channel intermChannel;
105 Call call = std::bind(&Attach::child,
111 const pid_t interPid = lxcpp::fork();
113 intermChannel.setLeft();
114 parent(intermChannel, interPid);
115 intermChannel.shutdown();
117 intermChannel.setRight();
118 interm(intermChannel, call);
119 intermChannel.shutdown();
124 int Attach::child(const Container::AttachCall& call,
125 const int capsToKeep,
126 const std::vector<std::string>& envToKeep,
127 const std::vector<std::pair<std::string, std::string>>& envToSet)
129 // Setup capabilities
130 dropCapsFromBoundingExcept(capsToKeep);
132 // Setup /proc /sys mount
135 // Setup environment variables
136 clearenvExcept(envToKeep);
143 void Attach::parent(utils::Channel& intermChannel, const pid_t interPid)
145 // TODO: Setup cgroups etc
146 const pid_t childPid = intermChannel.read<pid_t>();
148 // Wait for all processes
149 lxcpp::waitpid(interPid);
150 lxcpp::waitpid(childPid);
153 void Attach::interm(utils::Channel& intermChannel, Call& call)
155 lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces());
157 // Change the current work directory
158 // workDirInContainer is a path relative to the container's root
159 lxcpp::chdir(mWorkDirInContainer);
161 // PID namespace won't affect the returned pid
162 // CLONE_PARENT: Child's PPID == Caller's PID
163 const pid_t childPid = lxcpp::clone(execFunction,
166 intermChannel.write(childPid);