]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
udevadm: do not free node on success
[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
LP
33
34DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
35DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
82c121a4 36
bfebab7f 37int 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
bfebab7f 69int 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
bfebab7f 95int 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
bfebab7f 114int 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
bfebab7f 133int 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
bfebab7f 152int 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 {
163 struct sched_param p;
82c121a4
LP
164
165 zero(p);
166 if (sched_getparam(0, &p) >= 0)
167 n = p.sched_priority;
e62d8c39
ZJS
168 else
169 n = 0;
82c121a4
LP
170 }
171
172 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
173 return -ENOMEM;
174
175 return 0;
176}
177
bfebab7f 178int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
179 ExecContext *c = data;
180 dbus_bool_t b;
181 DBusMessageIter sub;
182
82c121a4
LP
183 assert(i);
184 assert(property);
185 assert(c);
186
fe68089d 187 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
82c121a4
LP
188 return -ENOMEM;
189
190 if (c->cpuset)
191 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
192 else
193 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
194
195 if (!b)
196 return -ENOMEM;
197
198 if (!dbus_message_iter_close_container(i, &sub))
199 return -ENOMEM;
200
201 return 0;
202}
203
bfebab7f 204int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
205 ExecContext *c = data;
206 uint64_t u;
207
82c121a4
LP
208 assert(i);
209 assert(property);
210 assert(c);
211
d88a251b 212 if (c->timer_slack_nsec != (nsec_t) -1)
03fae018 213 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
214 else
215 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
216
217 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
218 return -ENOMEM;
219
220 return 0;
221}
222
bfebab7f 223int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
260abb78
LP
224 ExecContext *c = data;
225 uint64_t normal, inverted;
226
260abb78
LP
227 assert(i);
228 assert(property);
229 assert(c);
230
7c3d67ef 231 /* We store this negated internally, to match the kernel, but
260abb78
LP
232 * we expose it normalized. */
233
234 normal = *(uint64_t*) data;
235 inverted = ~normal;
236
bfebab7f 237 return bus_property_append_uint64(i, property, &inverted);
260abb78
LP
238}
239
bfebab7f 240int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
241 ExecContext *c = data;
242 char *t = NULL;
243 const char *s;
244 dbus_bool_t b;
245
82c121a4
LP
246 assert(i);
247 assert(property);
248 assert(c);
249
250 if (c->capabilities)
251 s = t = cap_to_text(c->capabilities, NULL);
252 else
253 s = "";
254
674cdd19 255 if (!s)
82c121a4
LP
256 return -ENOMEM;
257
258 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
674cdd19
LP
259
260 if (t)
261 cap_free(t);
82c121a4
LP
262
263 if (!b)
264 return -ENOMEM;
265
266 return 0;
267}
268
bfebab7f 269int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
82c121a4
LP
270 ExecContext *c = data;
271 int r;
272 uint64_t u;
273
82c121a4
LP
274 assert(i);
275 assert(property);
276 assert(c);
277
278 assert_se((r = rlimit_from_string(property)) >= 0);
279
280 if (c->rlimit[r])
281 u = (uint64_t) c->rlimit[r]->rlim_max;
282 else {
283 struct rlimit rl;
284
285 zero(rl);
286 getrlimit(r, &rl);
287
288 u = (uint64_t) rl.rlim_max;
289 }
290
291 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
292 return -ENOMEM;
293
294 return 0;
295}
fe68089d 296
bfebab7f 297int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
fe68089d
LP
298 ExecCommand *c = data;
299 DBusMessageIter sub, sub2, sub3;
300
fe68089d
LP
301 assert(i);
302 assert(property);
303
7daa9e6e 304 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
fe68089d
LP
305 return -ENOMEM;
306
307 LIST_FOREACH(command, c, c) {
308 char **l;
309 uint32_t pid;
310 int32_t code, status;
7daa9e6e 311 dbus_bool_t b;
fe68089d
LP
312
313 if (!c->path)
314 continue;
315
316 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
317 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
318 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
319 return -ENOMEM;
320
321 STRV_FOREACH(l, c->argv)
322 if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
323 return -ENOMEM;
324
325 pid = (uint32_t) c->exec_status.pid;
326 code = (int32_t) c->exec_status.code;
327 status = (int32_t) c->exec_status.status;
328
7daa9e6e
LP
329 b = !!c->ignore;
330
fe68089d 331 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
7daa9e6e 332 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
fe68089d 333 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
b21a0ef8 334 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
fe68089d 335 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
b21a0ef8 336 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
e364ad06
LP
337 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
338 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
339 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
fe68089d
LP
340 return -ENOMEM;
341
342 if (!dbus_message_iter_close_container(&sub, &sub2))
343 return -ENOMEM;
344 }
345
346 if (!dbus_message_iter_close_container(i, &sub))
347 return -ENOMEM;
348
349 return 0;
350}
d200735e 351
8351ceae
LP
352int bus_execute_append_syscall_filter(DBusMessageIter *i, const char *property, void *data) {
353 ExecContext *c = data;
354 dbus_bool_t b;
355 DBusMessageIter sub;
356
357 assert(i);
358 assert(property);
359 assert(c);
360
361 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "u", &sub))
362 return -ENOMEM;
363
364 if (c->syscall_filter)
365 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, (syscall_max() + 31) >> 4);
366 else
367 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_UINT32, &c->syscall_filter, 0);
368
369 if (!b)
370 return -ENOMEM;
371
372 if (!dbus_message_iter_close_container(i, &sub))
373 return -ENOMEM;
374
375 return 0;
376}
377
d200735e
MS
378const BusProperty bus_exec_context_properties[] = {
379 { "Environment", bus_property_append_strv, "as", offsetof(ExecContext, environment), true },
380 { "EnvironmentFiles", bus_execute_append_env_files, "a(sb)", offsetof(ExecContext, environment_files), true },
381 { "UMask", bus_property_append_mode, "u", offsetof(ExecContext, umask) },
382 { "LimitCPU", bus_execute_append_rlimits, "t", 0 },
383 { "LimitFSIZE", bus_execute_append_rlimits, "t", 0 },
384 { "LimitDATA", bus_execute_append_rlimits, "t", 0 },
385 { "LimitSTACK", bus_execute_append_rlimits, "t", 0 },
386 { "LimitCORE", bus_execute_append_rlimits, "t", 0 },
387 { "LimitRSS", bus_execute_append_rlimits, "t", 0 },
388 { "LimitNOFILE", bus_execute_append_rlimits, "t", 0 },
389 { "LimitAS", bus_execute_append_rlimits, "t", 0 },
390 { "LimitNPROC", bus_execute_append_rlimits, "t", 0 },
391 { "LimitMEMLOCK", bus_execute_append_rlimits, "t", 0 },
392 { "LimitLOCKS", bus_execute_append_rlimits, "t", 0 },
393 { "LimitSIGPENDING", bus_execute_append_rlimits, "t", 0 },
394 { "LimitMSGQUEUE", bus_execute_append_rlimits, "t", 0 },
395 { "LimitNICE", bus_execute_append_rlimits, "t", 0 },
396 { "LimitRTPRIO", bus_execute_append_rlimits, "t", 0 },
397 { "LimitRTTIME", bus_execute_append_rlimits, "t", 0 },
398 { "WorkingDirectory", bus_property_append_string, "s", offsetof(ExecContext, working_directory), true },
399 { "RootDirectory", bus_property_append_string, "s", offsetof(ExecContext, root_directory), true },
400 { "OOMScoreAdjust", bus_execute_append_oom_score_adjust, "i", 0 },
401 { "Nice", bus_execute_append_nice, "i", 0 },
402 { "IOScheduling", bus_execute_append_ioprio, "i", 0 },
403 { "CPUSchedulingPolicy", bus_execute_append_cpu_sched_policy, "i", 0 },
404 { "CPUSchedulingPriority", bus_execute_append_cpu_sched_priority, "i", 0 },
405 { "CPUAffinity", bus_execute_append_affinity, "ay", 0 },
406 { "TimerSlackNSec", bus_execute_append_timer_slack_nsec, "t", 0 },
407 { "CPUSchedulingResetOnFork", bus_property_append_bool, "b", offsetof(ExecContext, cpu_sched_reset_on_fork) },
408 { "NonBlocking", bus_property_append_bool, "b", offsetof(ExecContext, non_blocking) },
409 { "StandardInput", bus_execute_append_input, "s", offsetof(ExecContext, std_input) },
410 { "StandardOutput", bus_execute_append_output, "s", offsetof(ExecContext, std_output) },
411 { "StandardError", bus_execute_append_output, "s", offsetof(ExecContext, std_error) },
412 { "TTYPath", bus_property_append_string, "s", offsetof(ExecContext, tty_path), true },
413 { "TTYReset", bus_property_append_bool, "b", offsetof(ExecContext, tty_reset) },
414 { "TTYVHangup", bus_property_append_bool, "b", offsetof(ExecContext, tty_vhangup) },
415 { "TTYVTDisallocate", bus_property_append_bool, "b", offsetof(ExecContext, tty_vt_disallocate) },
416 { "SyslogPriority", bus_property_append_int, "i", offsetof(ExecContext, syslog_priority) },
417 { "SyslogIdentifier", bus_property_append_string, "s", offsetof(ExecContext, syslog_identifier), true },
418 { "SyslogLevelPrefix", bus_property_append_bool, "b", offsetof(ExecContext, syslog_level_prefix) },
419 { "Capabilities", bus_execute_append_capabilities, "s", 0 },
420 { "SecureBits", bus_property_append_int, "i", offsetof(ExecContext, secure_bits) },
421 { "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", offsetof(ExecContext, capability_bounding_set_drop) },
422 { "User", bus_property_append_string, "s", offsetof(ExecContext, user), true },
423 { "Group", bus_property_append_string, "s", offsetof(ExecContext, group), true },
424 { "SupplementaryGroups", bus_property_append_strv, "as", offsetof(ExecContext, supplementary_groups), true },
425 { "TCPWrapName", bus_property_append_string, "s", offsetof(ExecContext, tcpwrap_name), true },
426 { "PAMName", bus_property_append_string, "s", offsetof(ExecContext, pam_name), true },
427 { "ReadWriteDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_write_dirs), true },
428 { "ReadOnlyDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_only_dirs), true },
429 { "InaccessibleDirectories", bus_property_append_strv, "as", offsetof(ExecContext, inaccessible_dirs), true },
430 { "MountFlags", bus_property_append_ul, "t", offsetof(ExecContext, mount_flags) },
431 { "PrivateTmp", bus_property_append_bool, "b", offsetof(ExecContext, private_tmp) },
432 { "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
433 { "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
d200735e
MS
434 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
435 { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
aa001cd6 436 { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
8351ceae
LP
437 { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe) },
438 { "NoNewPrivileges", bus_property_append_bool, "b", offsetof(ExecContext, no_new_privileges) },
439 { "SystemCallFilter", bus_execute_append_syscall_filter, "au", 0 },
d200735e
MS
440 { NULL, }
441};