1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2015 Lennart Poettering
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.
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.
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/>.
23 #include "bus-error.h"
24 #include "bus-unit-util.h"
26 #include "nspawn-register.h"
27 #include "stat-util.h"
31 static int append_machine_properties(
43 r
= sd_bus_message_append(m
, "(sv)", "DevicePolicy", "s", "closed");
45 return bus_log_create_error(r
);
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
56 "/dev/net/tun", "rwm",
57 /* Allow the container
58 * access to ptys. However,
60 * container to ever create
61 * these device nodes. */
64 return bus_log_create_error(r
);
66 for (j
= 0; j
< n_mounts
; j
++) {
67 CustomMount
*cm
= mounts
+ j
;
69 if (cm
->type
!= CUSTOM_MOUNT_BIND
)
72 r
= is_device_node(cm
->source
);
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
);
79 return log_error_errno(r
, "Failed to stat %s: %m", cm
->source
);
82 r
= sd_bus_message_append(m
, "(sv)", "DeviceAllow", "a(ss)", 1,
83 cm
->source
, cm
->read_only
? "r" : "rw");
85 return log_error_errno(r
, "Failed to append message arguments: %m");
89 if (kill_signal
!= 0) {
90 r
= sd_bus_message_append(m
, "(sv)", "KillSignal", "i", kill_signal
);
92 return bus_log_create_error(r
);
94 r
= sd_bus_message_append(m
, "(sv)", "KillMode", "s", "mixed");
96 return bus_log_create_error(r
);
102 int register_machine(
103 const char *machine_name
,
105 const char *directory
,
114 const char *service
) {
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
;
120 r
= sd_bus_default_system(&bus
);
122 return log_error_errno(r
, "Failed to open system bus: %m");
125 r
= sd_bus_call_method(
127 "org.freedesktop.machine1",
128 "/org/freedesktop/machine1",
129 "org.freedesktop.machine1.Manager",
130 "RegisterMachineWithNetwork",
135 SD_BUS_MESSAGE_APPEND_ID128(uuid
),
140 local_ifindex
> 0 ? 1 : 0, local_ifindex
);
142 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*m
= NULL
;
144 r
= sd_bus_message_new_method_call(
147 "org.freedesktop.machine1",
148 "/org/freedesktop/machine1",
149 "org.freedesktop.machine1.Manager",
150 "CreateMachineWithNetwork");
152 return bus_log_create_error(r
);
154 r
= sd_bus_message_append(
158 SD_BUS_MESSAGE_APPEND_ID128(uuid
),
163 local_ifindex
> 0 ? 1 : 0, local_ifindex
);
165 return bus_log_create_error(r
);
167 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
169 return bus_log_create_error(r
);
171 if (!isempty(slice
)) {
172 r
= sd_bus_message_append(m
, "(sv)", "Slice", "s", slice
);
174 return bus_log_create_error(r
);
177 r
= append_machine_properties(
186 r
= bus_append_unit_property_assignment_many(m
, properties
);
190 r
= sd_bus_message_close_container(m
);
192 return bus_log_create_error(r
);
194 r
= sd_bus_call(bus
, m
, 0, &error
, NULL
);
198 log_error("Failed to register machine: %s", bus_error_message(&error
, r
));
205 int terminate_machine(pid_t pid
) {
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
;
212 r
= sd_bus_default_system(&bus
);
214 return log_error_errno(r
, "Failed to open system bus: %m");
216 r
= sd_bus_call_method(
218 "org.freedesktop.machine1",
219 "/org/freedesktop/machine1",
220 "org.freedesktop.machine1.Manager",
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
));
234 r
= sd_bus_message_read(reply
, "o", &path
);
236 return bus_log_parse_error(r
);
238 r
= sd_bus_call_method(
240 "org.freedesktop.machine1",
242 "org.freedesktop.machine1.Machine",
248 log_debug("Failed to terminate machine: %s", bus_error_message(&error
, r
));
256 const char *machine_name
,
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
;
267 _cleanup_(sd_bus_message_unrefp
) sd_bus_message
*reply
= NULL
;
268 _cleanup_(bus_wait_for_jobs_freep
) BusWaitForJobs
*w
= NULL
;
269 _cleanup_free_
char *scope
= NULL
;
270 const char *description
, *object
;
273 r
= sd_bus_default_system(&bus
);
275 return log_error_errno(r
, "Failed to open system bus: %m");
277 r
= bus_wait_for_jobs_new(bus
, &w
);
279 return log_error_errno(r
, "Could not watch job: %m");
281 r
= unit_name_mangle_with_suffix(machine_name
, UNIT_NAME_NOGLOB
, ".scope", &scope
);
283 return log_error_errno(r
, "Failed to mangle scope name: %m");
285 r
= sd_bus_message_new_method_call(
288 "org.freedesktop.systemd1",
289 "/org/freedesktop/systemd1",
290 "org.freedesktop.systemd1.Manager",
291 "StartTransientUnit");
293 return bus_log_create_error(r
);
295 r
= sd_bus_message_append(m
, "ss", scope
, "fail");
297 return bus_log_create_error(r
);
300 r
= sd_bus_message_open_container(m
, 'a', "(sv)");
302 return bus_log_create_error(r
);
304 description
= strjoina("Container ", machine_name
);
306 r
= sd_bus_message_append(m
, "(sv)(sv)(sv)(sv)",
307 "PIDs", "au", 1, pid
,
308 "Description", "s", description
,
310 "Slice", "s", isempty(slice
) ? "machine.slice" : slice
);
312 return bus_log_create_error(r
);
314 r
= append_machine_properties(
323 r
= bus_append_unit_property_assignment_many(m
, properties
);
327 r
= sd_bus_message_close_container(m
);
329 return bus_log_create_error(r
);
331 /* No auxiliary units */
332 r
= sd_bus_message_append(
337 return bus_log_create_error(r
);
339 r
= sd_bus_call(bus
, m
, 0, &error
, &reply
);
341 log_error("Failed to allocate scope: %s", bus_error_message(&error
, r
));
345 r
= sd_bus_message_read(reply
, "o", &object
);
347 return bus_log_parse_error(r
);
349 r
= bus_wait_for_jobs_one(w
, object
, false);