]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/nspawn/nspawn-register.c
tree-wide: expose "p"-suffix unref calls in public APIs to make gcc cleanup easy
[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_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
46 _cleanup_(sd_bus_flush_close_unrefp) 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_(sd_bus_message_unrefp) 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)", "TasksMax", "t", 8192);
109 if (r < 0)
110 return bus_log_create_error(r);
111
112 r = sd_bus_message_append(m, "(sv)", "DevicePolicy", "s", "strict");
113 if (r < 0)
114 return bus_log_create_error(r);
115
116 /* If you make changes here, also make sure to update
117 * systemd-nspawn@.service, to keep the device
118 * policies in sync regardless if we are run with or
119 * without the --keep-unit switch. */
120 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 9,
121 /* Allow the container to
122 * access and create the API
123 * device nodes, so that
124 * PrivateDevices= in the
125 * container can work
126 * fine */
127 "/dev/null", "rwm",
128 "/dev/zero", "rwm",
129 "/dev/full", "rwm",
130 "/dev/random", "rwm",
131 "/dev/urandom", "rwm",
132 "/dev/tty", "rwm",
133 "/dev/net/tun", "rwm",
134 /* Allow the container
135 * access to ptys. However,
136 * do not permit the
137 * container to ever create
138 * these device nodes. */
139 "/dev/pts/ptmx", "rw",
140 "char-pts", "rw");
141 if (r < 0)
142 return bus_log_create_error(r);
143
144 for (j = 0; j < n_mounts; j++) {
145 CustomMount *cm = mounts + j;
146
147 if (cm->type != CUSTOM_MOUNT_BIND)
148 continue;
149
150 r = is_device_node(cm->source);
151 if (r < 0)
152 return log_error_errno(r, "Failed to stat %s: %m", cm->source);
153
154 if (r) {
155 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
156 cm->source, cm->read_only ? "r" : "rw");
157 if (r < 0)
158 return log_error_errno(r, "Failed to append message arguments: %m");
159 }
160 }
161
162 if (kill_signal != 0) {
163 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
164 if (r < 0)
165 return bus_log_create_error(r);
166
167 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
168 if (r < 0)
169 return bus_log_create_error(r);
170 }
171
172 STRV_FOREACH(i, properties) {
173 r = sd_bus_message_open_container(m, 'r', "sv");
174 if (r < 0)
175 return bus_log_create_error(r);
176
177 r = bus_append_unit_property_assignment(m, *i);
178 if (r < 0)
179 return r;
180
181 r = sd_bus_message_close_container(m);
182 if (r < 0)
183 return bus_log_create_error(r);
184 }
185
186 r = sd_bus_message_close_container(m);
187 if (r < 0)
188 return bus_log_create_error(r);
189
190 r = sd_bus_call(bus, m, 0, &error, NULL);
191 }
192
193 if (r < 0) {
194 log_error("Failed to register machine: %s", bus_error_message(&error, r));
195 return r;
196 }
197
198 return 0;
199 }
200
201 int terminate_machine(pid_t pid) {
202 _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
203 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
204 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
205 const char *path;
206 int r;
207
208 r = sd_bus_default_system(&bus);
209 if (r < 0)
210 return log_error_errno(r, "Failed to open system bus: %m");
211
212 r = sd_bus_call_method(
213 bus,
214 "org.freedesktop.machine1",
215 "/org/freedesktop/machine1",
216 "org.freedesktop.machine1.Manager",
217 "GetMachineByPID",
218 &error,
219 &reply,
220 "u",
221 (uint32_t) pid);
222 if (r < 0) {
223 /* Note that the machine might already have been
224 * cleaned up automatically, hence don't consider it a
225 * failure if we cannot get the machine object. */
226 log_debug("Failed to get machine: %s", bus_error_message(&error, r));
227 return 0;
228 }
229
230 r = sd_bus_message_read(reply, "o", &path);
231 if (r < 0)
232 return bus_log_parse_error(r);
233
234 r = sd_bus_call_method(
235 bus,
236 "org.freedesktop.machine1",
237 path,
238 "org.freedesktop.machine1.Machine",
239 "Terminate",
240 &error,
241 NULL,
242 NULL);
243 if (r < 0) {
244 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
245 return 0;
246 }
247
248 return 0;
249 }