]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
Use initalization instead of explicit zeroing
[thirdparty/systemd.git] / src / core / dbus-execute.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23 #include <dbus/dbus.h>
24 #include <sys/prctl.h>
25
26 #include "dbus-execute.h"
27 #include "missing.h"
28 #include "ioprio.h"
29 #include "strv.h"
30 #include "dbus-common.h"
31 #include "syscall-list.h"
32 #include "fileio.h"
33
34 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
35 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
36
37 int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
38 char **env_files = data, **j;
39 DBusMessageIter sub, sub2;
40
41 assert(i);
42 assert(property);
43
44 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
45 return -ENOMEM;
46
47 STRV_FOREACH(j, env_files) {
48 dbus_bool_t b = false;
49 char *fn = *j;
50
51 if (fn[0] == '-') {
52 b = true;
53 fn++;
54 }
55
56 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
57 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
58 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
59 !dbus_message_iter_close_container(&sub, &sub2))
60 return -ENOMEM;
61 }
62
63 if (!dbus_message_iter_close_container(i, &sub))
64 return -ENOMEM;
65
66 return 0;
67 }
68
69 int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
70 ExecContext *c = data;
71 int32_t n;
72
73 assert(i);
74 assert(property);
75 assert(c);
76
77 if (c->oom_score_adjust_set)
78 n = c->oom_score_adjust;
79 else {
80 char *t;
81
82 n = 0;
83 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
84 safe_atoi(t, &n);
85 free(t);
86 }
87 }
88
89 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
90 return -ENOMEM;
91
92 return 0;
93 }
94
95 int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
96 ExecContext *c = data;
97 int32_t n;
98
99 assert(i);
100 assert(property);
101 assert(c);
102
103 if (c->nice_set)
104 n = c->nice;
105 else
106 n = getpriority(PRIO_PROCESS, 0);
107
108 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
109 return -ENOMEM;
110
111 return 0;
112 }
113
114 int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
115 ExecContext *c = data;
116 int32_t n;
117
118 assert(i);
119 assert(property);
120 assert(c);
121
122 if (c->ioprio_set)
123 n = c->ioprio;
124 else
125 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
126
127 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
128 return -ENOMEM;
129
130 return 0;
131 }
132
133 int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
134 ExecContext *c = data;
135 int32_t n;
136
137 assert(i);
138 assert(property);
139 assert(c);
140
141 if (c->cpu_sched_set)
142 n = c->cpu_sched_policy;
143 else
144 n = sched_getscheduler(0);
145
146 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
147 return -ENOMEM;
148
149 return 0;
150 }
151
152 int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
153 ExecContext *c = data;
154 int32_t n;
155
156 assert(i);
157 assert(property);
158 assert(c);
159
160 if (c->cpu_sched_set)
161 n = c->cpu_sched_priority;
162 else {
163 struct sched_param p = {};
164
165 if (sched_getparam(0, &p) >= 0)
166 n = p.sched_priority;
167 else
168 n = 0;
169 }
170
171 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
172 return -ENOMEM;
173
174 return 0;
175 }
176
177 int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
178 ExecContext *c = data;
179 dbus_bool_t b;
180 DBusMessageIter sub;
181
182 assert(i);
183 assert(property);
184 assert(c);
185
186 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
187 return -ENOMEM;
188
189 if (c->cpuset)
190 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
191 else
192 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
193
194 if (!b)
195 return -ENOMEM;
196
197 if (!dbus_message_iter_close_container(i, &sub))
198 return -ENOMEM;
199
200 return 0;
201 }
202
203 int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
204 ExecContext *c = data;
205 uint64_t u;
206
207 assert(i);
208 assert(property);
209 assert(c);
210
211 if (c->timer_slack_nsec != (nsec_t) -1)
212 u = (uint64_t) c->timer_slack_nsec;
213 else
214 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
215
216 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
217 return -ENOMEM;
218
219 return 0;
220 }
221
222 int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
223 ExecContext *c = data;
224 uint64_t normal, inverted;
225
226 assert(i);
227 assert(property);
228 assert(c);
229
230 /* We store this negated internally, to match the kernel, but
231 * we expose it normalized. */
232
233 normal = *(uint64_t*) data;
234 inverted = ~normal;
235
236 return bus_property_append_uint64(i, property, &inverted);
237 }
238
239 int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
240 ExecContext *c = data;
241 char *t = NULL;
242 const char *s;
243 dbus_bool_t b;
244
245 assert(i);
246 assert(property);
247 assert(c);
248
249 if (c->capabilities)
250 s = t = cap_to_text(c->capabilities, NULL);
251 else
252 s = "";
253
254 if (!s)
255 return -ENOMEM;
256
257 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
258
259 if (t)
260 cap_free(t);
261
262 if (!b)
263 return -ENOMEM;
264
265 return 0;
266 }
267
268 int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
269 ExecContext *c = data;
270 int r;
271 uint64_t u;
272
273 assert(i);
274 assert(property);
275 assert(c);
276
277 assert_se((r = rlimit_from_string(property)) >= 0);
278
279 if (c->rlimit[r])
280 u = (uint64_t) c->rlimit[r]->rlim_max;
281 else {
282 struct rlimit rl = {};
283
284 getrlimit(r, &rl);
285
286 u = (uint64_t) rl.rlim_max;
287 }
288
289 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
290 return -ENOMEM;
291
292 return 0;
293 }
294
295 int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
296 ExecCommand *c = data;
297 DBusMessageIter sub, sub2, sub3;
298
299 assert(i);
300 assert(property);
301
302 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
303 return -ENOMEM;
304
305 LIST_FOREACH(command, c, c) {
306 char **l;
307 uint32_t pid;
308 int32_t code, status;
309 dbus_bool_t b;
310
311 if (!c->path)
312 continue;
313
314 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
315 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
316 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
317 return -ENOMEM;
318
319 STRV_FOREACH(l, c->argv)
320 if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
321 return -ENOMEM;
322
323 pid = (uint32_t) c->exec_status.pid;
324 code = (int32_t) c->exec_status.code;
325 status = (int32_t) c->exec_status.status;
326
327 b = !!c->ignore;
328
329 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
330 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
331 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
332 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
333 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
334 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
335 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
336 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
337 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
338 return -ENOMEM;
339
340 if (!dbus_message_iter_close_container(&sub, &sub2))
341 return -ENOMEM;
342 }
343
344 if (!dbus_message_iter_close_container(i, &sub))
345 return -ENOMEM;
346
347 return 0;
348 }
349
350 int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
351 ExecContext *c = data;
352 dbus_bool_t b;
353 DBusMessageIter sub;
354
355 assert(i);
356 assert(property);
357 assert(c);
358
359 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "u", &sub))
360 return -ENOMEM;
361
362 if (c->syscall_filter)
363 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, (syscall_max() + 31) >> 4);
364 else
365 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, 0);
366
367 if (!b)
368 return -ENOMEM;
369
370 if (!dbus_message_iter_close_container(i, &sub))
371 return -ENOMEM;
372
373 return 0;
374 }
375
376 const BusProperty bus_exec_context_properties[] = {
377 { "Environment", bus_property_append_strv, "as", offsetof(ExecContext, environment), true },
378 { "EnvironmentFiles", bus_execute_append_env_files, "a(sb)", offsetof(ExecContext, environment_files), true },
379 { "UMask", bus_property_append_mode, "u", offsetof(ExecContext, umask) },
380 { "LimitCPU", bus_execute_append_rlimits, "t", 0 },
381 { "LimitFSIZE", bus_execute_append_rlimits, "t", 0 },
382 { "LimitDATA", bus_execute_append_rlimits, "t", 0 },
383 { "LimitSTACK", bus_execute_append_rlimits, "t", 0 },
384 { "LimitCORE", bus_execute_append_rlimits, "t", 0 },
385 { "LimitRSS", bus_execute_append_rlimits, "t", 0 },
386 { "LimitNOFILE", bus_execute_append_rlimits, "t", 0 },
387 { "LimitAS", bus_execute_append_rlimits, "t", 0 },
388 { "LimitNPROC", bus_execute_append_rlimits, "t", 0 },
389 { "LimitMEMLOCK", bus_execute_append_rlimits, "t", 0 },
390 { "LimitLOCKS", bus_execute_append_rlimits, "t", 0 },
391 { "LimitSIGPENDING", bus_execute_append_rlimits, "t", 0 },
392 { "LimitMSGQUEUE", bus_execute_append_rlimits, "t", 0 },
393 { "LimitNICE", bus_execute_append_rlimits, "t", 0 },
394 { "LimitRTPRIO", bus_execute_append_rlimits, "t", 0 },
395 { "LimitRTTIME", bus_execute_append_rlimits, "t", 0 },
396 { "WorkingDirectory", bus_property_append_string, "s", offsetof(ExecContext, working_directory), true },
397 { "RootDirectory", bus_property_append_string, "s", offsetof(ExecContext, root_directory), true },
398 { "OOMScoreAdjust", bus_execute_append_oom_score_adjust, "i", 0 },
399 { "Nice", bus_execute_append_nice, "i", 0 },
400 { "IOScheduling", bus_execute_append_ioprio, "i", 0 },
401 { "CPUSchedulingPolicy", bus_execute_append_cpu_sched_policy, "i", 0 },
402 { "CPUSchedulingPriority", bus_execute_append_cpu_sched_priority, "i", 0 },
403 { "CPUAffinity", bus_execute_append_affinity, "ay", 0 },
404 { "TimerSlackNSec", bus_execute_append_timer_slack_nsec, "t", 0 },
405 { "CPUSchedulingResetOnFork", bus_property_append_bool, "b", offsetof(ExecContext, cpu_sched_reset_on_fork) },
406 { "NonBlocking", bus_property_append_bool, "b", offsetof(ExecContext, non_blocking) },
407 { "StandardInput", bus_execute_append_input, "s", offsetof(ExecContext, std_input) },
408 { "StandardOutput", bus_execute_append_output, "s", offsetof(ExecContext, std_output) },
409 { "StandardError", bus_execute_append_output, "s", offsetof(ExecContext, std_error) },
410 { "TTYPath", bus_property_append_string, "s", offsetof(ExecContext, tty_path), true },
411 { "TTYReset", bus_property_append_bool, "b", offsetof(ExecContext, tty_reset) },
412 { "TTYVHangup", bus_property_append_bool, "b", offsetof(ExecContext, tty_vhangup) },
413 { "TTYVTDisallocate", bus_property_append_bool, "b", offsetof(ExecContext, tty_vt_disallocate) },
414 { "SyslogPriority", bus_property_append_int, "i", offsetof(ExecContext, syslog_priority) },
415 { "SyslogIdentifier", bus_property_append_string, "s", offsetof(ExecContext, syslog_identifier), true },
416 { "SyslogLevelPrefix", bus_property_append_bool, "b", offsetof(ExecContext, syslog_level_prefix) },
417 { "Capabilities", bus_execute_append_capabilities, "s", 0 },
418 { "SecureBits", bus_property_append_int, "i", offsetof(ExecContext, secure_bits) },
419 { "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", offsetof(ExecContext, capability_bounding_set_drop) },
420 { "User", bus_property_append_string, "s", offsetof(ExecContext, user), true },
421 { "Group", bus_property_append_string, "s", offsetof(ExecContext, group), true },
422 { "SupplementaryGroups", bus_property_append_strv, "as", offsetof(ExecContext, supplementary_groups), true },
423 { "TCPWrapName", bus_property_append_string, "s", offsetof(ExecContext, tcpwrap_name), true },
424 { "PAMName", bus_property_append_string, "s", offsetof(ExecContext, pam_name), true },
425 { "ReadWriteDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_write_dirs), true },
426 { "ReadOnlyDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_only_dirs), true },
427 { "InaccessibleDirectories", bus_property_append_strv, "as", offsetof(ExecContext, inaccessible_dirs), true },
428 { "MountFlags", bus_property_append_ul, "t", offsetof(ExecContext, mount_flags) },
429 { "PrivateTmp", bus_property_append_bool, "b", offsetof(ExecContext, private_tmp) },
430 { "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
431 { "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
432 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
433 { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
434 { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
435 { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe) },
436 { "NoNewPrivileges", bus_property_append_bool, "b", offsetof(ExecContext, no_new_privileges) },
437 { "SystemCallFilter", bus_execute_append_syscall_filter, "au", 0 },
438 { NULL, }
439 };