]> git.proxmox.com Git - systemd.git/blame - src/nspawn/nspawn-register.c
New upstream version 236
[systemd.git] / src / nspawn / nspawn-register.c
CommitLineData
52ad194e 1/* SPDX-License-Identifier: LGPL-2.1+ */
d9dfd233
MP
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
d9dfd233 23#include "bus-error.h"
aa27b158 24#include "bus-unit-util.h"
db2df898 25#include "bus-util.h"
d9dfd233 26#include "nspawn-register.h"
db2df898
MP
27#include "stat-util.h"
28#include "strv.h"
29#include "util.h"
d9dfd233 30
81c58355
MB
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
52ad194e
MB
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
d9dfd233 120int register_machine(
52ad194e 121 sd_bus *bus,
d9dfd233
MP
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,
db2df898
MP
132 bool keep_unit,
133 const char *service) {
d9dfd233 134
4c89c718 135 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
d9dfd233
MP
136 int r;
137
52ad194e 138 assert(bus);
d9dfd233
MP
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),
db2df898 152 service,
d9dfd233
MP
153 "container",
154 (uint32_t) pid,
155 strempty(directory),
156 local_ifindex > 0 ? 1 : 0, local_ifindex);
157 } else {
4c89c718 158 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
d9dfd233
MP
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),
db2df898 175 service,
d9dfd233
MP
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
52ad194e
MB
193 r = append_controller_property(bus, m);
194 if (r < 0)
195 return r;
196
81c58355
MB
197 r = append_machine_properties(
198 m,
199 mounts,
200 n_mounts,
201 kill_signal,
202 properties);
d9dfd233 203 if (r < 0)
81c58355 204 return r;
d9dfd233 205
8a584da2
MP
206 r = bus_append_unit_property_assignment_many(m, properties);
207 if (r < 0)
208 return r;
d9dfd233
MP
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
52ad194e 225int terminate_machine(sd_bus *bus, pid_t pid) {
4c89c718
MP
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;
d9dfd233
MP
228 const char *path;
229 int r;
230
52ad194e 231 assert(bus);
d9dfd233
MP
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}
81c58355
MB
271
272int allocate_scope(
52ad194e 273 sd_bus *bus,
81c58355
MB
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;
81c58355
MB
284 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
285 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
286 _cleanup_free_ char *scope = NULL;
287 const char *description, *object;
288 int r;
289
52ad194e 290 assert(bus);
81c58355
MB
291
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
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
52ad194e
MB
329 r = append_controller_property(bus, m);
330 if (r < 0)
331 return r;
332
81c58355
MB
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
358 r = sd_bus_call(bus, m, 0, &error, &reply);
359 if (r < 0) {
360 log_error("Failed to allocate scope: %s", bus_error_message(&error, r));
361 return r;
362 }
363
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
372 return 0;
373}