]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-scope.c
networkd-test: stop varlink socket before setting up runtime directories
[thirdparty/systemd.git] / src / core / dbus-scope.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
6c12b52e 2
b5efdb8a 3#include "alloc-util.h"
96aad8d1 4#include "bus-common-errors.h"
40af3d02 5#include "bus-get-properties.h"
4ac08d8a 6#include "bus-util.h"
1d22e906
LP
7#include "dbus-cgroup.h"
8#include "dbus-kill.h"
5fa09835 9#include "dbus-manager.h"
1d22e906 10#include "dbus-scope.h"
0fb0fffa 11#include "dbus-util.h"
836e4e7e
DDM
12#include "manager.h"
13#include "pidref.h"
b5efdb8a
LP
14#include "scope.h"
15#include "selinux-access.h"
836e4e7e 16#include "string-util.h"
b5efdb8a 17#include "unit.h"
6c12b52e 18
c20076a8 19int bus_scope_method_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) {
99534007 20 Scope *s = ASSERT_PTR(userdata);
4e2f8d27 21 int r;
a911bb9a 22
a911bb9a 23 assert(message);
a911bb9a 24
1d22e906
LP
25 r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error);
26 if (r < 0)
27 return r;
28
29 r = bus_verify_manage_units_async(UNIT(s)->manager, message, error);
283868e1
SW
30 if (r < 0)
31 return r;
32 if (r == 0)
33 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
34
4e2f8d27 35 r = scope_abandon(s);
4e2f8d27
LP
36 if (r == -ESTALE)
37 return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id);
1d22e906
LP
38 if (r < 0)
39 return r;
4e2f8d27
LP
40
41 return sd_bus_reply_method_return(message, NULL);
a911bb9a
LP
42}
43
718db961 44static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
5fa09835 45static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
6c12b52e 46
718db961
LP
47const sd_bus_vtable bus_scope_vtable[] = {
48 SD_BUS_VTABLE_START(0),
371c0b79 49 SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc 50 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 51 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
9ed7de60 52 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Scope, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
5918a933 53 SD_BUS_PROPERTY("RuntimeRandomizedExtraUSec", "t", bus_property_get_usec, offsetof(Scope, runtime_rand_extra_usec), SD_BUS_VTABLE_PROPERTY_CONST),
5fa09835 54 SD_BUS_PROPERTY("OOMPolicy", "s", bus_property_get_oom_policy, offsetof(Scope, oom_policy), SD_BUS_VTABLE_PROPERTY_CONST),
2d4a39e7 55 SD_BUS_SIGNAL("RequestStop", NULL, 0),
c20076a8 56 SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_method_abandon, SD_BUS_VTABLE_UNPRIVILEGED),
718db961
LP
57 SD_BUS_VTABLE_END
58};
6c12b52e 59
9f2e86af 60static int bus_scope_set_transient_property(
6c12b52e
LP
61 Scope *s,
62 const char *name,
718db961 63 sd_bus_message *message,
2e59b241 64 UnitWriteFlags flags,
718db961 65 sd_bus_error *error) {
6c12b52e 66
ef71cc77 67 Unit *u = UNIT(s);
6c12b52e
LP
68 int r;
69
6c12b52e 70 assert(s);
718db961
LP
71 assert(name);
72 assert(message);
6c12b52e 73
2e59b241
LP
74 flags |= UNIT_PRIVATE;
75
0fb0fffa 76 if (streq(name, "TimeoutStopUSec"))
ef71cc77 77 return bus_set_transient_usec(u, name, &s->timeout_stop_usec, message, flags, error);
0fb0fffa 78
9ed7de60
PW
79 if (streq(name, "RuntimeMaxUSec"))
80 return bus_set_transient_usec(u, name, &s->runtime_max_usec, message, flags, error);
81
5918a933
AB
82 if (streq(name, "RuntimeRandomizedExtraUSec"))
83 return bus_set_transient_usec(u, name, &s->runtime_rand_extra_usec, message, flags, error);
84
5fa09835
ML
85 if (streq(name, "OOMPolicy"))
86 return bus_set_transient_oom_policy(u, name, &s->oom_policy, message, flags, error);
87
6c12b52e 88 if (streq(name, "PIDs")) {
4ac08d8a 89 _cleanup_(pidref_done) PidRef sender_pidref = PIDREF_NULL;
294a90cc 90 unsigned n = 0;
6c12b52e 91
718db961
LP
92 r = sd_bus_message_enter_container(message, 'a', "u");
93 if (r < 0)
94 return r;
6c12b52e 95
6592b975 96 for (;;) {
495e75ed 97 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
6592b975 98 uint32_t upid;
4ac08d8a 99 PidRef *p;
6592b975
LP
100
101 r = sd_bus_message_read(message, "u", &upid);
102 if (r < 0)
103 return r;
104 if (r == 0)
105 break;
106
107 if (upid == 0) {
4ac08d8a
LP
108 if (!pidref_is_set(&sender_pidref)) {
109 r = bus_query_sender_pidref(message, &sender_pidref);
6592b975
LP
110 if (r < 0)
111 return r;
112 }
113
4ac08d8a
LP
114 p = &sender_pidref;
115 } else {
116 r = pidref_set_pid(&pidref, upid);
6592b975
LP
117 if (r < 0)
118 return r;
6c12b52e 119
4ac08d8a
LP
120 p = &pidref;
121 }
495e75ed 122
4ac08d8a 123 r = unit_pid_attachable(u, p, error);
6592b975
LP
124 if (r < 0)
125 return r;
6c12b52e 126
2e59b241 127 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
4ac08d8a 128 r = unit_watch_pidref(u, p, /* exclusive= */ false);
66f83537 129 if (r < 0)
adb3a45d
LP
130 return r;
131 }
6c12b52e 132
adb3a45d 133 n++;
6c12b52e 134 }
718db961
LP
135
136 r = sd_bus_message_exit_container(message);
137 if (r < 0)
138 return r;
6c12b52e 139
7595fed9
LP
140 return n <= 0 ? -EINVAL : 1;
141 }
6c12b52e 142
7595fed9
LP
143 if (streq(name, "PIDFDs")) {
144 unsigned n = 0;
145
146 r = sd_bus_message_enter_container(message, 'a', "h");
147 if (r < 0)
148 return r;
149
150 for (;;) {
151 _cleanup_(pidref_done) PidRef pidref = PIDREF_NULL;
152 int fd;
153
154 r = sd_bus_message_read(message, "h", &fd);
155 if (r < 0)
156 return r;
157 if (r == 0)
158 break;
159
160 r = pidref_set_pidfd(&pidref, fd);
161 if (r < 0)
162 return r;
163
164 r = unit_pid_attachable(u, &pidref, error);
165 if (r < 0)
166 return r;
167
168 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
169 r = unit_watch_pidref(u, &pidref, /* exclusive= */ false);
66f83537 170 if (r < 0)
7595fed9
LP
171 return r;
172 }
173
174 n++;
175 }
176
177 r = sd_bus_message_exit_container(message);
178 if (r < 0)
179 return r;
180
181 return n <= 0 ? -EINVAL : 1;
182 }
cc23f9f1 183
7595fed9 184 if (streq(name, "Controller")) {
2d4a39e7 185 const char *controller;
2d4a39e7 186
f2c49c86
LP
187 /* We can't support direct connections with this, as direct connections know no service or unique name
188 * concept, but the Controller field stores exactly that. */
ef71cc77 189 if (sd_bus_message_get_bus(message) != u->manager->api_bus)
1b09b81c 190 return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus.");
f2c49c86 191
2d4a39e7
LP
192 r = sd_bus_message_read(message, "s", &controller);
193 if (r < 0)
194 return r;
195
5453a4b1 196 if (!isempty(controller) && !sd_bus_service_name_is_valid(controller))
2d4a39e7
LP
197 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
198
2e59b241
LP
199 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
200 r = free_and_strdup(&s->controller, empty_to_null(controller));
201 if (r < 0)
202 return r;
2d4a39e7
LP
203 }
204
cc23f9f1 205 return 1;
6c12b52e
LP
206 }
207
208 return 0;
209}
210
211int bus_scope_set_property(
212 Unit *u,
213 const char *name,
718db961 214 sd_bus_message *message,
2e59b241 215 UnitWriteFlags flags,
718db961 216 sd_bus_error *error) {
6c12b52e
LP
217
218 Scope *s = SCOPE(u);
219 int r;
220
718db961 221 assert(s);
6c12b52e 222 assert(name);
718db961 223 assert(message);
6c12b52e 224
2e59b241 225 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
6c12b52e
LP
226 if (r != 0)
227 return r;
228
229 if (u->load_state == UNIT_STUB) {
230 /* While we are created we still accept PIDs */
231
2e59b241 232 r = bus_scope_set_transient_property(s, name, message, flags, error);
6c12b52e
LP
233 if (r != 0)
234 return r;
a6c0353b 235
2e59b241 236 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
a6c0353b
LP
237 if (r != 0)
238 return r;
03860190
MS
239
240 if (streq(name, "User"))
241 return bus_set_transient_user_relaxed(u, name, &s->user, message, flags, error);
242
243 if (streq(name, "Group"))
244 return bus_set_transient_user_relaxed(u, name, &s->group, message, flags, error);
6c12b52e
LP
245 }
246
247 return 0;
248}
249
250int bus_scope_commit_properties(Unit *u) {
251 assert(u);
252
8d178f70 253 (void) unit_realize_cgroup(u);
bc432dc7 254
6c12b52e
LP
255 return 0;
256}
2d4a39e7
LP
257
258int bus_scope_send_request_stop(Scope *s) {
4afd3348 259 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2d4a39e7
LP
260 _cleanup_free_ char *p = NULL;
261 int r;
262
263 assert(s);
264
265 if (!s->controller)
266 return 0;
267
268 p = unit_dbus_path(UNIT(s));
269 if (!p)
270 return -ENOMEM;
271
272 r = sd_bus_message_new_signal(
273 UNIT(s)->manager->api_bus,
151b9b96 274 &m,
2d4a39e7
LP
275 p,
276 "org.freedesktop.systemd1.Scope",
151b9b96 277 "RequestStop");
2d4a39e7
LP
278 if (r < 0)
279 return r;
280
f4b0fb23 281 return sd_bus_send_to(UNIT(s)->manager->api_bus, m, s->controller, NULL);
2d4a39e7 282}
371c0b79
LP
283
284static int on_controller_gone(sd_bus_track *track, void *userdata) {
285 Scope *s = userdata;
286
287 assert(track);
288
289 if (s->controller) {
290 log_unit_debug(UNIT(s), "Controller %s disappeared from bus.", s->controller);
291 unit_add_to_dbus_queue(UNIT(s));
292 s->controller = mfree(s->controller);
293 }
294
295 s->controller_track = sd_bus_track_unref(s->controller_track);
296
297 return 0;
298}
299
300int bus_scope_track_controller(Scope *s) {
301 int r;
302
303 assert(s);
304
305 if (!s->controller || s->controller_track)
306 return 0;
307
308 r = sd_bus_track_new(UNIT(s)->manager->api_bus, &s->controller_track, on_controller_gone, s);
309 if (r < 0)
310 return r;
311
312 r = sd_bus_track_add_name(s->controller_track, s->controller);
313 if (r < 0) {
314 s->controller_track = sd_bus_track_unref(s->controller_track);
315 return r;
316 }
317
318 return 0;
319}