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