]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
unit: split off KillContext from ExecContext containing only kill definitions
[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
33 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
34 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
35
36 int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
37 char **env_files = data, **j;
38 DBusMessageIter sub, sub2;
39
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
68 int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
69 ExecContext *c = data;
70 int32_t n;
71
72 assert(i);
73 assert(property);
74 assert(c);
75
76 if (c->oom_score_adjust_set)
77 n = c->oom_score_adjust;
78 else {
79 char *t;
80
81 n = 0;
82 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
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
94 int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
95 ExecContext *c = data;
96 int32_t n;
97
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
113 int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
114 ExecContext *c = data;
115 int32_t n;
116
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
132 int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
133 ExecContext *c = data;
134 int32_t n;
135
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
151 int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
152 ExecContext *c = data;
153 int32_t n;
154
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
176 int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
177 ExecContext *c = data;
178 dbus_bool_t b;
179 DBusMessageIter sub;
180
181 assert(i);
182 assert(property);
183 assert(c);
184
185 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
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
202 int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
203 ExecContext *c = data;
204 uint64_t u;
205
206 assert(i);
207 assert(property);
208 assert(c);
209
210 if (c->timer_slack_nsec != (nsec_t) -1)
211 u = (uint64_t) c->timer_slack_nsec;
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
221 int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
222 ExecContext *c = data;
223 uint64_t normal, inverted;
224
225 assert(i);
226 assert(property);
227 assert(c);
228
229 /* We store this negated internally, to match the kernel, but
230 * we expose it normalized. */
231
232 normal = *(uint64_t*) data;
233 inverted = ~normal;
234
235 return bus_property_append_uint64(i, property, &inverted);
236 }
237
238 int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
239 ExecContext *c = data;
240 char *t = NULL;
241 const char *s;
242 dbus_bool_t b;
243
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
253 if (!s)
254 return -ENOMEM;
255
256 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
257
258 if (t)
259 cap_free(t);
260
261 if (!b)
262 return -ENOMEM;
263
264 return 0;
265 }
266
267 int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
268 ExecContext *c = data;
269 int r;
270 uint64_t u;
271
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 }
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 };