]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/nspawn/nspawn-register.c
Merge pull request #1695 from evverx/fix-cap-bounding-merging
[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
44 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
45 _cleanup_bus_flush_close_unref_ 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 "nspawn",
65 "container",
66 (uint32_t) pid,
67 strempty(directory),
68 local_ifindex > 0 ? 1 : 0, local_ifindex);
69 } else {
70 _cleanup_bus_message_unref_ 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 "nspawn",
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)", 9,
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 if (r < 0)
137 return bus_log_create_error(r);
138
139 for (j = 0; j < n_mounts; j++) {
140 CustomMount *cm = mounts + j;
141
142 if (cm->type != CUSTOM_MOUNT_BIND)
143 continue;
144
145 r = is_device_node(cm->source);
146 if (r < 0)
147 return log_error_errno(r, "Failed to stat %s: %m", cm->source);
148
149 if (r) {
150 r = sd_bus_message_append(m, "(sv)", "DeviceAllow", "a(ss)", 1,
151 cm->source, cm->read_only ? "r" : "rw");
152 if (r < 0)
153 return log_error_errno(r, "Failed to append message arguments: %m");
154 }
155 }
156
157 if (kill_signal != 0) {
158 r = sd_bus_message_append(m, "(sv)", "KillSignal", "i", kill_signal);
159 if (r < 0)
160 return bus_log_create_error(r);
161
162 r = sd_bus_message_append(m, "(sv)", "KillMode", "s", "mixed");
163 if (r < 0)
164 return bus_log_create_error(r);
165 }
166
167 STRV_FOREACH(i, properties) {
168 r = sd_bus_message_open_container(m, 'r', "sv");
169 if (r < 0)
170 return bus_log_create_error(r);
171
172 r = bus_append_unit_property_assignment(m, *i);
173 if (r < 0)
174 return r;
175
176 r = sd_bus_message_close_container(m);
177 if (r < 0)
178 return bus_log_create_error(r);
179 }
180
181 r = sd_bus_message_close_container(m);
182 if (r < 0)
183 return bus_log_create_error(r);
184
185 r = sd_bus_call(bus, m, 0, &error, NULL);
186 }
187
188 if (r < 0) {
189 log_error("Failed to register machine: %s", bus_error_message(&error, r));
190 return r;
191 }
192
193 return 0;
194 }
195
196 int terminate_machine(pid_t pid) {
197 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
198 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
199 _cleanup_bus_flush_close_unref_ sd_bus *bus = NULL;
200 const char *path;
201 int r;
202
203 r = sd_bus_default_system(&bus);
204 if (r < 0)
205 return log_error_errno(r, "Failed to open system bus: %m");
206
207 r = sd_bus_call_method(
208 bus,
209 "org.freedesktop.machine1",
210 "/org/freedesktop/machine1",
211 "org.freedesktop.machine1.Manager",
212 "GetMachineByPID",
213 &error,
214 &reply,
215 "u",
216 (uint32_t) pid);
217 if (r < 0) {
218 /* Note that the machine might already have been
219 * cleaned up automatically, hence don't consider it a
220 * failure if we cannot get the machine object. */
221 log_debug("Failed to get machine: %s", bus_error_message(&error, r));
222 return 0;
223 }
224
225 r = sd_bus_message_read(reply, "o", &path);
226 if (r < 0)
227 return bus_log_parse_error(r);
228
229 r = sd_bus_call_method(
230 bus,
231 "org.freedesktop.machine1",
232 path,
233 "org.freedesktop.machine1.Machine",
234 "Terminate",
235 &error,
236 NULL,
237 NULL);
238 if (r < 0) {
239 log_debug("Failed to terminate machine: %s", bus_error_message(&error, r));
240 return 0;
241 }
242
243 return 0;
244 }