]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nspawn/nspawn-register.c
Merge pull request #30284 from YHNdnzj/fstab-wantedby-defaultdeps
[thirdparty/systemd.git] / src / nspawn / nspawn-register.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
b7103bc5
LP
2
3#include "sd-bus.h"
4
b7103bc5 5#include "bus-error.h"
9b71e4ab 6#include "bus-locator.h"
20b16441 7#include "bus-unit-util.h"
8fcde012 8#include "bus-util.h"
e45c81b8 9#include "bus-wait-for-jobs.h"
b7103bc5 10#include "nspawn-register.h"
411d8c72 11#include "nspawn-settings.h"
910384c8 12#include "special.h"
8fcde012
LP
13#include "stat-util.h"
14#include "strv.h"
b7103bc5 15
cd2dfc6f
LP
16static int append_machine_properties(
17 sd_bus_message *m,
18 CustomMount *mounts,
19 unsigned n_mounts,
411d8c72
NR
20 int kill_signal,
21 bool coredump_receive) {
cd2dfc6f
LP
22
23 unsigned j;
24 int r;
25
26 assert(m);
27
28 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "closed");
29 if (r < 0)
30 return bus_log_create_error(r);
31
32 /* If you make changes here, also make sure to update systemd-nspawn@.service, to keep the device policies in
33 * sync regardless if we are run with or without the --keep-unit switch. */
34 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 2,
35 /* Allow the container to
36 * access and create the API
37 * device nodes, so that
38 * PrivateDevices= in the
39 * container can work
40 * fine */
41 "/dev/net/tun", "rwm",
42 /* Allow the container
43 * access to ptys. However,
44 * do not permit the
45 * container to ever create
46 * these device nodes. */
47 "char-pts", "rw");
48 if (r < 0)
49 return bus_log_create_error(r);
50
51 for (j = 0; j < n_mounts; j++) {
52 CustomMount *cm = mounts + j;
53
54 if (cm->type != CUSTOM_MOUNT_BIND)
55 continue;
56
57 r = is_device_node(cm->source);
58 if (r == -ENOENT) {
59 /* The bind source might only appear as the image is put together, hence don't complain */
60 log_debug_errno(r, "Bind mount source %s not found, ignoring: %m", cm->source);
61 continue;
62 }
63 if (r < 0)
64 return log_error_errno(r, "Failed to stat %s: %m", cm->source);
65
66 if (r) {
67 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
68 cm->source, cm->read_only ? "r" : "rw");
69 if (r < 0)
70 return log_error_errno(r, "Failed to append message arguments: %m");
71 }
72 }
73
74 if (kill_signal != 0) {
75 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
76 if (r < 0)
77 return bus_log_create_error(r);
78
79 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
80 if (r < 0)
81 return bus_log_create_error(r);
82 }
83
411d8c72
NR
84 if (coredump_receive) {
85 r = sd_bus_message_append(m, "(sv)", "CoredumpReceive", "b", true);
86 if (r < 0)
87 return bus_log_create_error(r);
88 }
89
cd2dfc6f
LP
90 return 0;
91}
92
abdb9b08
LP
93static int append_controller_property(sd_bus *bus, sd_bus_message *m) {
94 const char *unique;
95 int r;
96
97 assert(bus);
98 assert(m);
99
100 r = sd_bus_get_unique_name(bus, &unique);
101 if (r < 0)
102 return log_error_errno(r, "Failed to get unique name: %m");
103
104 r = sd_bus_message_append(m, "(sv)", "Controller", "s", unique);
105 if (r < 0)
106 return bus_log_create_error(r);
107
108 return 0;
109}
110
869c1cf8
NR
111static int can_set_coredump_receive(sd_bus *bus) {
112 _cleanup_(sd_bus_error_free) sd_bus_error e = SD_BUS_ERROR_NULL;
113 _cleanup_free_ char *path = NULL;
114 int b, r;
115
116 assert(bus);
117
118 path = unit_dbus_path_from_name(SPECIAL_INIT_SCOPE);
119 if (!path)
120 return log_oom();
121
122 r = sd_bus_get_property_trivial(
123 bus,
124 "org.freedesktop.systemd1",
125 path,
126 "org.freedesktop.systemd1.Scope",
127 "CoredumpReceive",
128 &e,
129 'b', &b);
130 if (r < 0 && !sd_bus_error_has_names(&e, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
131 log_warning_errno(r, "Failed to determine if CoredumpReceive= can be set, assuming it cannot be: %s",
132 bus_error_message(&e, r));
133
134 return r >= 0;
135}
136
b7103bc5 137int register_machine(
abdb9b08 138 sd_bus *bus,
b7103bc5
LP
139 const char *machine_name,
140 pid_t pid,
141 const char *directory,
142 sd_id128_t uuid,
143 int local_ifindex,
144 const char *slice,
145 CustomMount *mounts,
146 unsigned n_mounts,
147 int kill_signal,
148 char **properties,
de40a303 149 sd_bus_message *properties_message,
6aadfa4c 150 bool keep_unit,
411d8c72
NR
151 const char *service,
152 StartMode start_mode) {
b7103bc5 153
4afd3348 154 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
b7103bc5
LP
155 int r;
156
abdb9b08 157 assert(bus);
b7103bc5
LP
158
159 if (keep_unit) {
1ecaac5c 160 r = bus_call_method(
b7103bc5 161 bus,
1ecaac5c 162 bus_machine_mgr,
b7103bc5
LP
163 "RegisterMachineWithNetwork",
164 &error,
165 NULL,
166 "sayssusai",
167 machine_name,
168 SD_BUS_MESSAGE_APPEND_ID128(uuid),
6aadfa4c 169 service,
b7103bc5
LP
170 "container",
171 (uint32_t) pid,
172 strempty(directory),
173 local_ifindex > 0 ? 1 : 0, local_ifindex);
174 } else {
4afd3348 175 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
b7103bc5 176
1ecaac5c 177 r = bus_message_new_method_call(bus, &m, bus_machine_mgr, "CreateMachineWithNetwork");
b7103bc5
LP
178 if (r < 0)
179 return bus_log_create_error(r);
180
181 r = sd_bus_message_append(
182 m,
183 "sayssusai",
184 machine_name,
185 SD_BUS_MESSAGE_APPEND_ID128(uuid),
6aadfa4c 186 service,
b7103bc5
LP
187 "container",
188 (uint32_t) pid,
189 strempty(directory),
190 local_ifindex > 0 ? 1 : 0, local_ifindex);
191 if (r < 0)
192 return bus_log_create_error(r);
193
194 r = sd_bus_message_open_container(m, 'a', "(sv)");
195 if (r < 0)
196 return bus_log_create_error(r);
197
198 if (!isempty(slice)) {
199 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
200 if (r < 0)
201 return bus_log_create_error(r);
202 }
203
abdb9b08
LP
204 r = append_controller_property(bus, m);
205 if (r < 0)
206 return r;
207
cd2dfc6f
LP
208 r = append_machine_properties(
209 m,
210 mounts,
211 n_mounts,
411d8c72 212 kill_signal,
869c1cf8 213 start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
b7103bc5 214 if (r < 0)
cd2dfc6f 215 return r;
b7103bc5 216
de40a303
LP
217 if (properties_message) {
218 r = sd_bus_message_copy(m, properties_message, true);
219 if (r < 0)
220 return bus_log_create_error(r);
221 }
222
89ada3ba 223 r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
8673cf13
LP
224 if (r < 0)
225 return r;
b7103bc5
LP
226
227 r = sd_bus_message_close_container(m);
228 if (r < 0)
229 return bus_log_create_error(r);
230
231 r = sd_bus_call(bus, m, 0, &error, NULL);
232 }
4ae25393
YW
233 if (r < 0)
234 return log_error_errno(r, "Failed to register machine: %s", bus_error_message(&error, r));
b7103bc5
LP
235
236 return 0;
237}
238
0bb0a9fa 239int unregister_machine(
11d81e50
LP
240 sd_bus *bus,
241 const char *machine_name) {
242
4afd3348 243 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
b7103bc5
LP
244 int r;
245
abdb9b08 246 assert(bus);
b7103bc5 247
1ecaac5c 248 r = bus_call_method(bus, bus_machine_mgr, "UnregisterMachine", &error, NULL, "s", machine_name);
4ae25393 249 if (r < 0)
0bb0a9fa 250 log_debug("Failed to unregister machine: %s", bus_error_message(&error, r));
b7103bc5
LP
251
252 return 0;
253}
cd2dfc6f
LP
254
255int allocate_scope(
abdb9b08 256 sd_bus *bus,
cd2dfc6f
LP
257 const char *machine_name,
258 pid_t pid,
259 const char *slice,
260 CustomMount *mounts,
261 unsigned n_mounts,
262 int kill_signal,
de40a303 263 char **properties,
7eda208f 264 sd_bus_message *properties_message,
411d8c72
NR
265 bool allow_pidfd,
266 StartMode start_mode) {
cd2dfc6f 267
df61bc5e 268 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
cd2dfc6f 269 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
0a5706d1 270 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
cd2dfc6f 271 _cleanup_free_ char *scope = NULL;
0a5706d1 272 const char *description, *object;
cd2dfc6f
LP
273 int r;
274
abdb9b08 275 assert(bus);
cd2dfc6f 276
0a5706d1
ZJS
277 r = bus_wait_for_jobs_new(bus, &w);
278 if (r < 0)
279 return log_error_errno(r, "Could not watch job: %m");
280
df7c4eb6 281 r = unit_name_mangle_with_suffix(machine_name, "as machine name", 0, ".scope", &scope);
cd2dfc6f
LP
282 if (r < 0)
283 return log_error_errno(r, "Failed to mangle scope name: %m");
284
1ecaac5c 285 r = bus_message_new_method_call(bus, &m, bus_systemd_mgr, "StartTransientUnit");
cd2dfc6f
LP
286 if (r < 0)
287 return bus_log_create_error(r);
288
289 r = sd_bus_message_append(m, "ss", scope, "fail");
290 if (r < 0)
291 return bus_log_create_error(r);
292
293 /* Properties */
294 r = sd_bus_message_open_container(m, 'a', "(sv)");
295 if (r < 0)
296 return bus_log_create_error(r);
297
298 description = strjoina("Container ", machine_name);
299
7eda208f
LP
300 if (allow_pidfd) {
301 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
302 r = pidref_set_pid(&pidref, pid);
303 if (r < 0)
304 return log_error_errno(r, "Failed to allocate PID reference: %m");
305
306 r = bus_append_scope_pidref(m, &pidref);
307 } else
308 r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
309 if (r < 0)
310 return bus_log_create_error(r);
311
312 r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
cd2dfc6f
LP
313 "Description", "s", description,
314 "Delegate", "b", 1,
1d78fea2
LP
315 "CollectMode", "s", "inactive-or-failed",
316 "AddRef", "b", 1,
910384c8 317 "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
cd2dfc6f
LP
318 if (r < 0)
319 return bus_log_create_error(r);
320
abdb9b08
LP
321 r = append_controller_property(bus, m);
322 if (r < 0)
323 return r;
324
de40a303
LP
325 if (properties_message) {
326 r = sd_bus_message_copy(m, properties_message, true);
327 if (r < 0)
328 return bus_log_create_error(r);
329 }
330
cd2dfc6f
LP
331 r = append_machine_properties(
332 m,
333 mounts,
334 n_mounts,
411d8c72 335 kill_signal,
869c1cf8 336 start_mode == START_BOOT && can_set_coredump_receive(bus) > 0);
cd2dfc6f
LP
337 if (r < 0)
338 return r;
339
89ada3ba 340 r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
cd2dfc6f
LP
341 if (r < 0)
342 return r;
343
344 r = sd_bus_message_close_container(m);
345 if (r < 0)
346 return bus_log_create_error(r);
347
348 /* No auxiliary units */
349 r = sd_bus_message_append(
350 m,
351 "a(sa(sv))",
352 0);
353 if (r < 0)
354 return bus_log_create_error(r);
355
0a5706d1 356 r = sd_bus_call(bus, m, 0, &error, &reply);
7eda208f
LP
357 if (r < 0) {
358 /* If this failed with a property we couldn't write, this is quite likely because the server
359 * doesn't support PIDFDs yet, let's try without. */
360 if (allow_pidfd &&
361 sd_bus_error_has_names(&error, SD_BUS_ERROR_UNKNOWN_PROPERTY, SD_BUS_ERROR_PROPERTY_READ_ONLY))
411d8c72 362 return allocate_scope(bus, machine_name, pid, slice, mounts, n_mounts, kill_signal, properties, properties_message, /* allow_pidfd= */ false, start_mode);
7eda208f 363
4ae25393 364 return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r));
7eda208f 365 }
cd2dfc6f 366
0a5706d1
ZJS
367 r = sd_bus_message_read(reply, "o", &object);
368 if (r < 0)
369 return bus_log_parse_error(r);
370
e22ad53d 371 r = bus_wait_for_jobs_one(w, object, BUS_WAIT_JOBS_LOG_ERROR, NULL);
0a5706d1
ZJS
372 if (r < 0)
373 return r;
374
cd2dfc6f
LP
375 return 0;
376}
1d78fea2
LP
377
378int terminate_scope(
379 sd_bus *bus,
380 const char *machine_name) {
381
382 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
383 _cleanup_free_ char *scope = NULL;
384 int r;
385
df7c4eb6 386 r = unit_name_mangle_with_suffix(machine_name, "to terminate", 0, ".scope", &scope);
1d78fea2
LP
387 if (r < 0)
388 return log_error_errno(r, "Failed to mangle scope name: %m");
389
1ecaac5c 390 r = bus_call_method(bus, bus_systemd_mgr, "AbandonScope", &error, NULL, "s", scope);
1d78fea2
LP
391 if (r < 0) {
392 log_debug_errno(r, "Failed to abandon scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
393 sd_bus_error_free(&error);
394 }
395
1ecaac5c 396 r = bus_call_method(
1d78fea2 397 bus,
1ecaac5c 398 bus_systemd_mgr,
1d78fea2
LP
399 "KillUnit",
400 &error,
401 NULL,
402 "ssi",
403 scope,
404 "all",
405 (int32_t) SIGKILL);
406 if (r < 0) {
407 log_debug_errno(r, "Failed to SIGKILL scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
408 sd_bus_error_free(&error);
409 }
410
1ecaac5c 411 r = bus_call_method(bus, bus_systemd_mgr, "UnrefUnit", &error, NULL, "s", scope);
1d78fea2
LP
412 if (r < 0)
413 log_debug_errno(r, "Failed to drop reference to scope '%s', ignoring: %s", scope, bus_error_message(&error, r));
414
415 return 0;
416}