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