]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/nspawn/nspawn-register.c
nspawn: merge two variable declaration lines
[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
11d81e50
LP
204int terminate_machine(
205 sd_bus *bus,
206 const char *machine_name) {
207
4afd3348 208 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
b7103bc5
LP
209 int r;
210
abdb9b08 211 assert(bus);
b7103bc5
LP
212
213 r = sd_bus_call_method(
214 bus,
215 "org.freedesktop.machine1",
216 "/org/freedesktop/machine1",
217 "org.freedesktop.machine1.Manager",
11d81e50 218 "TerminateMachine",
b7103bc5
LP
219 &error,
220 NULL,
11d81e50
LP
221 "s",
222 machine_name);
4ae25393 223 if (r < 0)
b7103bc5 224 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
b7103bc5
LP
225
226 return 0;
227}
cd2dfc6f
LP
228
229int allocate_scope(
abdb9b08 230 sd_bus *bus,
cd2dfc6f
LP
231 const char *machine_name,
232 pid_t pid,
233 const char *slice,
234 CustomMount *mounts,
235 unsigned n_mounts,
236 int kill_signal,
237 char **properties) {
238
df61bc5e 239 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
cd2dfc6f 240 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
0a5706d1 241 _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
cd2dfc6f 242 _cleanup_free_ char *scope = NULL;
0a5706d1 243 const char *description, *object;
cd2dfc6f
LP
244 int r;
245
abdb9b08 246 assert(bus);
cd2dfc6f 247
0a5706d1
ZJS
248 r = bus_wait_for_jobs_new(bus, &w);
249 if (r < 0)
250 return log_error_errno(r, "Could not watch job: %m");
251
37cbc1d5 252 r = unit_name_mangle_with_suffix(machine_name, 0, ".scope", &scope);
cd2dfc6f
LP
253 if (r < 0)
254 return log_error_errno(r, "Failed to mangle scope name: %m");
255
256 r = sd_bus_message_new_method_call(
257 bus,
258 &m,
259 "org.freedesktop.systemd1",
260 "/org/freedesktop/systemd1",
261 "org.freedesktop.systemd1.Manager",
262 "StartTransientUnit");
263 if (r < 0)
264 return bus_log_create_error(r);
265
266 r = sd_bus_message_append(m, "ss", scope, "fail");
267 if (r < 0)
268 return bus_log_create_error(r);
269
270 /* Properties */
271 r = sd_bus_message_open_container(m, 'a', "(sv)");
272 if (r < 0)
273 return bus_log_create_error(r);
274
275 description = strjoina("Container ", machine_name);
276
277 r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)",
278 "PIDs", "au", 1, pid,
279 "Description", "s", description,
280 "Delegate", "b", 1,
910384c8 281 "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
cd2dfc6f
LP
282 if (r < 0)
283 return bus_log_create_error(r);
284
abdb9b08
LP
285 r = append_controller_property(bus, m);
286 if (r < 0)
287 return r;
288
cd2dfc6f
LP
289 r = append_machine_properties(
290 m,
291 mounts,
292 n_mounts,
2f14e52f 293 kill_signal);
cd2dfc6f
LP
294 if (r < 0)
295 return r;
296
89ada3ba 297 r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
cd2dfc6f
LP
298 if (r < 0)
299 return r;
300
301 r = sd_bus_message_close_container(m);
302 if (r < 0)
303 return bus_log_create_error(r);
304
305 /* No auxiliary units */
306 r = sd_bus_message_append(
307 m,
308 "a(sa(sv))",
309 0);
310 if (r < 0)
311 return bus_log_create_error(r);
312
0a5706d1 313 r = sd_bus_call(bus, m, 0, &error, &reply);
4ae25393
YW
314 if (r < 0)
315 return log_error_errno(r, "Failed to allocate scope: %s", bus_error_message(&error, r));
cd2dfc6f 316
0a5706d1
ZJS
317 r = sd_bus_message_read(reply, "o", &object);
318 if (r < 0)
319 return bus_log_parse_error(r);
320
321 r = bus_wait_for_jobs_one(w, object, false);
322 if (r < 0)
323 return r;
324
cd2dfc6f
LP
325 return 0;
326}