1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
22 #include <sys/prctl.h>
28 #include "syscall-list.h"
31 #include "dbus-execute.h"
32 #include "capability.h"
35 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
37 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
39 static int property_get_environment_files(
42 const char *interface,
44 sd_bus_message *reply,
46 sd_bus_error *error) {
48 ExecContext *c = userdata;
56 r = sd_bus_message_open_container(reply, 'a', "(sb)");
60 STRV_FOREACH(j, c->environment_files) {
63 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
68 return sd_bus_message_close_container(reply);
71 static int property_get_rlimit(
74 const char *interface,
76 sd_bus_message *reply,
78 sd_bus_error *error) {
87 rl = *(struct rlimit**) userdata;
89 u = (uint64_t) rl->rlim_max;
91 struct rlimit buf = {};
94 z = rlimit_from_string(property);
99 u = (uint64_t) buf.rlim_max;
102 return sd_bus_message_append(reply, "t", u);
105 static int property_get_oom_score_adjust(
108 const char *interface,
109 const char *property,
110 sd_bus_message *reply,
112 sd_bus_error *error) {
115 ExecContext *c = userdata;
122 if (c->oom_score_adjust_set)
123 n = c->oom_score_adjust;
125 _cleanup_free_ char *t = NULL;
128 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
132 return sd_bus_message_append(reply, "i", n);
135 static int property_get_nice(
138 const char *interface,
139 const char *property,
140 sd_bus_message *reply,
142 sd_bus_error *error) {
145 ExecContext *c = userdata;
156 n = getpriority(PRIO_PROCESS, 0);
161 return sd_bus_message_append(reply, "i", n);
164 static int property_get_ioprio(
167 const char *interface,
168 const char *property,
169 sd_bus_message *reply,
171 sd_bus_error *error) {
174 ExecContext *c = userdata;
184 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
186 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
189 return sd_bus_message_append(reply, "i", n);
192 static int property_get_cpu_sched_policy(
195 const char *interface,
196 const char *property,
197 sd_bus_message *reply,
199 sd_bus_error *error) {
201 ExecContext *c = userdata;
208 if (c->cpu_sched_set)
209 n = c->cpu_sched_policy;
211 n = sched_getscheduler(0);
216 return sd_bus_message_append(reply, "i", n);
219 static int property_get_cpu_sched_priority(
222 const char *interface,
223 const char *property,
224 sd_bus_message *reply,
226 sd_bus_error *error) {
228 ExecContext *c = userdata;
235 if (c->cpu_sched_set)
236 n = c->cpu_sched_priority;
238 struct sched_param p = {};
240 if (sched_getparam(0, &p) >= 0)
241 n = p.sched_priority;
246 return sd_bus_message_append(reply, "i", n);
249 static int property_get_cpu_affinity(
252 const char *interface,
253 const char *property,
254 sd_bus_message *reply,
256 sd_bus_error *error) {
258 ExecContext *c = userdata;
265 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
267 return sd_bus_message_append_array(reply, 'y', NULL, 0);
270 static int property_get_timer_slack_nsec(
273 const char *interface,
274 const char *property,
275 sd_bus_message *reply,
277 sd_bus_error *error) {
279 ExecContext *c = userdata;
286 if (c->timer_slack_nsec != (nsec_t) -1)
287 u = (uint64_t) c->timer_slack_nsec;
289 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
291 return sd_bus_message_append(reply, "t", u);
294 static int property_get_capability_bounding_set(
297 const char *interface,
298 const char *property,
299 sd_bus_message *reply,
301 sd_bus_error *error) {
303 ExecContext *c = userdata;
309 /* We store this negated internally, to match the kernel, but
310 * we expose it normalized. */
311 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
314 static int property_get_capabilities(
317 const char *interface,
318 const char *property,
319 sd_bus_message *reply,
321 sd_bus_error *error) {
323 ExecContext *c = userdata;
324 _cleanup_cap_free_charp_ char *t = NULL;
332 s = t = cap_to_text(c->capabilities, NULL);
339 return sd_bus_message_append(reply, "s", s);
342 static int property_get_syscall_filter(
345 const char *interface,
346 const char *property,
347 sd_bus_message *reply,
349 sd_bus_error *error) {
351 ExecContext *c = userdata;
357 if (c->syscall_filter)
358 return sd_bus_message_append_array(reply, 'u', c->syscall_filter, (syscall_max() + 31) >> 4);
360 return sd_bus_message_append_array(reply, 'u', NULL, 0);
363 const sd_bus_vtable bus_exec_vtable[] = {
364 SD_BUS_VTABLE_START(0),
365 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
366 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
367 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
368 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
369 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
370 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
371 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
372 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
373 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
374 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
375 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
376 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
377 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
378 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
379 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
380 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
381 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
382 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
383 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
384 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
385 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
386 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
387 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
388 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
389 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
390 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
391 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
392 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
393 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
394 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
395 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
396 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
397 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
398 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
399 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
400 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
401 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
402 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
403 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
404 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
405 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
406 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
407 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
408 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
409 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
410 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
411 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
412 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
413 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
414 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
415 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
416 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
417 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
418 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
419 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
420 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
421 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
422 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
423 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
424 SD_BUS_PROPERTY("SystemCallFilter", "au", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
428 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
437 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
441 r = sd_bus_message_append(reply, "s", c->path);
445 r = sd_bus_message_append_strv(reply, c->argv);
449 r = sd_bus_message_append(reply, "bttttuii",
451 c->exec_status.start_timestamp.realtime,
452 c->exec_status.start_timestamp.monotonic,
453 c->exec_status.exit_timestamp.realtime,
454 c->exec_status.exit_timestamp.monotonic,
455 (uint32_t) c->exec_status.pid,
456 (int32_t) c->exec_status.code,
457 (int32_t) c->exec_status.status);
461 return sd_bus_message_close_container(reply);
464 int bus_property_get_exec_command(
467 const char *interface,
468 const char *property,
469 sd_bus_message *reply,
471 sd_bus_error *ret_error) {
473 ExecCommand *c = (ExecCommand*) userdata;
479 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
483 r = append_exec_command(reply, c);
487 return sd_bus_message_close_container(reply);
490 int bus_property_get_exec_command_list(
493 const char *interface,
494 const char *property,
495 sd_bus_message *reply,
497 sd_bus_error *ret_error) {
499 ExecCommand *c = *(ExecCommand**) userdata;
505 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
509 LIST_FOREACH(command, c, c) {
510 r = append_exec_command(reply, c);
515 return sd_bus_message_close_container(reply);
518 int bus_exec_context_set_transient_property(
522 sd_bus_message *message,
523 UnitSetPropertiesMode mode,
524 sd_bus_error *error) {
533 if (streq(name, "User")) {
536 r = sd_bus_message_read(message, "s", &uu);
540 if (mode != UNIT_CHECK) {
556 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
561 } else if (streq(name, "Group")) {
564 r = sd_bus_message_read(message, "s", &gg);
568 if (mode != UNIT_CHECK) {
584 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
589 } else if (streq(name, "Nice")) {
592 r = sd_bus_message_read(message, "i", &n);
596 if (n < PRIO_MIN || n >= PRIO_MAX)
597 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
599 if (mode != UNIT_CHECK) {
601 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
606 } else if (streq(name, "Environment")) {
608 _cleanup_strv_free_ char **l = NULL;
610 r = sd_bus_message_read_strv(message, &l);
614 if (!strv_env_is_valid(l))
615 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
617 if (mode != UNIT_CHECK) {
618 _cleanup_free_ char *joined = NULL;
621 e = strv_env_merge(2, c->environment, l);
625 strv_free(c->environment);
628 joined = strv_join(c->environment, " ");
632 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);