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