]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
hwdb: update
[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"
a5c32cff 32#include "fileio.h"
4139c1b2 33
4ad49000
LP
34static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
35static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
82c121a4 36
4ad49000 37static int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
8c7be95e
LP
38 char **env_files = data, **j;
39 DBusMessageIter sub, sub2;
40
8c7be95e
LP
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
4ad49000 69static int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
70 ExecContext *c = data;
71 int32_t n;
72
82c121a4
LP
73 assert(i);
74 assert(property);
75 assert(c);
76
dd6c17b1
LP
77 if (c->oom_score_adjust_set)
78 n = c->oom_score_adjust;
82c121a4
LP
79 else {
80 char *t;
81
82 n = 0;
dd6c17b1 83 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
82c121a4
LP
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
4ad49000 95static int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
96 ExecContext *c = data;
97 int32_t n;
98
82c121a4
LP
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
4ad49000 114static int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
115 ExecContext *c = data;
116 int32_t n;
117
82c121a4
LP
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
4ad49000 133static int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
134 ExecContext *c = data;
135 int32_t n;
136
82c121a4
LP
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
4ad49000 152static int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
153 ExecContext *c = data;
154 int32_t n;
155
82c121a4
LP
156 assert(i);
157 assert(property);
158 assert(c);
159
160 if (c->cpu_sched_set)
161 n = c->cpu_sched_priority;
162 else {
b92bea5d 163 struct sched_param p = {};
82c121a4 164
82c121a4
LP
165 if (sched_getparam(0, &p) >= 0)
166 n = p.sched_priority;
e62d8c39
ZJS
167 else
168 n = 0;
82c121a4
LP
169 }
170
171 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
172 return -ENOMEM;
173
174 return 0;
175}
176
4ad49000 177static int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
178 ExecContext *c = data;
179 dbus_bool_t b;
180 DBusMessageIter sub;
181
82c121a4
LP
182 assert(i);
183 assert(property);
184 assert(c);
185
fe68089d 186 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
82c121a4
LP
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
4ad49000 203static int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
204 ExecContext *c = data;
205 uint64_t u;
206
82c121a4
LP
207 assert(i);
208 assert(property);
209 assert(c);
210
d88a251b 211 if (c->timer_slack_nsec != (nsec_t) -1)
03fae018 212 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
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
4ad49000 222static int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
260abb78
LP
223 ExecContext *c = data;
224 uint64_t normal, inverted;
225
260abb78
LP
226 assert(i);
227 assert(property);
228 assert(c);
229
7c3d67ef 230 /* We store this negated internally, to match the kernel, but
260abb78
LP
231 * we expose it normalized. */
232
233 normal = *(uint64_t*) data;
234 inverted = ~normal;
235
bfebab7f 236 return bus_property_append_uint64(i, property, &inverted);
260abb78
LP
237}
238
4ad49000 239static int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
240 ExecContext *c = data;
241 char *t = NULL;
242 const char *s;
243 dbus_bool_t b;
244
82c121a4
LP
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
674cdd19 254 if (!s)
82c121a4
LP
255 return -ENOMEM;
256
257 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
674cdd19
LP
258
259 if (t)
260 cap_free(t);
82c121a4
LP
261
262 if (!b)
263 return -ENOMEM;
264
265 return 0;
266}
267
4ad49000 268static int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
269 ExecContext *c = data;
270 int r;
271 uint64_t u;
272
82c121a4
LP
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 {
b92bea5d 282 struct rlimit rl = {};
82c121a4 283
82c121a4
LP
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
4ad49000 350static int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
8351ceae
LP
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 432 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
8351ceae
LP
433 { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe) },
434 { "NoNewPrivileges", bus_property_append_bool, "b", offsetof(ExecContext, no_new_privileges) },
435 { "SystemCallFilter", bus_execute_append_syscall_filter, "au", 0 },
4ad49000 436 {}
d200735e 437};