Coverage Report

Created: 2019-06-19 13:33

/src/systemd/src/core/dbus-scope.c
Line
Count
Source (jump to first uncovered line)
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
0
        int r;
20
0
21
0
        assert(message);
22
0
        assert(s);
23
0
24
0
        r = mac_selinux_unit_access_check(UNIT(s), message, "stop", error);
25
0
        if (r < 0)
26
0
                return r;
27
0
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
0
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
0
40
0
        return sd_bus_reply_method_return(message, NULL);
41
0
}
42
43
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
static int bus_scope_set_transient_property(
56
                Scope *s,
57
                const char *name,
58
                sd_bus_message *message,
59
                UnitWriteFlags flags,
60
0
                sd_bus_error *error) {
61
0
62
0
        int r;
63
0
64
0
        assert(s);
65
0
        assert(name);
66
0
        assert(message);
67
0
68
0
        flags |= UNIT_PRIVATE;
69
0
70
0
        if (streq(name, "TimeoutStopUSec"))
71
0
                return bus_set_transient_usec(UNIT(s), name, &s->timeout_stop_usec, message, flags, error);
72
0
73
0
        if (streq(name, "PIDs")) {
74
0
                _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
75
0
                unsigned n = 0;
76
0
77
0
                r = sd_bus_message_enter_container(message, 'a', "u");
78
0
                if (r < 0)
79
0
                        return r;
80
0
81
0
                for (;;) {
82
0
                        uint32_t upid;
83
0
                        pid_t pid;
84
0
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
0
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
0
                                }
97
0
98
0
                                r = sd_bus_creds_get_pid(creds, &pid);
99
0
                                if (r < 0)
100
0
                                        return r;
101
0
                        } else
102
0
                                pid = (uid_t) upid;
103
0
104
0
                        r = unit_pid_attachable(UNIT(s), pid, error);
105
0
                        if (r < 0)
106
0
                                return r;
107
0
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
0
                        }
113
0
114
0
                        n++;
115
0
                }
116
0
117
0
                r = sd_bus_message_exit_container(message);
118
0
                if (r < 0)
119
0
                        return r;
120
0
121
0
                if (n <= 0)
122
0
                        return -EINVAL;
123
0
124
0
                return 1;
125
0
126
0
        } else if (streq(name, "Controller")) {
127
0
                const char *controller;
128
0
129
0
                /* We can't support direct connections with this, as direct connections know no service or unique name
130
0
                 * 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
0
134
0
                r = sd_bus_message_read(message, "s", &controller);
135
0
                if (r < 0)
136
0
                        return r;
137
0
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
0
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
0
                }
146
0
147
0
                return 1;
148
0
        }
149
0
150
0
        return 0;
151
0
}
152
153
int bus_scope_set_property(
154
                Unit *u,
155
                const char *name,
156
                sd_bus_message *message,
157
                UnitWriteFlags flags,
158
0
                sd_bus_error *error) {
159
0
160
0
        Scope *s = SCOPE(u);
161
0
        int r;
162
0
163
0
        assert(s);
164
0
        assert(name);
165
0
        assert(message);
166
0
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
0
171
0
        if (u->load_state == UNIT_STUB) {
172
0
                /* While we are created we still accept PIDs */
173
0
174
0
                r = bus_scope_set_transient_property(s, name, message, flags, error);
175
0
                if (r != 0)
176
0
                        return r;
177
0
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
0
        }
182
0
183
0
        return 0;
184
0
}
185
186
0
int bus_scope_commit_properties(Unit *u) {
187
0
        assert(u);
188
0
189
0
        unit_invalidate_cgroup_members_masks(u);
190
0
        unit_realize_cgroup(u);
191
0
192
0
        return 0;
193
0
}
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
0
        int r;
199
0
200
0
        assert(s);
201
0
202
0
        if (!s->controller)
203
0
                return 0;
204
0
205
0
        p = unit_dbus_path(UNIT(s));
206
0
        if (!p)
207
0
                return -ENOMEM;
208
0
209
0
        r = sd_bus_message_new_signal(
210
0
                        UNIT(s)->manager->api_bus,
211
0
                        &m,
212
0
                        p,
213
0
                        "org.freedesktop.systemd1.Scope",
214
0
                        "RequestStop");
215
0
        if (r < 0)
216
0
                return r;
217
0
218
0
        return sd_bus_send_to(UNIT(s)->manager->api_bus, m, s->controller, NULL);
219
0
}
220
221
0
static int on_controller_gone(sd_bus_track *track, void *userdata) {
222
0
        Scope *s = userdata;
223
0
224
0
        assert(track);
225
0
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
0
        }
231
0
232
0
        s->controller_track = sd_bus_track_unref(s->controller_track);
233
0
234
0
        return 0;
235
0
}
236
237
0
int bus_scope_track_controller(Scope *s) {
238
0
        int r;
239
0
240
0
        assert(s);
241
0
242
0
        if (!s->controller || s->controller_track)
243
0
                return 0;
244
0
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
0
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
0
        }
254
0
255
0
        return 0;
256
0
}