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