]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nspawn/nspawn-register.c
nspawn: permit prefixing of source paths in --bind= and --overlay= with "+"
[thirdparty/systemd.git] / src / nspawn / nspawn-register.c
CommitLineData
b7103bc5
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2015 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
20#include "sd-bus.h"
21
b7103bc5 22#include "bus-error.h"
20b16441 23#include "bus-unit-util.h"
8fcde012 24#include "bus-util.h"
b7103bc5 25#include "nspawn-register.h"
8fcde012
LP
26#include "stat-util.h"
27#include "strv.h"
28#include "util.h"
b7103bc5
LP
29
30int register_machine(
31 const char *machine_name,
32 pid_t pid,
33 const char *directory,
34 sd_id128_t uuid,
35 int local_ifindex,
36 const char *slice,
37 CustomMount *mounts,
38 unsigned n_mounts,
39 int kill_signal,
40 char **properties,
6aadfa4c
ILG
41 bool keep_unit,
42 const char *service) {
b7103bc5 43
4afd3348
LP
44 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
45 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
b7103bc5
LP
46 int r;
47
48 r = sd_bus_default_system(&bus);
49 if (r < 0)
50 return log_error_errno(r, "Failed to open system bus: %m");
51
52 if (keep_unit) {
53 r = sd_bus_call_method(
54 bus,
55 "org.freedesktop.machine1",
56 "/org/freedesktop/machine1",
57 "org.freedesktop.machine1.Manager",
58 "RegisterMachineWithNetwork",
59 &error,
60 NULL,
61 "sayssusai",
62 machine_name,
63 SD_BUS_MESSAGE_APPEND_ID128(uuid),
6aadfa4c 64 service,
b7103bc5
LP
65 "container",
66 (uint32_t) pid,
67 strempty(directory),
68 local_ifindex > 0 ? 1 : 0, local_ifindex);
69 } else {
4afd3348 70 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
b7103bc5
LP
71 unsigned j;
72
73 r = sd_bus_message_new_method_call(
74 bus,
75 &m,
76 "org.freedesktop.machine1",
77 "/org/freedesktop/machine1",
78 "org.freedesktop.machine1.Manager",
79 "CreateMachineWithNetwork");
80 if (r < 0)
81 return bus_log_create_error(r);
82
83 r = sd_bus_message_append(
84 m,
85 "sayssusai",
86 machine_name,
87 SD_BUS_MESSAGE_APPEND_ID128(uuid),
6aadfa4c 88 service,
b7103bc5
LP
89 "container",
90 (uint32_t) pid,
91 strempty(directory),
92 local_ifindex > 0 ? 1 : 0, local_ifindex);
93 if (r < 0)
94 return bus_log_create_error(r);
95
96 r = sd_bus_message_open_container(m, 'a', "(sv)");
97 if (r < 0)
98 return bus_log_create_error(r);
99
100 if (!isempty(slice)) {
101 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
102 if (r < 0)
103 return bus_log_create_error(r);
104 }
105
54cd6556 106 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
b7103bc5
LP
107 if (r < 0)
108 return bus_log_create_error(r);
109
110 /* If you make changes here, also make sure to update
111 * systemd-nspawn@.service, to keep the device
112 * policies in sync regardless if we are run with or
113 * without the --keep-unit switch. */
54cd6556 114 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
b7103bc5
LP
115 /* Allow the container to
116 * access and create the API
117 * device nodes, so that
118 * PrivateDevices= in the
119 * container can work
120 * fine */
b7103bc5
LP
121 "/dev/net/tun", "rwm",
122 /* Allow the container
123 * access to ptys. However,
124 * do not permit the
125 * container to ever create
126 * these device nodes. */
54cd6556 127 "char-pts", "rw");
b7103bc5
LP
128 if (r < 0)
129 return bus_log_create_error(r);
130
131 for (j = 0; j < n_mounts; j++) {
132 CustomMount *cm = mounts + j;
133
134 if (cm->type != CUSTOM_MOUNT_BIND)
135 continue;
136
137 r = is_device_node(cm->source);
86c0dd4a
LP
138 if (r == -ENOENT) {
139 /* The bind source might only appear as the image is put together, hence don't complain */
140 log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
141 continue;
142 }
b7103bc5
LP
143 if (r < 0)
144 return log_error_errno(r, "Failed to stat %s: %m", cm->source);
145
146 if (r) {
147 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
148 cm->source, cm->read_only ? "r" : "rw");
149 if (r < 0)
150 return log_error_errno(r, "Failed to append message arguments: %m");
151 }
152 }
153
154 if (kill_signal != 0) {
155 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
156 if (r < 0)
157 return bus_log_create_error(r);
158
159 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
160 if (r < 0)
161 return bus_log_create_error(r);
162 }
163
8673cf13
LP
164 r = bus_append_unit_property_assignment_many(m, properties);
165 if (r < 0)
166 return r;
b7103bc5
LP
167
168 r = sd_bus_message_close_container(m);
169 if (r < 0)
170 return bus_log_create_error(r);
171
172 r = sd_bus_call(bus, m, 0, &error, NULL);
173 }
174
175 if (r < 0) {
176 log_error("Failed to register machine: %s", bus_error_message(&error, r));
177 return r;
178 }
179
180 return 0;
181}
182
183int terminate_machine(pid_t pid) {
4afd3348
LP
184 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
185 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
186 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
b7103bc5
LP
187 const char *path;
188 int r;
189
190 r = sd_bus_default_system(&bus);
191 if (r < 0)
192 return log_error_errno(r, "Failed to open system bus: %m");
193
194 r = sd_bus_call_method(
195 bus,
196 "org.freedesktop.machine1",
197 "/org/freedesktop/machine1",
198 "org.freedesktop.machine1.Manager",
199 "GetMachineByPID",
200 &error,
201 &reply,
202 "u",
203 (uint32_t) pid);
204 if (r < 0) {
205 /* Note that the machine might already have been
206 * cleaned up automatically, hence don't consider it a
207 * failure if we cannot get the machine object. */
208 log_debug("Failed to get machine: %s", bus_error_message(&error, r));
209 return 0;
210 }
211
212 r = sd_bus_message_read(reply, "o", &path);
213 if (r < 0)
214 return bus_log_parse_error(r);
215
216 r = sd_bus_call_method(
217 bus,
218 "org.freedesktop.machine1",
219 path,
220 "org.freedesktop.machine1.Machine",
221 "Terminate",
222 &error,
223 NULL,
224 NULL);
225 if (r < 0) {
226 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
227 return 0;
228 }
229
230 return 0;
231}