#include "alloc-util.h"
#include "bus-util.h"
#include "capability-util.h"
+#include "cap-list.h"
#include "dbus-execute.h"
#include "env-util.h"
+#include "errno-list.h"
#include "execute.h"
#include "fd-util.h"
#include "fileio.h"
#ifdef HAVE_SECCOMP
#include "seccomp-util.h"
#endif
+#include "securebits-util.h"
#include "strv.h"
#include "syslog-util.h"
#include "unit-printf.h"
}
return 1;
+
+ } else if (streq(name, "SupplementaryGroups")) {
+ _cleanup_strv_free_ char **l = NULL;
+ char **p;
+
+ r = sd_bus_message_read_strv(message, &l);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(p, l) {
+ if (!isempty(*p) && !valid_user_group_name_or_id(*p))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid supplementary group names");
+ }
+
+ if (mode != UNIT_CHECK) {
+ if (strv_length(l) == 0) {
+ c->supplementary_groups = strv_free(c->supplementary_groups);
+ unit_write_drop_in_private_format(u, mode, name, "%s=", name);
+ } else {
+ _cleanup_free_ char *joined = NULL;
+
+ r = strv_extend_strv(&c->supplementary_groups, l, true);
+ if (r < 0)
+ return -ENOMEM;
+
+ joined = strv_join(c->supplementary_groups, " ");
+ if (!joined)
+ return -ENOMEM;
+
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
+ }
+ }
+
+ return 1;
+
} else if (streq(name, "SyslogIdentifier")) {
const char *id;
}
return 1;
+ } else if (streq(name, "SecureBits")) {
+ int n;
+
+ r = sd_bus_message_read(message, "i", &n);
+ if (r < 0)
+ return r;
+
+ if (!secure_bits_is_valid(n))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid secure bits");
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *str = NULL;
+
+ c->secure_bits = n;
+ r = secure_bits_to_string_alloc(n, &str);
+ if (r < 0)
+ return r;
+
+ unit_write_drop_in_private_format(u, mode, name, "SecureBits=%s", str);
+ }
+
+ return 1;
+ } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
+ uint64_t n;
+
+ r = sd_bus_message_read(message, "t", &n);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *str = NULL;
+
+ if (streq(name, "CapabilityBoundingSet"))
+ c->capability_bounding_set = n;
+ else /* "AmbientCapabilities" */
+ c->capability_ambient_set = n;
+
+ r = capability_set_to_string_alloc(n, &str);
+ if (r < 0)
+ return r;
+
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
+ }
+
+ return 1;
+
+ } else if (streq(name, "Personality")) {
+ const char *s;
+ unsigned long p;
+
+ r = sd_bus_message_read(message, "s", &s);
+ if (r < 0)
+ return r;
+
+ p = personality_from_string(s);
+ if (p == PERSONALITY_INVALID)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid personality");
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *str = NULL;
+
+ c->personality = p;
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, s);
+ }
+
+ return 1;
+
+#ifdef HAVE_SECCOMP
+
+ } else if (streq(name, "SystemCallFilter")) {
+ int whitelist;
+ _cleanup_strv_free_ char **l;
+
+ r = sd_bus_message_enter_container(message, 'r', "bas");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "b", &whitelist);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read_strv(message, &l);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *joined = NULL;
+
+ if (strv_length(l) == 0) {
+ c->syscall_whitelist = false;
+ c->syscall_filter = set_free(c->syscall_filter);
+ } else {
+ char **s;
+
+ c->syscall_whitelist = whitelist;
+
+ r = set_ensure_allocated(&c->syscall_filter, NULL);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(s, l) {
+ if (**s == '@') {
+ const SyscallFilterSet *set;
+ const char *i;
+
+ set = syscall_filter_set_find(*s);
+ if (!set)
+ return -EINVAL;
+
+ NULSTR_FOREACH(i, set->value) {
+ int id;
+
+ id = seccomp_syscall_resolve_name(i);
+ if (id == __NR_SCMP_ERROR)
+ return -EINVAL;
+
+ r = set_put(c->address_families, INT_TO_PTR(id + 1));
+ if (r < 0)
+ return r;
+ }
+
+ } else {
+ int id;
+
+ id = seccomp_syscall_resolve_name(*s);
+ if (id == __NR_SCMP_ERROR)
+ return -EINVAL;
+
+ r = set_put(c->address_families, INT_TO_PTR(id + 1));
+ if (r < 0)
+ return r;
+ }
+ }
+ }
+
+ joined = strv_join(l, " ");
+ if (!joined)
+ return -ENOMEM;
+
+ unit_write_drop_in_private_format(u, mode, name, "SystemCallFilter=%s%s", whitelist ? "" : "~", joined);
+ }
+
+ return 1;
+
+ } else if (streq(name, "SystemCallArchitectures")) {
+ _cleanup_strv_free_ char **l = NULL;
+
+ r = sd_bus_message_read_strv(message, &l);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *joined = NULL;
+
+ if (strv_length(l) == 0)
+ c->syscall_archs = set_free(c->syscall_archs);
+ else {
+ char **s;
+
+ r = set_ensure_allocated(&c->syscall_archs, NULL);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(s, l) {
+ uint32_t a;
+
+ r = seccomp_arch_from_string(*s, &a);
+ if (r < 0)
+ return r;
+
+ r = set_put(c->syscall_archs, UINT32_TO_PTR(a + 1));
+ if (r < 0)
+ return r;
+ }
+
+ }
+
+ joined = strv_join(l, " ");
+ if (!joined)
+ return -ENOMEM;
+
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, joined);
+ }
+
+ return 1;
+
+ } else if (streq(name, "SystemCallErrorNumber")) {
+ int32_t n;
+ const char *str;
+
+ r = sd_bus_message_read(message, "i", &n);
+ if (r < 0)
+ return r;
+
+ str = errno_to_name(n);
+ if (!str)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid SystemCallErrorNumber");
+
+ if (mode != UNIT_CHECK) {
+ c->syscall_errno = n;
+
+ unit_write_drop_in_private_format(u, mode, name, "SystemCallErrorNumber=%s", str);
+ }
+
+ return 1;
+
+ } else if (streq(name, "RestrictAddressFamilies")) {
+ int whitelist;
+ _cleanup_strv_free_ char **l;
+
+ r = sd_bus_message_enter_container(message, 'r', "bas");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "b", &whitelist);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read_strv(message, &l);
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_exit_container(message);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *joined = NULL;
+
+ if (strv_length(l) == 0) {
+ c->address_families_whitelist = false;
+ c->address_families = set_free(c->address_families);
+ } else {
+ char **s;
+
+ c->address_families_whitelist = whitelist;
+
+ r = set_ensure_allocated(&c->address_families, NULL);
+ if (r < 0)
+ return r;
+
+ STRV_FOREACH(s, l) {
+ int af;
+
+ af = af_from_name(*s);
+ if (af <= 0)
+ return -EINVAL;
+
+ r = set_put(c->address_families, INT_TO_PTR(af));
+ if (r < 0)
+ return r;
+ }
+ }
+
+ joined = strv_join(l, " ");
+ if (!joined)
+ return -ENOMEM;
+
+ unit_write_drop_in_private_format(u, mode, name, "RestrictAddressFamilies=%s%s", whitelist ? "" : "~", joined);
+ }
+
+ return 1;
+#endif
+
+ } else if (streq(name, "CPUSchedulingPolicy")) {
+ int32_t n;
+
+ r = sd_bus_message_read(message, "i", &n);
+ if (r < 0)
+ return r;
+
+ if (!sched_policy_is_valid(n))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling policy");
+
+ if (mode != UNIT_CHECK) {
+ _cleanup_free_ char *str = NULL;
+
+ c->cpu_sched_policy = n;
+ r = sched_policy_to_string_alloc(n, &str);
+ if (r < 0)
+ return r;
+
+ unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPolicy=%s", str);
+ }
+
+ return 1;
+
+ } else if (streq(name, "CPUSchedulingPriority")) {
+ int32_t n;
+
+ r = sd_bus_message_read(message, "i", &n);
+ if (r < 0)
+ return r;
+
+ if (!ioprio_priority_is_valid(n))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
+
+ if (mode != UNIT_CHECK) {
+ c->cpu_sched_priority = n;
+ unit_write_drop_in_private_format(u, mode, name, "CPUSchedulingPriority=%i", n);
+ }
+
+ return 1;
+
+ } else if (streq(name, "CPUAffinity")) {
+ const void *a;
+ size_t n = 0;
+
+ r = sd_bus_message_read_array(message, 'y', &a, &n);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ if (n == 0) {
+ c->cpuset = mfree(c->cpuset);
+ unit_write_drop_in_private_format(u, mode, name, "%s=", name);
+ } else {
+ _cleanup_free_ char *str = NULL;
+ uint8_t *l;
+ size_t allocated = 0, len = 0, i;
+
+ c->cpuset = (cpu_set_t*) memdup(a, sizeof(cpu_set_t) * n);
+ if (c->cpuset)
+ return -ENOMEM;
+
+ l = (uint8_t*) a;
+ for (i = 0; i < n; i++) {
+ _cleanup_free_ char *p = NULL;
+ size_t add;
+
+ r = asprintf(&p, "%hhi", l[i]);
+ if (r < 0)
+ return -ENOMEM;
+
+ add = strlen(p);
+
+ if (GREEDY_REALLOC(str, allocated, len + add + 2))
+ return -ENOMEM;
+
+ strcpy(mempcpy(str + len, p, add), " ");
+ len += add + 1;
+ }
+
+ if (len != 0)
+ str[len - 1] = '\0';
+
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, str);
+ }
+ }
+
+ return 1;
} else if (streq(name, "Nice")) {
int32_t n;
return 1;
} else if (STR_IN_SET(name,
- "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
+ "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers",
"NoNewPrivileges", "SyslogLevelPrefix", "MemoryDenyWriteExecute",
"RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
- "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS")) {
+ "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
+ "CPUSchedulingResetOnFork", "NonBlocking")) {
int b;
r = sd_bus_message_read(message, "b", &b);
c->tty_vhangup = b;
else if (streq(name, "TTYReset"))
c->tty_reset = b;
+ else if (streq(name, "TTYVTDisallocate"))
+ c->tty_vt_disallocate = b;
else if (streq(name, "PrivateTmp"))
c->private_tmp = b;
else if (streq(name, "PrivateDevices"))
c->protect_control_groups = b;
else if (streq(name, "MountAPIVFS"))
c->mount_apivfs = b;
+ else if (streq(name, "CPUSchedulingResetOnFork"))
+ c->cpu_sched_reset_on_fork = b;
+ else if (streq(name, "NonBlocking"))
+ c->non_blocking = b;
unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, yes_no(b));
}
return 1;
- } else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode")) {
+ } else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
mode_t m;
r = sd_bus_message_read(message, "u", &m);
if (mode != UNIT_CHECK) {
ExecDirectoryType i;
- for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
- if (startswith(name, exec_directory_type_to_string(i))) {
- c->directories[i].mode = m;
- break;
- }
+ if (streq(name, "UMask"))
+ c->umask = m;
+ else
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
+ if (startswith(name, exec_directory_type_to_string(i))) {
+ c->directories[i].mode = m;
+ break;
+ }
unit_write_drop_in_private_format(u, mode, name, "%s=%040o", name, m);
}
} else if (streq(name, "SELinuxContext")) {
const char *s;
-
r = sd_bus_message_read(message, "s", &s);
if (r < 0)
return r;
}
return 1;
+
+ } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
+ int ignore;
+ const char *s;
+
+ r = sd_bus_message_enter_container(message, 'r', "bs");
+ if (r < 0)
+ return r;
+
+ r = sd_bus_message_read(message, "bs", &ignore, &s);
+ if (r < 0)
+ return r;
+
+ if (mode != UNIT_CHECK) {
+ char **p;
+ bool *b;
+
+ if (streq(name, "AppArmorProfile")) {
+ p = &c->apparmor_profile;
+ b = &c->apparmor_profile_ignore;
+ } else { /* "SmackProcessLabel" */
+ p = &c->smack_process_label;
+ b = &c->smack_process_label_ignore;
+ }
+
+ if (isempty(s)) {
+ *p = mfree(*p);
+ *b = false;
+ } else {
+ if (free_and_strdup(p, s) < 0)
+ return -ENOMEM;
+ *b = ignore;
+ }
+
+ unit_write_drop_in_private_format(u, mode, name, "%s=%s%s", name, ignore ? "-" : "", strempty(s));
+ }
+
+ return 1;
+
} else if (streq(name, "RestrictNamespaces")) {
uint64_t flags;
#include "bus-internal.h"
#include "bus-unit-util.h"
#include "bus-util.h"
+#include "cap-list.h"
#include "cgroup-util.h"
+#include "cpu-set-util.h"
#include "env-util.h"
+#include "errno-list.h"
#include "escape.h"
#include "hashmap.h"
#include "list.h"
#include "path-util.h"
#include "process-util.h"
#include "rlimit-util.h"
+#include "securebits-util.h"
#include "signal-util.h"
#include "string-util.h"
#include "syslog-util.h"
#include "terminal-util.h"
+#include "user-util.h"
#include "utf8.h"
#include "util.h"
} else if (STR_IN_SET(field,
"CPUAccounting", "MemoryAccounting", "IOAccounting", "BlockIOAccounting", "TasksAccounting",
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
- "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
+ "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "TTYVTDisallocate", "RemainAfterExit",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "PrivateUsers", "NoNewPrivileges",
"SyslogLevelPrefix", "Delegate", "RemainAfterElapse", "MemoryDenyWriteExecute",
"RestrictRealtime", "DynamicUser", "RemoveIPC", "ProtectKernelTunables",
- "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS")) {
+ "ProtectKernelModules", "ProtectControlGroups", "MountAPIVFS",
+ "CPUSchedulingResetOnFork")) {
r = parse_boolean(eq);
if (r < 0)
"Description", "Slice", "Type", "WorkingDirectory",
"RootDirectory", "SyslogIdentifier", "ProtectSystem",
"ProtectHome", "SELinuxContext", "Restart", "RootImage",
- "NotifyAccess", "RuntimeDirectoryPreserve"))
+ "NotifyAccess", "RuntimeDirectoryPreserve", "Personality"))
r = sd_bus_message_append(m, "v", "s", eq);
- else if (streq(field, "SyslogLevel")) {
+ else if (STR_IN_SET(field, "AppArmorProfile", "SmackProcessLabel")) {
+ bool ignore;
+ const char *s;
+
+ if (eq[0] == '-') {
+ ignore = true;
+ s = eq + 1;
+ } else {
+ ignore = false;
+ s = eq;
+ }
+
+ r = sd_bus_message_append(m, "v", "(bs)", ignore, s);
+
+ } else if (streq(field, "SyslogLevel")) {
int level;
level = log_level_from_string(eq);
r = sd_bus_message_append(m, "v", "i", facility);
+ } else if (streq(field, "SecureBits")) {
+
+ r = secure_bits_from_string(eq);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ r = sd_bus_message_append(m, "v", "i", r);
+
+ } else if (STR_IN_SET(field, "CapabilityBoundingSet", "AmbientCapabilities")) {
+ uint64_t sum = 0;
+ bool invert = false;
+ const char *p;
+
+ p = eq;
+ if (*p == '~') {
+ invert = true;
+ p++;
+ }
+
+ r = capability_set_from_string(p, &sum);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s.", field, eq);
+ return -EINVAL;
+ }
+
+ sum = invert ? ~sum : sum;
+
+ r = sd_bus_message_append(m, "v", "t", sum);
+
} else if (streq(field, "DeviceAllow")) {
if (isempty(eq))
r = sd_bus_message_append(m, "v", "a(st)", 1, path, u);
}
+ } else if (streq(field, "CPUSchedulingPolicy")) {
+ int n;
+
+ n = sched_policy_from_string(eq);
+ if (n < 0)
+ return log_error_errno(r, "Failed to parse CPUSchedulingPolicy: %s", eq);
+
+ r = sd_bus_message_append(m, "v", "i", (int32_t) n);
+
+ } else if (streq(field, "CPUSchedulingPriority")) {
+ int n;
+
+ r = safe_atoi(eq, &n);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse CPUSchedulingPriority: %s", eq);
+ if (!sched_priority_is_valid(n))
+ return log_error_errno(r, "Invalid CPUSchedulingPriority: %s", eq);
+
+ r = sd_bus_message_append(m, "v", "i", (int32_t) n);
+
+ } else if (streq(field, "CPUAffinity")) {
+ _cleanup_cpu_free_ cpu_set_t *cpuset = NULL;
+ int ncpus;
+
+ ncpus = parse_cpu_set(eq, &cpuset);
+ if (ncpus < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+
+ r = sd_bus_message_open_container(m, 'v', "ay");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (cpuset)
+ sd_bus_message_append_array(m, 'y', cpuset, CPU_ALLOC_SIZE(ncpus));
+
+ r = sd_bus_message_close_container(m);
+
} else if (streq(field, "Nice")) {
int n;
r = sd_bus_message_append(m, "v", "i", (int32_t) n);
+#ifdef HAVE_SECCOMP
+
+ } else if (streq(field, "SystemCallFilter")) {
+ int whitelist;
+ const char *p;
+
+ r = sd_bus_message_open_container(m, 'v', "bas");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ p = eq;
+ if (*p == '~') {
+ whitelist = 0;
+ p++;
+ } else
+ whitelist = 1;
+
+ r = sd_bus_message_append_basic(m, 'b', &whitelist);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ if (whitelist != 0) {
+ r = sd_bus_message_append_basic(m, 's', "@default");
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+ if (r == 0)
+ break;
+
+ r = sd_bus_message_append_basic(m, 's', word);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+
+ } else if (streq(field, "SystemCallArchitectures")) {
+ const char *p;
+
+ r = sd_bus_message_open_container(m, 'v', "as");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ for (p = eq;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+ if (r == 0)
+ break;
+
+ r = sd_bus_message_append_basic(m, 's', word);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+
+ } else if (streq(field, "SystemCallErrorNumber")) {
+ int n;
+
+ n = errno_from_name(eq);
+ if (n < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+
+ r = sd_bus_message_append(m, "v", "i", (int32_t) n);
+
+ } else if (streq(field, "RestrictAddressFamilies")) {
+ int whitelist;
+ const char *p;
+
+ r = sd_bus_message_open_container(m, 'v', "bas");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ p = eq;
+ if (*p == '~') {
+ whitelist = 0;
+ p++;
+ } else
+ whitelist = 1;
+
+ r = sd_bus_message_append_basic(m, 'b', &whitelist);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ for (;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse %s value: %s", field, eq);
+ if (r == 0)
+ break;
+
+ r = sd_bus_message_append_basic(m, 's', word);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+
+#endif
+
} else if (streq(field, "FileDescriptorStoreMax")) {
unsigned u;
r = sd_bus_message_close_container(m);
- } else if (STR_IN_SET(field, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode")) {
+ } else if (streq(field, "SupplementaryGroups")) {
+ const char *p;
+
+ r = sd_bus_message_open_container(m, 'v', "as");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_open_container(m, 'a', "s");
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ for (p = eq;;) {
+ _cleanup_free_ char *word = NULL;
+
+ r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
+ if (r < 0) {
+ log_error("Failed to parse %s value %s", field, eq);
+ return -EINVAL;
+ }
+ if (r == 0)
+ break;
+
+ if (!valid_user_group_name_or_id(word)) {
+ log_error("Failed to parse %s value %s", field, eq);
+ return -EINVAL;
+ }
+
+ r = sd_bus_message_append_basic(m, 's', word);
+ if (r < 0)
+ return bus_log_create_error(r);
+ }
+
+ r = sd_bus_message_close_container(m);
+ if (r < 0)
+ return bus_log_create_error(r);
+
+ r = sd_bus_message_close_container(m);
+
+ } else if (STR_IN_SET(field, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode", "UMask")) {
mode_t mode;
r = parse_mode(eq, &mode);