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>
34 #include "dbus-execute.h"
35 #include "capability.h"
38 #include "namespace.h"
41 #include "seccomp-util.h"
44 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
46 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
48 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protected_home, protected_home, ProtectedHome);
50 static int property_get_environment_files(
53 const char *interface,
55 sd_bus_message *reply,
57 sd_bus_error *error) {
59 ExecContext *c = userdata;
67 r = sd_bus_message_open_container(reply, 'a', "(sb)");
71 STRV_FOREACH(j, c->environment_files) {
74 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
79 return sd_bus_message_close_container(reply);
82 static int property_get_rlimit(
85 const char *interface,
87 sd_bus_message *reply,
89 sd_bus_error *error) {
99 rl = *(struct rlimit**) userdata;
103 struct rlimit buf = {};
106 z = rlimit_from_string(property);
113 /* rlim_t might have different sizes, let's map
114 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
116 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
118 return sd_bus_message_append(reply, "t", u);
121 static int property_get_oom_score_adjust(
124 const char *interface,
125 const char *property,
126 sd_bus_message *reply,
128 sd_bus_error *error) {
131 ExecContext *c = userdata;
138 if (c->oom_score_adjust_set)
139 n = c->oom_score_adjust;
141 _cleanup_free_ char *t = NULL;
144 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
148 return sd_bus_message_append(reply, "i", n);
151 static int property_get_nice(
154 const char *interface,
155 const char *property,
156 sd_bus_message *reply,
158 sd_bus_error *error) {
161 ExecContext *c = userdata;
172 n = getpriority(PRIO_PROCESS, 0);
177 return sd_bus_message_append(reply, "i", n);
180 static int property_get_ioprio(
183 const char *interface,
184 const char *property,
185 sd_bus_message *reply,
187 sd_bus_error *error) {
190 ExecContext *c = userdata;
200 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
202 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
205 return sd_bus_message_append(reply, "i", n);
208 static int property_get_cpu_sched_policy(
211 const char *interface,
212 const char *property,
213 sd_bus_message *reply,
215 sd_bus_error *error) {
217 ExecContext *c = userdata;
224 if (c->cpu_sched_set)
225 n = c->cpu_sched_policy;
227 n = sched_getscheduler(0);
232 return sd_bus_message_append(reply, "i", n);
235 static int property_get_cpu_sched_priority(
238 const char *interface,
239 const char *property,
240 sd_bus_message *reply,
242 sd_bus_error *error) {
244 ExecContext *c = userdata;
251 if (c->cpu_sched_set)
252 n = c->cpu_sched_priority;
254 struct sched_param p = {};
256 if (sched_getparam(0, &p) >= 0)
257 n = p.sched_priority;
262 return sd_bus_message_append(reply, "i", n);
265 static int property_get_cpu_affinity(
268 const char *interface,
269 const char *property,
270 sd_bus_message *reply,
272 sd_bus_error *error) {
274 ExecContext *c = userdata;
281 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
283 return sd_bus_message_append_array(reply, 'y', NULL, 0);
286 static int property_get_timer_slack_nsec(
289 const char *interface,
290 const char *property,
291 sd_bus_message *reply,
293 sd_bus_error *error) {
295 ExecContext *c = userdata;
302 if (c->timer_slack_nsec != (nsec_t) -1)
303 u = (uint64_t) c->timer_slack_nsec;
305 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
307 return sd_bus_message_append(reply, "t", u);
310 static int property_get_capability_bounding_set(
313 const char *interface,
314 const char *property,
315 sd_bus_message *reply,
317 sd_bus_error *error) {
319 ExecContext *c = userdata;
325 /* We store this negated internally, to match the kernel, but
326 * we expose it normalized. */
327 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
330 static int property_get_capabilities(
333 const char *interface,
334 const char *property,
335 sd_bus_message *reply,
337 sd_bus_error *error) {
339 ExecContext *c = userdata;
340 _cleanup_cap_free_charp_ char *t = NULL;
348 s = t = cap_to_text(c->capabilities, NULL);
355 return sd_bus_message_append(reply, "s", s);
358 static int property_get_syscall_filter(
361 const char *interface,
362 const char *property,
363 sd_bus_message *reply,
365 sd_bus_error *error) {
367 ExecContext *c = userdata;
368 _cleanup_strv_free_ char **l = NULL;
380 r = sd_bus_message_open_container(reply, 'r', "bas");
384 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
389 SET_FOREACH(id, c->syscall_filter, i) {
392 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
396 r = strv_consume(&l, name);
404 r = sd_bus_message_append_strv(reply, l);
408 return sd_bus_message_close_container(reply);
411 static int property_get_syscall_archs(
414 const char *interface,
415 const char *property,
416 sd_bus_message *reply,
418 sd_bus_error *error) {
420 ExecContext *c = userdata;
421 _cleanup_strv_free_ char **l = NULL;
434 SET_FOREACH(id, c->syscall_archs, i) {
437 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
441 r = strv_extend(&l, name);
449 r = sd_bus_message_append_strv(reply, l);
456 static int property_get_syscall_errno(
459 const char *interface,
460 const char *property,
461 sd_bus_message *reply,
463 sd_bus_error *error) {
465 ExecContext *c = userdata;
471 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
474 static int property_get_selinux_context(
477 const char *interface,
478 const char *property,
479 sd_bus_message *reply,
481 sd_bus_error *error) {
483 ExecContext *c = userdata;
489 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
492 static int property_get_apparmor_profile(
495 const char *interface,
496 const char *property,
497 sd_bus_message *reply,
499 sd_bus_error *error) {
501 ExecContext *c = userdata;
507 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
510 static int property_get_personality(
513 const char *interface,
514 const char *property,
515 sd_bus_message *reply,
517 sd_bus_error *error) {
519 ExecContext *c = userdata;
525 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
528 static int property_get_address_families(
531 const char *interface,
532 const char *property,
533 sd_bus_message *reply,
535 sd_bus_error *error) {
537 ExecContext *c = userdata;
538 _cleanup_strv_free_ char **l = NULL;
547 r = sd_bus_message_open_container(reply, 'r', "bas");
551 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
555 SET_FOREACH(af, c->address_families, i) {
558 name = af_to_name(PTR_TO_INT(af));
562 r = strv_extend(&l, name);
569 r = sd_bus_message_append_strv(reply, l);
573 return sd_bus_message_close_container(reply);
576 const sd_bus_vtable bus_exec_vtable[] = {
577 SD_BUS_VTABLE_START(0),
578 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
579 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
580 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
581 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
582 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
583 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
584 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
585 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
586 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
587 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
588 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
589 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
590 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
591 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
592 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
593 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
594 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
595 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
596 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
597 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
598 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
599 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
600 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
601 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
602 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
603 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
604 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
605 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
606 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
607 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
608 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
609 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
610 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
611 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
612 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
613 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
614 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
615 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
616 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
617 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
618 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
619 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
620 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
621 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
622 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
623 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
624 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
625 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
626 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
627 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
630 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("ProtectedHome", "s", bus_property_get_protected_home, offsetof(ExecContext, protected_home), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("ReadOnlySystem", "b", bus_property_get_bool, offsetof(ExecContext, read_only_system), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
646 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
650 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
659 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
663 r = sd_bus_message_append(reply, "s", c->path);
667 r = sd_bus_message_append_strv(reply, c->argv);
671 r = sd_bus_message_append(reply, "bttttuii",
673 c->exec_status.start_timestamp.realtime,
674 c->exec_status.start_timestamp.monotonic,
675 c->exec_status.exit_timestamp.realtime,
676 c->exec_status.exit_timestamp.monotonic,
677 (uint32_t) c->exec_status.pid,
678 (int32_t) c->exec_status.code,
679 (int32_t) c->exec_status.status);
683 return sd_bus_message_close_container(reply);
686 int bus_property_get_exec_command(
689 const char *interface,
690 const char *property,
691 sd_bus_message *reply,
693 sd_bus_error *ret_error) {
695 ExecCommand *c = (ExecCommand*) userdata;
701 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
705 r = append_exec_command(reply, c);
709 return sd_bus_message_close_container(reply);
712 int bus_property_get_exec_command_list(
715 const char *interface,
716 const char *property,
717 sd_bus_message *reply,
719 sd_bus_error *ret_error) {
721 ExecCommand *c = *(ExecCommand**) userdata;
727 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
731 LIST_FOREACH(command, c, c) {
732 r = append_exec_command(reply, c);
737 return sd_bus_message_close_container(reply);
740 int bus_exec_context_set_transient_property(
744 sd_bus_message *message,
745 UnitSetPropertiesMode mode,
746 sd_bus_error *error) {
755 if (streq(name, "User")) {
758 r = sd_bus_message_read(message, "s", &uu);
762 if (mode != UNIT_CHECK) {
778 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
783 } else if (streq(name, "Group")) {
786 r = sd_bus_message_read(message, "s", &gg);
790 if (mode != UNIT_CHECK) {
806 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
811 } else if (streq(name, "Nice")) {
814 r = sd_bus_message_read(message, "i", &n);
818 if (n < PRIO_MIN || n >= PRIO_MAX)
819 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
821 if (mode != UNIT_CHECK) {
823 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
828 } else if (streq(name, "Environment")) {
830 _cleanup_strv_free_ char **l = NULL;
832 r = sd_bus_message_read_strv(message, &l);
836 if (!strv_env_is_valid(l))
837 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
839 if (mode != UNIT_CHECK) {
840 _cleanup_free_ char *joined = NULL;
843 e = strv_env_merge(2, c->environment, l);
847 strv_free(c->environment);
850 joined = strv_join(c->environment, " ");
854 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
859 } else if (rlimit_from_string(name) >= 0) {
863 r = sd_bus_message_read(message, "t", &rl);
867 if (rl == (uint64_t) -1)
872 if ((uint64_t) x != rl)
876 if (mode != UNIT_CHECK) {
879 z = rlimit_from_string(name);
882 c->rlimit[z] = new(struct rlimit, 1);
887 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
889 if (x == RLIM_INFINITY)
890 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
892 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);