]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
service: introduce a proper service result if the start limit is hit
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4139c1b2
LP
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
5430f7f2
LP
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
4139c1b2
LP
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
5430f7f2 16 Lesser General Public License for more details.
4139c1b2 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <errno.h>
23#include <dbus/dbus.h>
82c121a4 24#include <sys/prctl.h>
4139c1b2
LP
25
26#include "dbus-execute.h"
82c121a4
LP
27#include "missing.h"
28#include "ioprio.h"
fe68089d 29#include "strv.h"
bfebab7f 30#include "dbus-common.h"
8351ceae 31#include "syscall-list.h"
4139c1b2
LP
32
33DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
34DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
82c121a4 35
bfebab7f 36int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
8c7be95e
LP
37 char **env_files = data, **j;
38 DBusMessageIter sub, sub2;
39
8c7be95e
LP
40 assert(i);
41 assert(property);
42
43 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
44 return -ENOMEM;
45
46 STRV_FOREACH(j, env_files) {
47 dbus_bool_t b = false;
48 char *fn = *j;
49
50 if (fn[0] == '-') {
51 b = true;
52 fn++;
53 }
54
55 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
56 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
57 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
58 !dbus_message_iter_close_container(&sub, &sub2))
59 return -ENOMEM;
60 }
61
62 if (!dbus_message_iter_close_container(i, &sub))
63 return -ENOMEM;
64
65 return 0;
66}
67
bfebab7f 68int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
69 ExecContext *c = data;
70 int32_t n;
71
82c121a4
LP
72 assert(i);
73 assert(property);
74 assert(c);
75
dd6c17b1
LP
76 if (c->oom_score_adjust_set)
77 n = c->oom_score_adjust;
82c121a4
LP
78 else {
79 char *t;
80
81 n = 0;
dd6c17b1 82 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
82c121a4
LP
83 safe_atoi(t, &n);
84 free(t);
85 }
86 }
87
88 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
89 return -ENOMEM;
90
91 return 0;
92}
93
bfebab7f 94int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
95 ExecContext *c = data;
96 int32_t n;
97
82c121a4
LP
98 assert(i);
99 assert(property);
100 assert(c);
101
102 if (c->nice_set)
103 n = c->nice;
104 else
105 n = getpriority(PRIO_PROCESS, 0);
106
107 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
108 return -ENOMEM;
109
110 return 0;
111}
112
bfebab7f 113int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
114 ExecContext *c = data;
115 int32_t n;
116
82c121a4
LP
117 assert(i);
118 assert(property);
119 assert(c);
120
121 if (c->ioprio_set)
122 n = c->ioprio;
123 else
124 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
125
126 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
127 return -ENOMEM;
128
129 return 0;
130}
131
bfebab7f 132int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
133 ExecContext *c = data;
134 int32_t n;
135
82c121a4
LP
136 assert(i);
137 assert(property);
138 assert(c);
139
140 if (c->cpu_sched_set)
141 n = c->cpu_sched_policy;
142 else
143 n = sched_getscheduler(0);
144
145 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
146 return -ENOMEM;
147
148 return 0;
149}
150
bfebab7f 151int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
152 ExecContext *c = data;
153 int32_t n;
154
82c121a4
LP
155 assert(i);
156 assert(property);
157 assert(c);
158
159 if (c->cpu_sched_set)
160 n = c->cpu_sched_priority;
161 else {
162 struct sched_param p;
163 n = 0;
164
165 zero(p);
166 if (sched_getparam(0, &p) >= 0)
167 n = p.sched_priority;
168 }
169
170 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
171 return -ENOMEM;
172
173 return 0;
174}
175
bfebab7f 176int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
177 ExecContext *c = data;
178 dbus_bool_t b;
179 DBusMessageIter sub;
180
82c121a4
LP
181 assert(i);
182 assert(property);
183 assert(c);
184
fe68089d 185 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
82c121a4
LP
186 return -ENOMEM;
187
188 if (c->cpuset)
189 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
190 else
191 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
192
193 if (!b)
194 return -ENOMEM;
195
196 if (!dbus_message_iter_close_container(i, &sub))
197 return -ENOMEM;
198
199 return 0;
200}
201
bfebab7f 202int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
203 ExecContext *c = data;
204 uint64_t u;
205
82c121a4
LP
206 assert(i);
207 assert(property);
208 assert(c);
209
d88a251b 210 if (c->timer_slack_nsec != (nsec_t) -1)
03fae018 211 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
212 else
213 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
214
215 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
216 return -ENOMEM;
217
218 return 0;
219}
220
bfebab7f 221int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
260abb78
LP
222 ExecContext *c = data;
223 uint64_t normal, inverted;
224
260abb78
LP
225 assert(i);
226 assert(property);
227 assert(c);
228
7c3d67ef 229 /* We store this negated internally, to match the kernel, but
260abb78
LP
230 * we expose it normalized. */
231
232 normal = *(uint64_t*) data;
233 inverted = ~normal;
234
bfebab7f 235 return bus_property_append_uint64(i, property, &inverted);
260abb78
LP
236}
237
bfebab7f 238int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
239 ExecContext *c = data;
240 char *t = NULL;
241 const char *s;
242 dbus_bool_t b;
243
82c121a4
LP
244 assert(i);
245 assert(property);
246 assert(c);
247
248 if (c->capabilities)
249 s = t = cap_to_text(c->capabilities, NULL);
250 else
251 s = "";
252
674cdd19 253 if (!s)
82c121a4
LP
254 return -ENOMEM;
255
256 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
674cdd19
LP
257
258 if (t)
259 cap_free(t);
82c121a4
LP
260
261 if (!b)
262 return -ENOMEM;
263
264 return 0;
265}
266
bfebab7f 267int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
268 ExecContext *c = data;
269 int r;
270 uint64_t u;
271
82c121a4
LP
272 assert(i);
273 assert(property);
274 assert(c);
275
276 assert_se((r = rlimit_from_string(property)) >= 0);
277
278 if (c->rlimit[r])
279 u = (uint64_t) c->rlimit[r]->rlim_max;
280 else {
281 struct rlimit rl;
282
283 zero(rl);
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}
fe68089d 294
bfebab7f 295int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
fe68089d
LP
296 ExecCommand *c = data;
297 DBusMessageIter sub, sub2, sub3;
298
fe68089d
LP
299 assert(i);
300 assert(property);
301
7daa9e6e 302 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
fe68089d
LP
303 return -ENOMEM;
304
305 LIST_FOREACH(command, c, c) {
306 char **l;
307 uint32_t pid;
308 int32_t code, status;
7daa9e6e 309 dbus_bool_t b;
fe68089d
LP
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
7daa9e6e
LP
327 b = !!c->ignore;
328
fe68089d 329 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
7daa9e6e 330 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
fe68089d 331 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
b21a0ef8 332 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
fe68089d 333 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
b21a0ef8 334 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
e364ad06
LP
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))
fe68089d
LP
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}
d200735e 349
8351ceae
LP
350int 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
d200735e
MS
376const 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) },
d200735e
MS
432 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
433 { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
aa001cd6 434 { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
8351ceae
LP
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 },
d200735e
MS
438 { NULL, }
439};