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