Run Security Containers Server as non root user
[platform/core/security/vasum.git] / server / container-connection-transport.cpp
1 /*
2  *  Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Contact: Piotr Bartosiewicz <p.bartosiewi@partner.samsung.com>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License
17  */
18
19 /**
20  * @file
21  * @author  Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com)
22  * @brief   Implementation of a class for communication transport between container and server
23  */
24
25 #include "config.hpp"
26
27 #include "container-connection-transport.hpp"
28 #include "exception.hpp"
29
30 #include "utils/file-wait.hpp"
31 #include "utils/fs.hpp"
32 #include "log/logger.hpp"
33
34 #include <boost/filesystem.hpp>
35 #include <boost/system/system_error.hpp>
36
37 namespace security_containers {
38
39 namespace {
40
41 // Timeout in ms for waiting for dbus transport.
42 // Should be very long to ensure dbus in container is ready.
43 // TODO: this should be in container's configuration file
44 const unsigned int TRANSPORT_READY_TIMEOUT = 2 * 60 * 1000;
45
46 } // namespace
47
48
49 ContainerConnectionTransport::ContainerConnectionTransport(const std::string& runMountPoint)
50     : mRunMountPoint(runMountPoint), mDetachOnExit(false)
51 {
52     if (runMountPoint.empty()) {
53         return;
54     }
55     boost::system::error_code errorCode;
56     boost::filesystem::create_directories(runMountPoint, errorCode);
57     if (errorCode) {
58         LOGE("Initialization failed: could not create '" << runMountPoint << "' :" << errorCode);
59         throw ContainerConnectionException("Could not create: " + runMountPoint +
60                                            " :" + errorCode.message());
61     }
62
63     bool isMount = false;
64     if (!utils::isMountPoint(runMountPoint, isMount)) {
65         LOGE("Failed to check if " << runMountPoint << " is a mount point.");
66         throw ContainerConnectionException("Could not check if " + runMountPoint +
67                                            " is a mount point.");
68     }
69
70     if (!isMount) {
71         LOGD(runMountPoint << " not mounted - mounting.");
72
73         if (!utils::mountRun(runMountPoint)) {
74             LOGE("Initialization failed: could not mount " << runMountPoint);
75             throw ContainerConnectionException("Could not mount: " + runMountPoint);
76         }
77     }
78
79     // if there is no systemd in the container this dir won't be created automatically
80     // TODO: will require chown with USER namespace enabled
81     std::string dbusDirectory = runMountPoint + "/dbus";
82     boost::filesystem::create_directories(dbusDirectory, errorCode);
83     if (errorCode) {
84         LOGE("Initialization failed: could not create '" << dbusDirectory << "' :" << errorCode);
85         throw ContainerConnectionException("Could not create: " + dbusDirectory +
86                                            " :" + errorCode.message());
87     }
88 }
89
90
91 ContainerConnectionTransport::~ContainerConnectionTransport()
92 {
93     if (!mDetachOnExit) {
94         if (!mRunMountPoint.empty()) {
95             if (!utils::umount(mRunMountPoint)) {
96                 LOGE("Deinitialization failed: could not umount " << mRunMountPoint);
97             }
98         }
99     }
100 }
101
102
103 std::string ContainerConnectionTransport::acquireAddress()
104 {
105     if (mRunMountPoint.empty()) {
106         return std::string();
107     }
108
109     const std::string dbusPath = mRunMountPoint + "/dbus/system_bus_socket";
110
111     // TODO This should be done asynchronously.
112     LOGT("Waiting for " << dbusPath);
113     utils::waitForFile(dbusPath, TRANSPORT_READY_TIMEOUT);
114
115     return "unix:path=" + dbusPath;
116 }
117
118 void ContainerConnectionTransport::setDetachOnExit()
119 {
120     mDetachOnExit = true;
121 }
122
123 } // namespace security_containers