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