ipc: Fix critical build break in unique-id
[platform/core/security/vasum.git] / libs / lxcpp / commands / attach-manager.cpp
1 /*
2  *  Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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.
7  *
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.
12  *
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
16  */
17
18 /**
19  * @file
20  * @author  Jan Olszak (j.olszak@samsung.com)
21  * @brief   Implementation of attaching to a container
22  */
23
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"
31
32 #include "utils/exception.hpp"
33
34 #include <unistd.h>
35 #include <sys/mount.h>
36
37 #include <functional>
38
39 namespace lxcpp {
40
41 namespace {
42
43 void setupMountPoints()
44 {
45     /* TODO: Uncomment when preparing the final attach() version
46
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);
50
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);
54     }
55
56     if(isMountPoint("/proc")) {
57         lxcpp::umount("/proc", MNT_DETACH);
58         lxcpp::mount("none", "/proc", "proc", 0, nullptr);
59     }
60
61     if(isMountPoint("/sys")) {
62         lxcpp::umount("/sys", MNT_DETACH);
63         lxcpp::mount("none", "/sys", "sysfs", 0, nullptr);
64     }
65
66     */
67 }
68
69 int execFunction(void* call)
70 {
71     try {
72         return (*static_cast<AttachManager::Call*>(call))();
73     } catch(...) {
74         return -1; // Non-zero on failure
75     }
76     return 0; // Success
77 }
78
79 } // namespace
80
81 AttachManager::AttachManager(lxcpp::ContainerImpl& container)
82     : mContainer(container)
83 {
84 }
85
86 AttachManager::~AttachManager()
87 {
88 }
89
90 void AttachManager::attach(Container::AttachCall& userCall,
91                            const int capsToKeep,
92                            const std::string& workDirInContainer,
93                            const std::vector<std::string>& envToKeep,
94                            const std::vector<std::pair<std::string, std::string>>& envToSet)
95 {
96     // Channels for setup synchronization
97     utils::Channel intermChannel;
98
99     Call call = std::bind(&AttachManager::child,
100                           std::move(userCall),
101                           capsToKeep,
102                           std::move(envToKeep),
103                           std::move(envToSet));
104
105     const pid_t interPid = lxcpp::fork();
106     if (interPid > 0) {
107         intermChannel.setLeft();
108         parent(intermChannel, interPid);
109         intermChannel.shutdown();
110     } else {
111         intermChannel.setRight();
112         interm(intermChannel, workDirInContainer, call);
113         intermChannel.shutdown();
114         ::_exit(0);
115     }
116 }
117
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)
122 {
123     // Setup capabilities
124     dropCapsFromBoundingExcept(capsToKeep);
125
126     // Setup /proc /sys mount
127     setupMountPoints();
128
129     // Setup environment variables
130     clearenvExcept(envToKeep);
131     setenv(envToSet);
132
133     // Run user's code
134     return call();
135 }
136
137 void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid)
138 {
139     // TODO: Setup cgroups etc
140     const pid_t childPid = intermChannel.read<pid_t>();
141
142     // Wait for all processes
143     lxcpp::waitpid(interPid);
144     lxcpp::waitpid(childPid);
145 }
146
147 void AttachManager::interm(utils::Channel& intermChannel,
148                            const std::string& workDirInContainer,
149                            Call& call)
150 {
151     lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces());
152
153     // Change the current work directory
154     // workDirInContainer is a path relative to the container's root
155     lxcpp::chdir(workDirInContainer);
156
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,
160                                         &call,
161                                         CLONE_PARENT);
162     intermChannel.write(childPid);
163
164 }
165
166 } // namespace lxcpp