core: add missing properties in D-Bus API
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 7 Aug 2017 15:37:02 +0000 (00:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 7 Aug 2017 15:37:02 +0000 (00:37 +0900)
Closes #6466.

src/core/dbus-execute.c
src/shared/bus-unit-util.c

index 12348d3..bd4e113 100644 (file)
 #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"
@@ -43,6 +45,7 @@
 #ifdef HAVE_SECCOMP
 #include "seccomp-util.h"
 #endif
+#include "securebits-util.h"
 #include "strv.h"
 #include "syslog-util.h"
 #include "unit-printf.h"
@@ -1028,6 +1031,41 @@ int bus_exec_context_set_transient_property(
                 }
 
                 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;
 
@@ -1078,6 +1116,361 @@ int bus_exec_context_set_transient_property(
                 }
 
                 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;
 
@@ -1297,11 +1690,12 @@ int bus_exec_context_set_transient_property(
                 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);
@@ -1315,6 +1709,8 @@ int bus_exec_context_set_transient_property(
                                 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"))
@@ -1343,6 +1739,10 @@ int bus_exec_context_set_transient_property(
                                 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));
                 }
@@ -1709,7 +2109,7 @@ int bus_exec_context_set_transient_property(
 
                 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);
@@ -1719,11 +2119,14 @@ int bus_exec_context_set_transient_property(
                 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);
                 }
@@ -1777,7 +2180,6 @@ int bus_exec_context_set_transient_property(
 
         } else if (streq(name, "SELinuxContext")) {
                 const char *s;
-
                 r = sd_bus_message_read(message, "s", &s);
                 if (r < 0)
                         return r;
@@ -1792,6 +2194,45 @@ int bus_exec_context_set_transient_property(
                 }
 
                 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;
 
index 1d77c18..1e72000 100644 (file)
 #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"
 
@@ -204,11 +209,12 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
         } 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)
@@ -267,10 +273,24 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                               "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);
@@ -292,6 +312,37 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
 
                 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))
@@ -381,6 +432,43 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                         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;
 
@@ -390,6 +478,142 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
 
                 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;
 
@@ -548,7 +772,45 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
 
                 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);