]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-execute.c
bus: decorate the various object vtables with SD_BUS_VTABLE_PROPERTY_CONST where...
[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 <sys/prctl.h>
23
24 #include "bus-util.h"
25 #include "missing.h"
26 #include "ioprio.h"
27 #include "strv.h"
28 #include "syscall-list.h"
29 #include "fileio.h"
30 #include "execute.h"
31 #include "dbus-execute.h"
32
33 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
34
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
36
37 static int property_get_environment_files(
38 sd_bus *bus,
39 const char *path,
40 const char *interface,
41 const char *property,
42 sd_bus_message *reply,
43 void *userdata,
44 sd_bus_error *error) {
45
46 ExecContext *c = userdata;
47 char **j;
48 int r;
49
50 assert(bus);
51 assert(reply);
52 assert(c);
53
54 r = sd_bus_message_open_container(reply, 'a', "(sb)");
55 if (r < 0)
56 return r;
57
58 STRV_FOREACH(j, c->environment_files) {
59 const char *fn = *j;
60
61 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
62 if (r < 0)
63 return r;
64 }
65
66 return sd_bus_message_close_container(reply);
67 }
68
69 static int property_get_rlimit(
70 sd_bus *bus,
71 const char *path,
72 const char *interface,
73 const char *property,
74 sd_bus_message *reply,
75 void *userdata,
76 sd_bus_error *error) {
77
78 struct rlimit *rl;
79 uint64_t u;
80
81 assert(bus);
82 assert(reply);
83 assert(userdata);
84
85 rl = *(struct rlimit**) userdata;
86 if (rl)
87 u = (uint64_t) rl->rlim_max;
88 else {
89 struct rlimit buf = {};
90 int z;
91
92 z = rlimit_from_string(property);
93 assert(z >= 0);
94
95 getrlimit(z, &buf);
96
97 u = (uint64_t) buf.rlim_max;
98 }
99
100 return sd_bus_message_append(reply, "t", u);
101 }
102
103 static int property_get_oom_score_adjust(
104 sd_bus *bus,
105 const char *path,
106 const char *interface,
107 const char *property,
108 sd_bus_message *reply,
109 void *userdata,
110 sd_bus_error *error) {
111
112
113 ExecContext *c = userdata;
114 int32_t n;
115
116 assert(bus);
117 assert(reply);
118 assert(c);
119
120 if (c->oom_score_adjust_set)
121 n = c->oom_score_adjust;
122 else {
123 _cleanup_free_ char *t = NULL;
124
125 n = 0;
126 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
127 safe_atoi(t, &n);
128 }
129
130 return sd_bus_message_append(reply, "i", n);
131 }
132
133 static int property_get_nice(
134 sd_bus *bus,
135 const char *path,
136 const char *interface,
137 const char *property,
138 sd_bus_message *reply,
139 void *userdata,
140 sd_bus_error *error) {
141
142
143 ExecContext *c = userdata;
144 int32_t n;
145
146 assert(bus);
147 assert(reply);
148 assert(c);
149
150 if (c->nice_set)
151 n = c->nice;
152 else {
153 errno = 0;
154 n = getpriority(PRIO_PROCESS, 0);
155 if (errno != 0)
156 n = 0;
157 }
158
159 return sd_bus_message_append(reply, "i", n);
160 }
161
162 static int property_get_ioprio(
163 sd_bus *bus,
164 const char *path,
165 const char *interface,
166 const char *property,
167 sd_bus_message *reply,
168 void *userdata,
169 sd_bus_error *error) {
170
171
172 ExecContext *c = userdata;
173 int32_t n;
174
175 assert(bus);
176 assert(reply);
177 assert(c);
178
179 if (c->ioprio_set)
180 n = c->ioprio;
181 else {
182 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
183 if (n < 0)
184 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
185 }
186
187 return sd_bus_message_append(reply, "i", n);
188 }
189
190 static int property_get_cpu_sched_policy(
191 sd_bus *bus,
192 const char *path,
193 const char *interface,
194 const char *property,
195 sd_bus_message *reply,
196 void *userdata,
197 sd_bus_error *error) {
198
199 ExecContext *c = userdata;
200 int32_t n;
201
202 assert(bus);
203 assert(reply);
204 assert(c);
205
206 if (c->cpu_sched_set)
207 n = c->cpu_sched_policy;
208 else {
209 n = sched_getscheduler(0);
210 if (n < 0)
211 n = SCHED_OTHER;
212 }
213
214 return sd_bus_message_append(reply, "i", n);
215 }
216
217 static int property_get_cpu_sched_priority(
218 sd_bus *bus,
219 const char *path,
220 const char *interface,
221 const char *property,
222 sd_bus_message *reply,
223 void *userdata,
224 sd_bus_error *error) {
225
226 ExecContext *c = userdata;
227 int32_t n;
228
229 assert(bus);
230 assert(reply);
231 assert(c);
232
233 if (c->cpu_sched_set)
234 n = c->cpu_sched_priority;
235 else {
236 struct sched_param p = {};
237
238 if (sched_getparam(0, &p) >= 0)
239 n = p.sched_priority;
240 else
241 n = 0;
242 }
243
244 return sd_bus_message_append(reply, "i", n);
245 }
246
247 static int property_get_cpu_affinity(
248 sd_bus *bus,
249 const char *path,
250 const char *interface,
251 const char *property,
252 sd_bus_message *reply,
253 void *userdata,
254 sd_bus_error *error) {
255
256 ExecContext *c = userdata;
257
258 assert(bus);
259 assert(reply);
260 assert(c);
261
262 if (c->cpuset)
263 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
264 else
265 return sd_bus_message_append_array(reply, 'y', NULL, 0);
266 }
267
268 static int property_get_timer_slack_nsec(
269 sd_bus *bus,
270 const char *path,
271 const char *interface,
272 const char *property,
273 sd_bus_message *reply,
274 void *userdata,
275 sd_bus_error *error) {
276
277 ExecContext *c = userdata;
278 uint64_t u;
279
280 assert(bus);
281 assert(reply);
282 assert(c);
283
284 if (c->timer_slack_nsec != (nsec_t) -1)
285 u = (uint64_t) c->timer_slack_nsec;
286 else
287 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
288
289 return sd_bus_message_append(reply, "t", u);
290 }
291
292 static int property_get_capability_bounding_set(
293 sd_bus *bus,
294 const char *path,
295 const char *interface,
296 const char *property,
297 sd_bus_message *reply,
298 void *userdata,
299 sd_bus_error *error) {
300
301 ExecContext *c = userdata;
302
303 assert(bus);
304 assert(reply);
305 assert(c);
306
307 /* We store this negated internally, to match the kernel, but
308 * we expose it normalized. */
309 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
310 }
311
312 static int property_get_capabilities(
313 sd_bus *bus,
314 const char *path,
315 const char *interface,
316 const char *property,
317 sd_bus_message *reply,
318 void *userdata,
319 sd_bus_error *error) {
320
321 ExecContext *c = userdata;
322 char *t = NULL;
323 const char *s;
324 int r;
325
326 assert(bus);
327 assert(reply);
328 assert(c);
329
330 if (c->capabilities)
331 s = t = cap_to_text(c->capabilities, NULL);
332 else
333 s = "";
334
335 if (!s)
336 return -ENOMEM;
337
338 r = sd_bus_message_append(reply, "s", s);
339
340 if (t)
341 cap_free(t);
342
343 return r;
344 }
345
346 static int property_get_syscall_filter(
347 sd_bus *bus,
348 const char *path,
349 const char *interface,
350 const char *property,
351 sd_bus_message *reply,
352 void *userdata,
353 sd_bus_error *error) {
354
355 ExecContext *c = userdata;
356
357 assert(bus);
358 assert(reply);
359 assert(c);
360
361 if (c->syscall_filter)
362 return sd_bus_message_append_array(reply, 'u', c->syscall_filter, (syscall_max() + 31) >> 4);
363 else
364 return sd_bus_message_append_array(reply, 'u', NULL, 0);
365 }
366
367 const sd_bus_vtable bus_exec_vtable[] = {
368 SD_BUS_VTABLE_START(0),
369 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
370 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
371 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
372 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
373 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
374 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
375 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
376 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
377 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
378 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
379 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
380 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
381 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
382 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
383 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
384 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
385 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
386 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
387 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
388 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
389 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
390 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
391 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
392 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
393 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
394 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
395 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
396 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
397 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
398 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
399 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
400 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
401 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
402 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
403 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
404 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
405 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
406 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
407 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
408 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
409 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
410 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
411 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
412 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
413 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
414 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
415 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
416 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
417 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
418 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
419 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
420 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
421 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
422 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
423 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
424 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
425 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
426 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
427 SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
428 SD_BUS_VTABLE_END
429 };
430
431 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
432 int r;
433
434 assert(reply);
435 assert(c);
436
437 if (!c->path)
438 return 0;
439
440 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
441 if (r < 0)
442 return r;
443
444 r = sd_bus_message_append(reply, "s", c->path);
445 if (r < 0)
446 return r;
447
448 r = sd_bus_message_append_strv(reply, c->argv);
449 if (r < 0)
450 return r;
451
452 r = sd_bus_message_append(reply, "bttttuii",
453 c->ignore,
454 c->exec_status.start_timestamp.realtime,
455 c->exec_status.start_timestamp.monotonic,
456 c->exec_status.exit_timestamp.realtime,
457 c->exec_status.exit_timestamp.monotonic,
458 (uint32_t) c->exec_status.pid,
459 (int32_t) c->exec_status.code,
460 (int32_t) c->exec_status.status);
461 if (r < 0)
462 return r;
463
464 return sd_bus_message_close_container(reply);
465 }
466
467 int bus_property_get_exec_command(
468 sd_bus *bus,
469 const char *path,
470 const char *interface,
471 const char *property,
472 sd_bus_message *reply,
473 void *userdata,
474 sd_bus_error *ret_error) {
475
476 ExecCommand *c = (ExecCommand*) userdata;
477 int r;
478
479 assert(bus);
480 assert(reply);
481
482 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
483 if (r < 0)
484 return r;
485
486 r = append_exec_command(reply, c);
487 if (r < 0)
488 return r;
489
490 return sd_bus_message_close_container(reply);
491 }
492
493 int bus_property_get_exec_command_list(
494 sd_bus *bus,
495 const char *path,
496 const char *interface,
497 const char *property,
498 sd_bus_message *reply,
499 void *userdata,
500 sd_bus_error *ret_error) {
501
502 ExecCommand *c = *(ExecCommand**) userdata;
503 int r;
504
505 assert(bus);
506 assert(reply);
507
508 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
509 if (r < 0)
510 return r;
511
512 LIST_FOREACH(command, c, c) {
513 r = append_exec_command(reply, c);
514 if (r < 0)
515 return r;
516 }
517
518 return sd_bus_message_close_container(reply);
519 }