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_protect_home, protect_home, ProtectHome);
49 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
51 static int property_get_environment_files(
54 const char *interface,
56 sd_bus_message *reply,
58 sd_bus_error *error) {
60 ExecContext *c = userdata;
68 r = sd_bus_message_open_container(reply, 'a', "(sb)");
72 STRV_FOREACH(j, c->environment_files) {
75 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
80 return sd_bus_message_close_container(reply);
83 static int property_get_rlimit(
86 const char *interface,
88 sd_bus_message *reply,
90 sd_bus_error *error) {
100 rl = *(struct rlimit**) userdata;
104 struct rlimit buf = {};
107 z = rlimit_from_string(property);
114 /* rlim_t might have different sizes, let's map
115 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
117 u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
119 return sd_bus_message_append(reply, "t", u);
122 static int property_get_oom_score_adjust(
125 const char *interface,
126 const char *property,
127 sd_bus_message *reply,
129 sd_bus_error *error) {
132 ExecContext *c = userdata;
139 if (c->oom_score_adjust_set)
140 n = c->oom_score_adjust;
142 _cleanup_free_ char *t = NULL;
145 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
149 return sd_bus_message_append(reply, "i", n);
152 static int property_get_nice(
155 const char *interface,
156 const char *property,
157 sd_bus_message *reply,
159 sd_bus_error *error) {
162 ExecContext *c = userdata;
173 n = getpriority(PRIO_PROCESS, 0);
178 return sd_bus_message_append(reply, "i", n);
181 static int property_get_ioprio(
184 const char *interface,
185 const char *property,
186 sd_bus_message *reply,
188 sd_bus_error *error) {
191 ExecContext *c = userdata;
201 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
203 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
206 return sd_bus_message_append(reply, "i", n);
209 static int property_get_cpu_sched_policy(
212 const char *interface,
213 const char *property,
214 sd_bus_message *reply,
216 sd_bus_error *error) {
218 ExecContext *c = userdata;
225 if (c->cpu_sched_set)
226 n = c->cpu_sched_policy;
228 n = sched_getscheduler(0);
233 return sd_bus_message_append(reply, "i", n);
236 static int property_get_cpu_sched_priority(
239 const char *interface,
240 const char *property,
241 sd_bus_message *reply,
243 sd_bus_error *error) {
245 ExecContext *c = userdata;
252 if (c->cpu_sched_set)
253 n = c->cpu_sched_priority;
255 struct sched_param p = {};
257 if (sched_getparam(0, &p) >= 0)
258 n = p.sched_priority;
263 return sd_bus_message_append(reply, "i", n);
266 static int property_get_cpu_affinity(
269 const char *interface,
270 const char *property,
271 sd_bus_message *reply,
273 sd_bus_error *error) {
275 ExecContext *c = userdata;
282 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
284 return sd_bus_message_append_array(reply, 'y', NULL, 0);
287 static int property_get_timer_slack_nsec(
290 const char *interface,
291 const char *property,
292 sd_bus_message *reply,
294 sd_bus_error *error) {
296 ExecContext *c = userdata;
303 if (c->timer_slack_nsec != NSEC_INFINITY)
304 u = (uint64_t) c->timer_slack_nsec;
306 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
308 return sd_bus_message_append(reply, "t", u);
311 static int property_get_capability_bounding_set(
314 const char *interface,
315 const char *property,
316 sd_bus_message *reply,
318 sd_bus_error *error) {
320 ExecContext *c = userdata;
326 /* We store this negated internally, to match the kernel, but
327 * we expose it normalized. */
328 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
331 static int property_get_capabilities(
334 const char *interface,
335 const char *property,
336 sd_bus_message *reply,
338 sd_bus_error *error) {
340 ExecContext *c = userdata;
341 _cleanup_cap_free_charp_ char *t = NULL;
349 s = t = cap_to_text(c->capabilities, NULL);
356 return sd_bus_message_append(reply, "s", s);
359 static int property_get_syscall_filter(
362 const char *interface,
363 const char *property,
364 sd_bus_message *reply,
366 sd_bus_error *error) {
368 ExecContext *c = userdata;
369 _cleanup_strv_free_ char **l = NULL;
381 r = sd_bus_message_open_container(reply, 'r', "bas");
385 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
390 SET_FOREACH(id, c->syscall_filter, i) {
393 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
397 r = strv_consume(&l, name);
405 r = sd_bus_message_append_strv(reply, l);
409 return sd_bus_message_close_container(reply);
412 static int property_get_syscall_archs(
415 const char *interface,
416 const char *property,
417 sd_bus_message *reply,
419 sd_bus_error *error) {
421 ExecContext *c = userdata;
422 _cleanup_strv_free_ char **l = NULL;
435 SET_FOREACH(id, c->syscall_archs, i) {
438 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
442 r = strv_extend(&l, name);
450 r = sd_bus_message_append_strv(reply, l);
457 static int property_get_syscall_errno(
460 const char *interface,
461 const char *property,
462 sd_bus_message *reply,
464 sd_bus_error *error) {
466 ExecContext *c = userdata;
472 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
475 static int property_get_selinux_context(
478 const char *interface,
479 const char *property,
480 sd_bus_message *reply,
482 sd_bus_error *error) {
484 ExecContext *c = userdata;
490 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
493 static int property_get_apparmor_profile(
496 const char *interface,
497 const char *property,
498 sd_bus_message *reply,
500 sd_bus_error *error) {
502 ExecContext *c = userdata;
508 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
511 static int property_get_personality(
514 const char *interface,
515 const char *property,
516 sd_bus_message *reply,
518 sd_bus_error *error) {
520 ExecContext *c = userdata;
526 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
529 static int property_get_address_families(
532 const char *interface,
533 const char *property,
534 sd_bus_message *reply,
536 sd_bus_error *error) {
538 ExecContext *c = userdata;
539 _cleanup_strv_free_ char **l = NULL;
548 r = sd_bus_message_open_container(reply, 'r', "bas");
552 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
556 SET_FOREACH(af, c->address_families, i) {
559 name = af_to_name(PTR_TO_INT(af));
563 r = strv_extend(&l, name);
570 r = sd_bus_message_append_strv(reply, l);
574 return sd_bus_message_close_container(reply);
577 const sd_bus_vtable bus_exec_vtable[] = {
578 SD_BUS_VTABLE_START(0),
579 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
580 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
581 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
582 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
583 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
584 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
585 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
586 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
587 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
588 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
589 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
590 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
591 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
592 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
593 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
594 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
595 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
596 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
597 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
598 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
599 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
600 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
601 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
602 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
603 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
604 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
605 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
606 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
607 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
608 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
609 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
610 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
611 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
612 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
613 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
614 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
615 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
616 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
617 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
618 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
619 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
620 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
621 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
622 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
623 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
624 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
625 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
626 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
627 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
628 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
629 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
630 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
633 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
646 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
647 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
651 static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
660 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
664 r = sd_bus_message_append(reply, "s", c->path);
668 r = sd_bus_message_append_strv(reply, c->argv);
672 r = sd_bus_message_append(reply, "bttttuii",
674 c->exec_status.start_timestamp.realtime,
675 c->exec_status.start_timestamp.monotonic,
676 c->exec_status.exit_timestamp.realtime,
677 c->exec_status.exit_timestamp.monotonic,
678 (uint32_t) c->exec_status.pid,
679 (int32_t) c->exec_status.code,
680 (int32_t) c->exec_status.status);
684 return sd_bus_message_close_container(reply);
687 int bus_property_get_exec_command(
690 const char *interface,
691 const char *property,
692 sd_bus_message *reply,
694 sd_bus_error *ret_error) {
696 ExecCommand *c = (ExecCommand*) userdata;
702 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
706 r = append_exec_command(reply, c);
710 return sd_bus_message_close_container(reply);
713 int bus_property_get_exec_command_list(
716 const char *interface,
717 const char *property,
718 sd_bus_message *reply,
720 sd_bus_error *ret_error) {
722 ExecCommand *c = *(ExecCommand**) userdata;
728 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
732 LIST_FOREACH(command, c, c) {
733 r = append_exec_command(reply, c);
738 return sd_bus_message_close_container(reply);
741 int bus_exec_context_set_transient_property(
745 sd_bus_message *message,
746 UnitSetPropertiesMode mode,
747 sd_bus_error *error) {
756 if (streq(name, "User")) {
759 r = sd_bus_message_read(message, "s", &uu);
763 if (mode != UNIT_CHECK) {
779 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
784 } else if (streq(name, "Group")) {
787 r = sd_bus_message_read(message, "s", &gg);
791 if (mode != UNIT_CHECK) {
807 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
812 } else if (streq(name, "Nice")) {
815 r = sd_bus_message_read(message, "i", &n);
819 if (n < PRIO_MIN || n >= PRIO_MAX)
820 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
822 if (mode != UNIT_CHECK) {
824 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
829 } else if (streq(name, "Environment")) {
831 _cleanup_strv_free_ char **l = NULL;
833 r = sd_bus_message_read_strv(message, &l);
837 if (!strv_env_is_valid(l))
838 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
840 if (mode != UNIT_CHECK) {
841 _cleanup_free_ char *joined = NULL;
844 e = strv_env_merge(2, c->environment, l);
848 strv_free(c->environment);
851 joined = strv_join_quoted(c->environment);
855 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
860 } else if (rlimit_from_string(name) >= 0) {
864 r = sd_bus_message_read(message, "t", &rl);
868 if (rl == (uint64_t) -1)
873 if ((uint64_t) x != rl)
877 if (mode != UNIT_CHECK) {
880 z = rlimit_from_string(name);
883 c->rlimit[z] = new(struct rlimit, 1);
888 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
890 if (x == RLIM_INFINITY)
891 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
893 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);