]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nspawn/nspawn-register.c
Fail on unknown (alphanumerical) specifiers
[thirdparty/systemd.git] / src / nspawn / nspawn-register.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
b7103bc5
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2015 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
21#include "sd-bus.h"
22
b7103bc5 23#include "bus-error.h"
20b16441 24#include "bus-unit-util.h"
8fcde012 25#include "bus-util.h"
b7103bc5 26#include "nspawn-register.h"
8fcde012
LP
27#include "stat-util.h"
28#include "strv.h"
29#include "util.h"
b7103bc5 30
cd2dfc6f
LP
31static int append_machine_properties(
32 sd_bus_message *m,
33 CustomMount *mounts,
34 unsigned n_mounts,
35 int kill_signal,
36 char **properties) {
37
38 unsigned j;
39 int r;
40
41 assert(m);
42
43 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
44 if (r < 0)
45 return bus_log_create_error(r);
46
47 /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in
48 * sync regardless if we are run with or without the --keep-unit switch. */
49 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
50 /* Allow the container to
51 * access and create the API
52 * device nodes, so that
53 * PrivateDevices= in the
54 * container can work
55 * fine */
56 "/dev/net/tun", "rwm",
57 /* Allow the container
58 * access to ptys. However,
59 * do not permit the
60 * container to ever create
61 * these device nodes. */
62 "char-pts", "rw");
63 if (r < 0)
64 return bus_log_create_error(r);
65
66 for (j = 0; j < n_mounts; j++) {
67 CustomMount *cm = mounts + j;
68
69 if (cm->type != CUSTOM_MOUNT_BIND)
70 continue;
71
72 r = is_device_node(cm->source);
73 if (r == -ENOENT) {
74 /* The bind source might only appear as the image is put together, hence don't complain */
75 log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
76 continue;
77 }
78 if (r < 0)
79 return log_error_errno(r, "Failed to stat %s: %m", cm->source);
80
81 if (r) {
82 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
83 cm->source, cm->read_only ? "r" : "rw");
84 if (r < 0)
85 return log_error_errno(r, "Failed to append message arguments: %m");
86 }
87 }
88
89 if (kill_signal != 0) {
90 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
91 if (r < 0)
92 return bus_log_create_error(r);
93
94 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
95 if (r < 0)
96 return bus_log_create_error(r);
97 }
98
99 return 0;
100}
101
abdb9b08
LP
102static int append_controller_property(sd_bus *bus, sd_bus_message *m) {
103 const char *unique;
104 int r;
105
106 assert(bus);
107 assert(m);
108
109 r = sd_bus_get_unique_name(bus, &unique);
110 if (r < 0)
111 return log_error_errno(r, "Failed to get unique name: %m");
112
113 r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique);
114 if (r < 0)
115 return bus_log_create_error(r);
116
117 return 0;
118}
119
b7103bc5 120int register_machine(
abdb9b08 121 sd_bus *bus,
b7103bc5
LP
122 const char *machine_name,
123 pid_t pid,
124 const char *directory,
125 sd_id128_t uuid,
126 int local_ifindex,
127 const char *slice,
128 CustomMount *mounts,
129 unsigned n_mounts,
130 int kill_signal,
131 char **properties,
6aadfa4c
ILG
132 bool keep_unit,
133 const char *service) {
b7103bc5 134
4afd3348 135 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
b7103bc5
LP
136 int r;
137
abdb9b08 138 assert(bus);
b7103bc5
LP
139
140 if (keep_unit) {
141 r = sd_bus_call_method(
142 bus,
143 "org.freedesktop.machine1",
144 "/org/freedesktop/machine1",
145 "org.freedesktop.machine1.Manager",
146 "RegisterMachineWithNetwork",
147 &error,
148 NULL,
149 "sayssusai",
150 machine_name,
151 SD_BUS_MESSAGE_APPEND_ID128(uuid),
6aadfa4c 152 service,
b7103bc5
LP
153 "container",
154 (uint32_t) pid,
155 strempty(directory),
156 local_ifindex > 0 ? 1 : 0, local_ifindex);
157 } else {
4afd3348 158 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
b7103bc5
LP
159
160 r = sd_bus_message_new_method_call(
161 bus,
162 &m,
163 "org.freedesktop.machine1",
164 "/org/freedesktop/machine1",
165 "org.freedesktop.machine1.Manager",
166 "CreateMachineWithNetwork");
167 if (r < 0)
168 return bus_log_create_error(r);
169
170 r = sd_bus_message_append(
171 m,
172 "sayssusai",
173 machine_name,
174 SD_BUS_MESSAGE_APPEND_ID128(uuid),
6aadfa4c 175 service,
b7103bc5
LP
176 "container",
177 (uint32_t) pid,
178 strempty(directory),
179 local_ifindex > 0 ? 1 : 0, local_ifindex);
180 if (r < 0)
181 return bus_log_create_error(r);
182
183 r = sd_bus_message_open_container(m, 'a', "(sv)");
184 if (r < 0)
185 return bus_log_create_error(r);
186
187 if (!isempty(slice)) {
188 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
189 if (r < 0)
190 return bus_log_create_error(r);
191 }
192
abdb9b08
LP
193 r = append_controller_property(bus, m);
194 if (r < 0)
195 return r;
196
cd2dfc6f
LP
197 r = append_machine_properties(
198 m,
199 mounts,
200 n_mounts,
201 kill_signal,
202 properties);
b7103bc5 203 if (r < 0)
cd2dfc6f 204 return r;
b7103bc5 205
8673cf13
LP
206 r = bus_append_unit_property_assignment_many(m, properties);
207 if (r < 0)
208 return r;
b7103bc5
LP
209
210 r = sd_bus_message_close_container(m);
211 if (r < 0)
212 return bus_log_create_error(r);
213
214 r = sd_bus_call(bus, m, 0, &error, NULL);
215 }
216
217 if (r < 0) {
218 log_error("Failed to register machine: %s", bus_error_message(&error, r));
219 return r;
220 }
221
222 return 0;
223}
224
abdb9b08 225int terminate_machine(sd_bus *bus, pid_t pid) {
4afd3348
LP
226 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
227 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
b7103bc5
LP
228 const char *path;
229 int r;
230
abdb9b08 231 assert(bus);
b7103bc5
LP
232
233 r = sd_bus_call_method(
234 bus,
235 "org.freedesktop.machine1",
236 "/org/freedesktop/machine1",
237 "org.freedesktop.machine1.Manager",
238 "GetMachineByPID",
239 &error,
240 &reply,
241 "u",
242 (uint32_t) pid);
243 if (r < 0) {
244 /* Note that the machine might already have been
245 * cleaned up automatically, hence don't consider it a
246 * failure if we cannot get the machine object. */
247 log_debug("Failed to get machine: %s", bus_error_message(&error, r));
248 return 0;
249 }
250
251 r = sd_bus_message_read(reply, "o", &path);
252 if (r < 0)
253 return bus_log_parse_error(r);
254
255 r = sd_bus_call_method(
256 bus,
257 "org.freedesktop.machine1",
258 path,
259 "org.freedesktop.machine1.Machine",
260 "Terminate",
261 &error,
262 NULL,
263 NULL);
264 if (r < 0) {
265 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
266 return 0;
267 }
268
269 return 0;
270}
cd2dfc6f
LP
271
272int allocate_scope(
abdb9b08 273 sd_bus *bus,
cd2dfc6f
LP
274 const char *machine_name,
275 pid_t pid,
276 const char *slice,
277 CustomMount *mounts,
278 unsigned n_mounts,
279 int kill_signal,
280 char **properties) {
281
282 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
283 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
0a5706d1
ZJS
284 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
285 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
cd2dfc6f 286 _cleanup_free_ char *scope = NULL;
0a5706d1 287 const char *description, *object;
cd2dfc6f
LP
288 int r;
289
abdb9b08 290 assert(bus);
cd2dfc6f 291
0a5706d1
ZJS
292 r = bus_wait_for_jobs_new(bus, &w);
293 if (r < 0)
294 return log_error_errno(r, "Could not watch job: %m");
295
cd2dfc6f
LP
296 r = unit_name_mangle_with_suffix(machine_name, UNIT_NAME_NOGLOB, ".scope", &scope);
297 if (r < 0)
298 return log_error_errno(r, "Failed to mangle scope name: %m");
299
300 r = sd_bus_message_new_method_call(
301 bus,
302 &m,
303 "org.freedesktop.systemd1",
304 "/org/freedesktop/systemd1",
305 "org.freedesktop.systemd1.Manager",
306 "StartTransientUnit");
307 if (r < 0)
308 return bus_log_create_error(r);
309
310 r = sd_bus_message_append(m, "ss", scope, "fail");
311 if (r < 0)
312 return bus_log_create_error(r);
313
314 /* Properties */
315 r = sd_bus_message_open_container(m, 'a', "(sv)");
316 if (r < 0)
317 return bus_log_create_error(r);
318
319 description = strjoina("Container ", machine_name);
320
321 r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
322 "PIDs", "au", 1, pid,
323 "Description", "s", description,
324 "Delegate", "b", 1,
325 "Slice", "s", isempty(slice) ? "machine.slice" : slice);
326 if (r < 0)
327 return bus_log_create_error(r);
328
abdb9b08
LP
329 r = append_controller_property(bus, m);
330 if (r < 0)
331 return r;
332
cd2dfc6f
LP
333 r = append_machine_properties(
334 m,
335 mounts,
336 n_mounts,
337 kill_signal,
338 properties);
339 if (r < 0)
340 return r;
341
342 r = bus_append_unit_property_assignment_many(m, properties);
343 if (r < 0)
344 return r;
345
346 r = sd_bus_message_close_container(m);
347 if (r < 0)
348 return bus_log_create_error(r);
349
350 /* No auxiliary units */
351 r = sd_bus_message_append(
352 m,
353 "a(sa(sv))",
354 0);
355 if (r < 0)
356 return bus_log_create_error(r);
357
0a5706d1 358 r = sd_bus_call(bus, m, 0, &error, &reply);
cd2dfc6f
LP
359 if (r < 0) {
360 log_error("Failed to allocate scope: %s", bus_error_message(&error, r));
361 return r;
362 }
363
0a5706d1
ZJS
364 r = sd_bus_message_read(reply, "o", &object);
365 if (r < 0)
366 return bus_log_parse_error(r);
367
368 r = bus_wait_for_jobs_one(w, object, false);
369 if (r < 0)
370 return r;
371
cd2dfc6f
LP
372 return 0;
373}