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