]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-scope.c
core: in bus_init_system() make sure we setup the system bus even if we inherit the...
[thirdparty/systemd.git] / src / core / dbus-scope.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
6c12b52e
LP
2/***
3 This file is part of systemd.
4
5 Copyright 2013 Lennart Poettering
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
b5efdb8a 21#include "alloc-util.h"
96aad8d1 22#include "bus-common-errors.h"
b5efdb8a
LP
23#include "bus-internal.h"
24#include "bus-util.h"
1d22e906
LP
25#include "dbus-cgroup.h"
26#include "dbus-kill.h"
27#include "dbus-scope.h"
b5efdb8a 28#include "dbus-unit.h"
0fb0fffa 29#include "dbus-util.h"
b5efdb8a
LP
30#include "dbus.h"
31#include "scope.h"
32#include "selinux-access.h"
33#include "unit.h"
6c12b52e 34
19070062 35static int bus_scope_abandon(sd_bus_message *message, void *userdata, sd_bus_error *error) {
a911bb9a 36 Scope *s = userdata;
4e2f8d27 37 int r;
a911bb9a 38
a911bb9a
LP
39 assert(message);
40 assert(s);
41
1d22e906
LP
42 r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error);
43 if (r < 0)
44 return r;
45
46 r = bus_verify_manage_units_async(UNIT(s)->manager, message, error);
283868e1
SW
47 if (r < 0)
48 return r;
49 if (r == 0)
50 return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
51
4e2f8d27 52 r = scope_abandon(s);
4e2f8d27
LP
53 if (r == -ESTALE)
54 return sd_bus_error_setf(error, BUS_ERROR_SCOPE_NOT_RUNNING, "Scope %s is not running, cannot abandon.", UNIT(s)->id);
1d22e906
LP
55 if (r < 0)
56 return r;
4e2f8d27
LP
57
58 return sd_bus_reply_method_return(message, NULL);
a911bb9a
LP
59}
60
718db961 61static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, scope_result, ScopeResult);
6c12b52e 62
718db961
LP
63const sd_bus_vtable bus_scope_vtable[] = {
64 SD_BUS_VTABLE_START(0),
371c0b79 65 SD_BUS_PROPERTY("Controller", "s", NULL, offsetof(Scope, controller), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc 66 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Scope, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 67 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Scope, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
2d4a39e7 68 SD_BUS_SIGNAL("RequestStop", NULL, 0),
1d22e906 69 SD_BUS_METHOD("Abandon", NULL, NULL, bus_scope_abandon, SD_BUS_VTABLE_UNPRIVILEGED),
718db961
LP
70 SD_BUS_VTABLE_END
71};
6c12b52e 72
9f2e86af 73static int bus_scope_set_transient_property(
6c12b52e
LP
74 Scope *s,
75 const char *name,
718db961 76 sd_bus_message *message,
2e59b241 77 UnitWriteFlags flags,
718db961 78 sd_bus_error *error) {
6c12b52e
LP
79
80 int r;
81
6c12b52e 82 assert(s);
718db961
LP
83 assert(name);
84 assert(message);
6c12b52e 85
2e59b241
LP
86 flags |= UNIT_PRIVATE;
87
0fb0fffa
YW
88 if (streq(name, "TimeoutStopUSec"))
89 return bus_set_transient_usec(UNIT(s), name, &s->timeout_stop_usec, message, flags, error);
90
6c12b52e 91 if (streq(name, "PIDs")) {
294a90cc 92 unsigned n = 0;
718db961 93 uint32_t pid;
6c12b52e 94
718db961
LP
95 r = sd_bus_message_enter_container(message, 'a', "u");
96 if (r < 0)
97 return r;
6c12b52e 98
718db961 99 while ((r = sd_bus_message_read(message, "u", &pid)) > 0) {
6c12b52e
LP
100
101 if (pid <= 1)
102 return -EINVAL;
103
2e59b241 104 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
a911bb9a 105 r = unit_watch_pid(UNIT(s), pid);
adb3a45d
LP
106 if (r < 0 && r != -EEXIST)
107 return r;
108 }
6c12b52e 109
adb3a45d 110 n++;
6c12b52e 111 }
718db961
LP
112 if (r < 0)
113 return r;
114
115 r = sd_bus_message_exit_container(message);
116 if (r < 0)
117 return r;
6c12b52e 118
adb3a45d 119 if (n <= 0)
6c12b52e
LP
120 return -EINVAL;
121
122 return 1;
cc23f9f1 123
2d4a39e7
LP
124 } else if (streq(name, "Controller")) {
125 const char *controller;
2d4a39e7 126
f2c49c86
LP
127 /* We can't support direct connections with this, as direct connections know no service or unique name
128 * concept, but the Controller field stores exactly that. */
129 if (sd_bus_message_get_bus(message) != UNIT(s)->manager->api_bus)
130 return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "Sorry, Controller= logic only supported via the bus.");
131
2d4a39e7
LP
132 r = sd_bus_message_read(message, "s", &controller);
133 if (r < 0)
134 return r;
135
136 if (!isempty(controller) && !service_name_is_valid(controller))
137 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
138
2e59b241
LP
139 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
140 r = free_and_strdup(&s->controller, empty_to_null(controller));
141 if (r < 0)
142 return r;
2d4a39e7
LP
143 }
144
cc23f9f1 145 return 1;
6c12b52e
LP
146 }
147
148 return 0;
149}
150
151int bus_scope_set_property(
152 Unit *u,
153 const char *name,
718db961 154 sd_bus_message *message,
2e59b241 155 UnitWriteFlags flags,
718db961 156 sd_bus_error *error) {
6c12b52e
LP
157
158 Scope *s = SCOPE(u);
159 int r;
160
718db961 161 assert(s);
6c12b52e 162 assert(name);
718db961 163 assert(message);
6c12b52e 164
2e59b241 165 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
6c12b52e
LP
166 if (r != 0)
167 return r;
168
169 if (u->load_state == UNIT_STUB) {
170 /* While we are created we still accept PIDs */
171
2e59b241 172 r = bus_scope_set_transient_property(s, name, message, flags, error);
6c12b52e
LP
173 if (r != 0)
174 return r;
a6c0353b 175
2e59b241 176 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
a6c0353b
LP
177 if (r != 0)
178 return r;
6c12b52e
LP
179 }
180
181 return 0;
182}
183
184int bus_scope_commit_properties(Unit *u) {
185 assert(u);
186
bc432dc7 187 unit_update_cgroup_members_masks(u);
6c12b52e 188 unit_realize_cgroup(u);
bc432dc7 189
6c12b52e
LP
190 return 0;
191}
2d4a39e7
LP
192
193int bus_scope_send_request_stop(Scope *s) {
4afd3348 194 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
2d4a39e7
LP
195 _cleanup_free_ char *p = NULL;
196 int r;
197
198 assert(s);
199
200 if (!s->controller)
201 return 0;
202
203 p = unit_dbus_path(UNIT(s));
204 if (!p)
205 return -ENOMEM;
206
207 r = sd_bus_message_new_signal(
208 UNIT(s)->manager->api_bus,
151b9b96 209 &m,
2d4a39e7
LP
210 p,
211 "org.freedesktop.systemd1.Scope",
151b9b96 212 "RequestStop");
2d4a39e7
LP
213 if (r < 0)
214 return r;
215
f4b0fb23 216 return sd_bus_send_to(UNIT(s)->manager->api_bus, m, s->controller, NULL);
2d4a39e7 217}
371c0b79
LP
218
219static int on_controller_gone(sd_bus_track *track, void *userdata) {
220 Scope *s = userdata;
221
222 assert(track);
223
224 if (s->controller) {
225 log_unit_debug(UNIT(s), "Controller %s disappeared from bus.", s->controller);
226 unit_add_to_dbus_queue(UNIT(s));
227 s->controller = mfree(s->controller);
228 }
229
230 s->controller_track = sd_bus_track_unref(s->controller_track);
231
232 return 0;
233}
234
235int bus_scope_track_controller(Scope *s) {
236 int r;
237
238 assert(s);
239
240 if (!s->controller || s->controller_track)
241 return 0;
242
243 r = sd_bus_track_new(UNIT(s)->manager->api_bus, &s->controller_track, on_controller_gone, s);
244 if (r < 0)
245 return r;
246
247 r = sd_bus_track_add_name(s->controller_track, s->controller);
248 if (r < 0) {
249 s->controller_track = sd_bus_track_unref(s->controller_track);
250 return r;
251 }
252
253 return 0;
254}