]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/nspawn/nspawn-register.c
nspawn: support custom container service name
[thirdparty/systemd.git] / src / nspawn / nspawn-register.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2015 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include "sd-bus.h"
23
24 #include "bus-error.h"
25 #include "bus-util.h"
26 #include "nspawn-register.h"
27 #include "stat-util.h"
28 #include "strv.h"
29 #include "util.h"
30
31 int register_machine(
32 const char *machine_name,
33 pid_t pid,
34 const char *directory,
35 sd_id128_t uuid,
36 int local_ifindex,
37 const char *slice,
38 CustomMount *mounts,
39 unsigned n_mounts,
40 int kill_signal,
41 char **properties,
42 bool keep_unit,
43 const char *service) {
44
45 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
46 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
47 int r;
48
49 r = sd_bus_default_system(&bus);
50 if (r < 0)
51 return log_error_errno(r, "Failed to open system bus: %m");
52
53 if (keep_unit) {
54 r = sd_bus_call_method(
55 bus,
56 "org.freedesktop.machine1",
57 "/org/freedesktop/machine1",
58 "org.freedesktop.machine1.Manager",
59 "RegisterMachineWithNetwork",
60 &error,
61 NULL,
62 "sayssusai",
63 machine_name,
64 SD_BUS_MESSAGE_APPEND_ID128(uuid),
65 service,
66 "container",
67 (uint32_t) pid,
68 strempty(directory),
69 local_ifindex > 0 ? 1 : 0, local_ifindex);
70 } else {
71 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
72 char **i;
73 unsigned j;
74
75 r = sd_bus_message_new_method_call(
76 bus,
77 &m,
78 "org.freedesktop.machine1",
79 "/org/freedesktop/machine1",
80 "org.freedesktop.machine1.Manager",
81 "CreateMachineWithNetwork");
82 if (r < 0)
83 return bus_log_create_error(r);
84
85 r = sd_bus_message_append(
86 m,
87 "sayssusai",
88 machine_name,
89 SD_BUS_MESSAGE_APPEND_ID128(uuid),
90 service,
91 "container",
92 (uint32_t) pid,
93 strempty(directory),
94 local_ifindex > 0 ? 1 : 0, local_ifindex);
95 if (r < 0)
96 return bus_log_create_error(r);
97
98 r = sd_bus_message_open_container(m, 'a', "(sv)");
99 if (r < 0)
100 return bus_log_create_error(r);
101
102 if (!isempty(slice)) {
103 r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
104 if (r < 0)
105 return bus_log_create_error(r);
106 }
107
108 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
109 if (r < 0)
110 return bus_log_create_error(r);
111
112 /* If you make changes here, also make sure to update
113 * systemd-nspawn@.service, to keep the device
114 * policies in sync regardless if we are run with or
115 * without the --keep-unit switch. */
116 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
117 /* Allow the container to
118 * access and create the API
119 * device nodes, so that
120 * PrivateDevices= in the
121 * container can work
122 * fine */
123 "/dev/null", "rwm",
124 "/dev/zero", "rwm",
125 "/dev/full", "rwm",
126 "/dev/random", "rwm",
127 "/dev/urandom", "rwm",
128 "/dev/tty", "rwm",
129 "/dev/net/tun", "rwm",
130 /* Allow the container
131 * access to ptys. However,
132 * do not permit the
133 * container to ever create
134 * these device nodes. */
135 "/dev/pts/ptmx", "rw",
136 "char-pts", "rw");
137 if (r < 0)
138 return bus_log_create_error(r);
139
140 for (j = 0; j < n_mounts; j++) {
141 CustomMount *cm = mounts + j;
142
143 if (cm->type != CUSTOM_MOUNT_BIND)
144 continue;
145
146 r = is_device_node(cm->source);
147 if (r < 0)
148 return log_error_errno(r, "Failed to stat %s: %m", cm->source);
149
150 if (r) {
151 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
152 cm->source, cm->read_only ? "r" : "rw");
153 if (r < 0)
154 return log_error_errno(r, "Failed to append message arguments: %m");
155 }
156 }
157
158 if (kill_signal != 0) {
159 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
160 if (r < 0)
161 return bus_log_create_error(r);
162
163 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
164 if (r < 0)
165 return bus_log_create_error(r);
166 }
167
168 STRV_FOREACH(i, properties) {
169 r = sd_bus_message_open_container(m, 'r', "sv");
170 if (r < 0)
171 return bus_log_create_error(r);
172
173 r = bus_append_unit_property_assignment(m, *i);
174 if (r < 0)
175 return r;
176
177 r = sd_bus_message_close_container(m);
178 if (r < 0)
179 return bus_log_create_error(r);
180 }
181
182 r = sd_bus_message_close_container(m);
183 if (r < 0)
184 return bus_log_create_error(r);
185
186 r = sd_bus_call(bus, m, 0, &error, NULL);
187 }
188
189 if (r < 0) {
190 log_error("Failed to register machine: %s", bus_error_message(&error, r));
191 return r;
192 }
193
194 return 0;
195 }
196
197 int terminate_machine(pid_t pid) {
198 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
199 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
200 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
201 const char *path;
202 int r;
203
204 r = sd_bus_default_system(&bus);
205 if (r < 0)
206 return log_error_errno(r, "Failed to open system bus: %m");
207
208 r = sd_bus_call_method(
209 bus,
210 "org.freedesktop.machine1",
211 "/org/freedesktop/machine1",
212 "org.freedesktop.machine1.Manager",
213 "GetMachineByPID",
214 &error,
215 &reply,
216 "u",
217 (uint32_t) pid);
218 if (r < 0) {
219 /* Note that the machine might already have been
220 * cleaned up automatically, hence don't consider it a
221 * failure if we cannot get the machine object. */
222 log_debug("Failed to get machine: %s", bus_error_message(&error, r));
223 return 0;
224 }
225
226 r = sd_bus_message_read(reply, "o", &path);
227 if (r < 0)
228 return bus_log_parse_error(r);
229
230 r = sd_bus_call_method(
231 bus,
232 "org.freedesktop.machine1",
233 path,
234 "org.freedesktop.machine1.Machine",
235 "Terminate",
236 &error,
237 NULL,
238 NULL);
239 if (r < 0) {
240 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
241 return 0;
242 }
243
244 return 0;
245 }