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