diff --git a/src/core/execute.c b/src/core/execute.c index 6301d51ca2..76f30b14a8 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -366,13 +366,17 @@ const char* exec_get_private_notify_socket_path(const ExecContext *context, cons return "/run/host/notify"; } -int exec_log_level_max(const ExecContext *context, const ExecParameters *params) { - assert(context); +int exec_log_level_max_with_exec_params(const ExecContext *context, const ExecParameters *params) { assert(params); if (params->debug_invocation) return LOG_DEBUG; + return exec_log_level_max(context); +} + +int exec_log_level_max(const ExecContext *context) { + assert(context); return context->log_level_max < 0 ? log_get_max_level() : context->log_level_max; } diff --git a/src/core/execute.h b/src/core/execute.h index 2e30374830..8d0f06aeef 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -633,7 +633,8 @@ bool exec_is_cgroup_mount_read_only(const ExecContext *context); const char* exec_get_private_notify_socket_path(const ExecContext *context, const ExecParameters *params, bool needs_sandboxing); -int exec_log_level_max(const ExecContext *context, const ExecParameters *params); +int exec_log_level_max_with_exec_params(const ExecContext *context, const ExecParameters *params); +int exec_log_level_max(const ExecContext *context); /* These logging macros do the same logging as those in unit.h, but using ExecContext and ExecParameters * instead of the unit object, so that it can be used in the sd-executor context (where the unit object is @@ -655,7 +656,7 @@ int exec_log_level_max(const ExecContext *context, const ExecParameters *params) LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_ID_FIELD(p), p->unit_id); \ LOG_CONTEXT_PUSH_KEY_VALUE(LOG_EXEC_INVOCATION_ID_FIELD(p), p->invocation_id_string); \ LOG_CONTEXT_PUSH_IOV(c->log_extra_fields, c->n_log_extra_fields) \ - LOG_CONTEXT_SET_LOG_LEVEL(exec_log_level_max(c, p)) \ + LOG_CONTEXT_SET_LOG_LEVEL(exec_log_level_max_with_exec_params(c, p)) \ LOG_SET_PREFIX(p->unit_id); #define LOG_CONTEXT_PUSH_EXEC(ec, ep) \ diff --git a/src/core/meson.build b/src/core/meson.build index 92d6c143d0..fbadd0f6a6 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -66,6 +66,7 @@ libcore_sources = files( 'varlink-cgroup.c', 'varlink-common.c', 'varlink-dynamic-user.c', + 'varlink-execute.c', 'varlink-manager.c', 'varlink-unit.c', ) diff --git a/src/core/varlink-cgroup.c b/src/core/varlink-cgroup.c index 7e23d4a0f7..d26542f032 100644 --- a/src/core/varlink-cgroup.c +++ b/src/core/varlink-cgroup.c @@ -4,7 +4,6 @@ #include "bpf-program.h" #include "cgroup.h" -#include "cpu-set-util.h" #include "json-util.h" #include "in-addr-prefix-util.h" #include "ip-protocol-list.h" @@ -12,35 +11,7 @@ #include "set.h" #include "unit.h" #include "varlink-cgroup.h" - -#define JSON_BUILD_PAIR_CONDITION_UNSIGNED(condition, name, value) \ - SD_JSON_BUILD_PAIR_CONDITION(condition, name, SD_JSON_BUILD_UNSIGNED(value)) - -static int cpu_set_build_json(sd_json_variant **ret, const char *name, void *userdata) { - _cleanup_free_ uint8_t *array = NULL; - CPUSet *cpuset = ASSERT_PTR(userdata); - size_t allocated; - int r; - - assert(ret); - assert(name); - - if (!cpuset->set) - goto empty; - - r = cpu_set_to_dbus(cpuset, &array, &allocated); - if (r < 0) - return log_debug_errno(r, "Failed to call cpu_set_to_dbus(): %m"); - - if (allocated == 0) - goto empty; - - return sd_json_variant_new_array_bytes(ret, array, allocated); - -empty: - *ret = NULL; - return 0; -} +#include "varlink-common.h" static int tasks_max_build_json(sd_json_variant **ret, const char *name, void *userdata) { CGroupTasksMax *tasks_max = ASSERT_PTR(userdata); @@ -283,8 +254,8 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("StartupCPUWeight", c->startup_cpu_weight, CGROUP_WEIGHT_INVALID), JSON_BUILD_PAIR_FINITE_USEC("CPUQuotaPerSecUSec", c->cpu_quota_per_sec_usec), JSON_BUILD_PAIR_FINITE_USEC("CPUQuotaPeriodUSec", c->cpu_quota_period_usec), - JSON_BUILD_PAIR_CALLBACK_NON_NULL("AllowedCPUs", cpu_set_build_json, &c->cpuset_cpus), - JSON_BUILD_PAIR_CALLBACK_NON_NULL("StartupAllowedCPUs", cpu_set_build_json, &c->startup_cpuset_cpus), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("AllowedCPUs", cpuset_build_json, &c->cpuset_cpus), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("StartupAllowedCPUs", cpuset_build_json, &c->startup_cpuset_cpus), /* Memory Accounting and Control */ SD_JSON_BUILD_PAIR_BOOLEAN("MemoryAccounting", c->memory_accounting), @@ -303,8 +274,8 @@ int unit_cgroup_context_build_json(sd_json_variant **ret, const char *name, void JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("MemoryZSwapMax", c->memory_zswap_max, CGROUP_LIMIT_MAX), JSON_BUILD_PAIR_CONDITION_UNSIGNED(c->startup_memory_zswap_max_set, "StartupMemoryZSwapMax", c->startup_memory_zswap_max), SD_JSON_BUILD_PAIR_BOOLEAN("MemoryZSwapWriteback", c->memory_zswap_writeback), - JSON_BUILD_PAIR_CALLBACK_NON_NULL("AllowedMemoryNodes", cpu_set_build_json, &c->cpuset_mems), - JSON_BUILD_PAIR_CALLBACK_NON_NULL("StartupAllowedMemoryNodes", cpu_set_build_json, &c->startup_cpuset_mems), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("AllowedMemoryNodes", cpuset_build_json, &c->cpuset_mems), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("StartupAllowedMemoryNodes", cpuset_build_json, &c->startup_cpuset_mems), /* Process Accounting and Control */ SD_JSON_BUILD_PAIR_BOOLEAN("TasksAccounting", c->tasks_accounting), @@ -478,7 +449,7 @@ static int effective_cpuset_build_json(sd_json_variant **ret, const char *name, if (r < 0) return log_debug_errno(r, "Failed to get cpu set '%s': %m", cpuset_name); - return cpu_set_build_json(ret, name, &cpus); + return cpuset_build_json(ret, name, &cpus); } static inline int effective_cpus_build_json(sd_json_variant **ret, const char *name, void *userdata) { diff --git a/src/core/varlink-common.c b/src/core/varlink-common.c index 6a1e6af9ae..babed68378 100644 --- a/src/core/varlink-common.c +++ b/src/core/varlink-common.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include "cpu-set-util.h" #include "json-util.h" #include "rlimit-util.h" #include "varlink-common.h" @@ -54,3 +55,28 @@ int rlimit_table_build_json(sd_json_variant **ret, const char *name, void *userd return 0; } + +int cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_free_ uint8_t *array = NULL; + CPUSet *cpuset = ASSERT_PTR(userdata); + size_t allocated; + int r; + + assert(ret); + + if (!cpuset->set) + goto empty; + + r = cpu_set_to_dbus(cpuset, &array, &allocated); + if (r < 0) + return log_debug_errno(r, "Failed to serialize cpu set to dbus: %m"); + + if (allocated == 0) + goto empty; + + return sd_json_variant_new_array_bytes(ret, array, allocated); + +empty: + *ret = NULL; + return 0; +} diff --git a/src/core/varlink-common.h b/src/core/varlink-common.h index 314398e438..24e21e7b0b 100644 --- a/src/core/varlink-common.h +++ b/src/core/varlink-common.h @@ -5,3 +5,4 @@ int rlimit_build_json(sd_json_variant **ret, const char *name, void *userdata); int rlimit_table_build_json(sd_json_variant **ret, const char *name, void *userdata); +int cpuset_build_json(sd_json_variant **ret, const char *name, void *userdata); diff --git a/src/core/varlink-execute.c b/src/core/varlink-execute.c new file mode 100644 index 0000000000..2493c1bbf1 --- /dev/null +++ b/src/core/varlink-execute.c @@ -0,0 +1,957 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include + +#include "sd-json.h" + +#include "alloc-util.h" +#include "capability-list.h" +#include "dissect-image.h" +#include "errno-list.h" +#include "exec-credential.h" +#include "execute.h" +#include "image-policy.h" +#include "ioprio-util.h" +#include "json-util.h" +#include "manager.h" +#include "mountpoint-util.h" +#include "namespace.h" +#include "nsflags.h" +#include "ordered-set.h" +#include "process-util.h" +#include "securebits-util.h" +#include "set.h" +#include "strv.h" +#include "syslog-util.h" +#include "unit.h" +#include "varlink-common.h" +#include "varlink-execute.h" + +static int working_directory_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + + assert(ret); + assert(name); + + const char *wd = c->working_directory_home ? "~" : c->working_directory; + if (!wd) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_STRING("path", wd), + SD_JSON_BUILD_PAIR_BOOLEAN("missingOK", c->working_directory_missing_ok)); +} + +static int root_image_options_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + MountOptions *root_image_options = userdata; + int r; + + assert(ret); + assert(name); + + LIST_FOREACH(mount_options, m, root_image_options) { + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("partitionDesignator", partition_designator_to_string(m->partition_designator)), + SD_JSON_BUILD_PAIR_STRING("options", m->options)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int image_policy_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_free_ char *s = NULL; + ImagePolicy *policy = userdata; + int r; + + assert(ret); + assert(name); + + r = image_policy_to_string(policy ?: &image_policy_service, /* simplify= */ true, &s); + if (r < 0) + return log_debug_errno(r, "Failed to convert image policy to string: %m"); + + return sd_json_variant_new_string(ret, s); +} + +static int bind_paths_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecContext *c = ASSERT_PTR(userdata); + int r; + + assert(ret); + assert(name); + + bool ro = strstr(name, "ReadOnly"); + FOREACH_ARRAY(i, c->bind_mounts, c->n_bind_mounts) { + if (ro != i->read_only) + continue; + + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("source", i->source), + SD_JSON_BUILD_PAIR_STRING("destination", i->destination), + SD_JSON_BUILD_PAIR_BOOLEAN("ignoreEnoent", i->ignore_enoent), + SD_JSON_BUILD_PAIR_STRV("options", STRV_MAKE(i->recursive ? "rbind" : "norbind"))); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int mount_images_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecContext *c = ASSERT_PTR(userdata); + int r; + + assert(ret); + assert(name); + + FOREACH_ARRAY(i, c->mount_images, c->n_mount_images) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *mo = NULL; + + LIST_FOREACH(mount_options, m, i->mount_options) { + r = sd_json_variant_append_arraybo( + &mo, + SD_JSON_BUILD_PAIR_STRING("partitionDesignator", partition_designator_to_string(m->partition_designator)), + SD_JSON_BUILD_PAIR_STRING("options", m->options)); + if (r < 0) + return r; + } + + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("source", i->source), + SD_JSON_BUILD_PAIR_STRING("destination", i->destination), + SD_JSON_BUILD_PAIR_BOOLEAN("ignoreEnoent", i->ignore_enoent), + SD_JSON_BUILD_PAIR_VARIANT("mountOptions", mo)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int extension_images_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecContext *c = ASSERT_PTR(userdata); + int r; + + assert(ret); + assert(name); + + FOREACH_ARRAY(i, c->extension_images, c->n_extension_images) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *mo = NULL; + + LIST_FOREACH(mount_options, m, i->mount_options) { + r = sd_json_variant_append_arraybo( + &mo, + SD_JSON_BUILD_PAIR_STRING("partitionDesignator", partition_designator_to_string(m->partition_designator)), + SD_JSON_BUILD_PAIR_STRING("options", m->options)); + if (r < 0) + return r; + } + + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("source", i->source), + SD_JSON_BUILD_PAIR_BOOLEAN("ignoreEnoent", i->ignore_enoent), + SD_JSON_BUILD_PAIR_VARIANT("mountOptions", mo)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int capability_set_build_json(sd_json_variant **ret, const char *name, void *userdata) { + uint64_t capability_set = PTR_TO_INT64(userdata); + _cleanup_strv_free_ char **l = NULL; + int r; + + assert(ret); + assert(name); + + r = capability_set_to_strv(capability_set, &l); + if (r < 0) + return log_debug_errno(r, "Failed to convert capability set to strv: %m"); + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_array_strv(ret, l); +} + +static int secure_bits_build_json(sd_json_variant **ret, const char *name, void *userdata) { + int secure_bits = PTR_TO_INT(userdata); + _cleanup_strv_free_ char **l = NULL; + int r; + + assert(ret); + assert(name); + + r = secure_bits_to_strv(secure_bits, &l); + if (r < 0) + return log_debug_errno(r, "Failed to convert secure bits to strv: %m"); + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_array_strv(ret, l); +} + +static int rlimit_table_with_defaults_build_json(sd_json_variant **ret, const char *name, void *userdata) { + /* This function is similar rlimit_table_build_json() but it falls back + * to Manager's default if ExecContext doesn't have one. */ + + /* Note, this is deviation from DBus implementation. DBus falls + * back directly to getrlimit() without considering Manager's defaults */ + + Unit *u = ASSERT_PTR(userdata); + Manager *m = ASSERT_PTR(u->manager); + ExecContext *c = ASSERT_PTR(unit_get_exec_context(u)); + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + int r; + + assert(ret); + assert(name); + + for (int i = 0; i < _RLIMIT_MAX; i++) { + r = sd_json_variant_merge_objectbo( + &v, + JSON_BUILD_PAIR_CALLBACK_NON_NULL(rlimit_to_string(i), rlimit_build_json, c->rlimit[i] ?: m->defaults.rlimit[i])); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int cpu_sched_class_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_free_ char *s = NULL; + int r; + + assert(ret); + assert(name); + + int p = exec_context_get_cpu_sched_policy(c); + r = sched_policy_to_string_alloc(p, &s); + if (r < 0) + return log_debug_errno(r, "Failed to convert sched policy to string: %m"); + + return sd_json_variant_new_string(ret, s); +} + +static int cpu_affinity_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + _cleanup_(cpu_set_done) CPUSet numa_cpuset = {}; + ExecContext *c = ASSERT_PTR(userdata); + CPUSet *s = NULL; + int r; + + assert(ret); + assert(name); + + bool cpu_affinity_from_numa = exec_context_get_cpu_affinity_from_numa(c); + if (cpu_affinity_from_numa) { + r = numa_to_cpu_set(&c->numa_policy, &numa_cpuset); + if (r < 0) + return log_debug_errno(r, "Failed to convert numa policy to cpu set: %m"); + + s = &numa_cpuset; + } else + s = &c->cpu_set; + + r = cpuset_build_json(&v, /* name= */ NULL, s); + if (r < 0) + return r; + + if (!v) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_VARIANT("affinity", v), + SD_JSON_BUILD_PAIR_BOOLEAN("fromNUMA", cpu_affinity_from_numa)); +} + +static int numa_policy_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + + assert(ret); + assert(name); + + int t = numa_policy_get_type(&c->numa_policy); + if (!mpol_is_valid(t)) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_string(ret, mpol_to_string(t)); +} + +static int numa_mask_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + + assert(ret); + assert(name); + + int t = numa_policy_get_type(&c->numa_policy); + if (!mpol_is_valid(t)) { + *ret = NULL; + return 0; + } + + return cpuset_build_json(ret, /* name= */ NULL, &c->numa_policy.nodes); +} + +static int ioprio_class_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_free_ char *s = NULL; + int r; + + assert(ret); + assert(name); + + int ioprio = exec_context_get_effective_ioprio(c); + r = ioprio_class_to_string_alloc(ioprio_prio_class(ioprio), &s); + if (r < 0) + return log_debug_errno(r, "Failed to convert IO priority class to string: %m"); + + return sd_json_variant_new_string(ret, s); +} + +static int exec_dir_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecDirectory *exec_dir = ASSERT_PTR(userdata); + const QuotaLimit *quota = &exec_dir->exec_quota; + int r; + + assert(ret); + assert(name); + + if (exec_dir->n_items == 0) { + *ret = NULL; + return 0; + } + + FOREACH_ARRAY(dir, exec_dir->items, exec_dir->n_items) { + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("path", dir->path), + JSON_BUILD_PAIR_STRV_NON_EMPTY("symlinks", dir->symlinks)); + if (r < 0) + return r; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR("paths", SD_JSON_BUILD_VARIANT(v)), + SD_JSON_BUILD_PAIR_UNSIGNED("mode", exec_dir->mode), + SD_JSON_BUILD_PAIR("quota", + SD_JSON_BUILD_OBJECT( + SD_JSON_BUILD_PAIR_BOOLEAN("accounting", quota->quota_accounting), + SD_JSON_BUILD_PAIR_BOOLEAN("enforce", quota->quota_enforce), + SD_JSON_BUILD_PAIR_UNSIGNED("quotaAbsolute", quota->quota_absolute), + SD_JSON_BUILD_PAIR_UNSIGNED("quotaScale", quota->quota_scale)))); +} + +static int temporary_filesystems_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecContext *c = ASSERT_PTR(userdata); + int r; + + assert(ret); + assert(name); + + FOREACH_ARRAY(t, c->temporary_filesystems, c->n_temporary_filesystems) { + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("path", t->path), + JSON_BUILD_PAIR_STRING_NON_EMPTY("options", t->options)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int address_families_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + ExecContext *c = ASSERT_PTR(userdata); + + assert(ret); + assert(name); + + l = exec_context_get_address_families(c); + if (!l) + return -ENOMEM; + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->address_families_allow_list), + SD_JSON_BUILD_PAIR_STRV("addressFamilies", l)); +} + +static int restrict_filesystems_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_strv_free_ char **l = NULL; + + assert(ret); + assert(name); + + l = exec_context_get_restrict_filesystems(c); + if (!l) + return -ENOMEM; + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->restrict_filesystems_allow_list), + SD_JSON_BUILD_PAIR_STRV("filesystems", l)); +} + +static int namespace_flags_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_strv_free_ char **l = NULL; + unsigned long namespaces = PTR_TO_ULONG(userdata); + int r; + + assert(ret); + assert(name); + + r = namespace_flags_to_strv(namespaces, &l); + if (r < 0) + return log_debug_errno(r, "Failed to convert namespace flags to strv: %m"); + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_array_strv(ret, l); +} + +static int private_bpf_delegate_commands_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_free_ char *v = bpf_delegate_commands_to_string(c->bpf_delegate_commands); + + if (!v) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_string(ASSERT_PTR(ret), v); +} + +static int private_bpf_delegate_maps_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_free_ char *v = bpf_delegate_maps_to_string(c->bpf_delegate_maps); + + if (!v) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_string(ASSERT_PTR(ret), v); +} + +static int private_bpf_delegate_programs_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_free_ char *v = bpf_delegate_programs_to_string(c->bpf_delegate_programs); + + if (!v) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_string(ASSERT_PTR(ret), v); +} + +static int private_bpf_delegate_attachments_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_free_ char *v = bpf_delegate_attachments_to_string(c->bpf_delegate_attachments); + + if (!v) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_string(ASSERT_PTR(ret), v); +} + +static int syscall_filter_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_strv_free_ char **l = NULL; + + assert(ret); + assert(name); + + l = exec_context_get_syscall_filter(c); + if (!l) + return -ENOMEM; + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->syscall_allow_list), + SD_JSON_BUILD_PAIR_STRV("systemCalls", l)); +} + +static int syscall_error_number_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + + assert(ret); + assert(name); + + if (c->syscall_errno == 0) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_string(ret, ERRNO_NAME(c->syscall_errno)); +} + +static int syscall_archs_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_strv_free_ char **l = NULL; + + assert(ret); + assert(name); + + l = exec_context_get_syscall_archs(c); + if (!l) + return -ENOMEM; + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_variant_new_array_strv(ret, l); +} + +static int syscall_log_build_json(sd_json_variant **ret, const char *name, void *userdata) { + ExecContext *c = ASSERT_PTR(userdata); + _cleanup_strv_free_ char **l = NULL; + + assert(ret); + assert(name); + + l = exec_context_get_syscall_log(c); + if (!l) + return -ENOMEM; + + if (strv_isempty(l)) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ret, + SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", c->syscall_allow_list), + SD_JSON_BUILD_PAIR_STRV("systemCalls", l)); +} + +static int environment_files_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + char **environment_files = userdata; + int r; + + assert(ret); + assert(name); + + STRV_FOREACH(j, environment_files) { + const char *fn = *j; + if (isempty(fn)) + continue; + + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("path", fn[0] == '-' ? fn + 1 : fn), + SD_JSON_BUILD_PAIR_BOOLEAN("graceful", fn[0] == '-')); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int log_level_build_json(sd_json_variant **ret, const char *name, void *userdata) { + int log_level = PTR_TO_INT(userdata); + _cleanup_free_ char *s = NULL; + int r; + + assert(ret); + assert(name); + + if (log_level < 0) { + *ret = NULL; + return 0; + } + + r = log_level_to_string_alloc(log_level, &s); + if (r < 0) + return log_debug_errno(r, "Failed to convert log level to string: %m"); + + return sd_json_variant_new_string(ret, s); +} + +static int log_extra_fields_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecContext *c = ASSERT_PTR(userdata); + int r; + + assert(ret); + assert(name); + + FOREACH_ARRAY(i, c->log_extra_fields, c->n_log_extra_fields) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *s = NULL; + r = sd_json_variant_new_stringn(&s, i->iov_base, i->iov_len); + if (r < 0) + return r; + + r = sd_json_variant_append_array(&v, s); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int log_filter_patterns_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + ExecContext *c = ASSERT_PTR(userdata); + const char *pattern; + int r; + + assert(ret); + assert(name); + + SET_FOREACH(pattern, c->log_filter_allowed_patterns) { + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", true), + SD_JSON_BUILD_PAIR_STRING("pattern", pattern)); + if (r < 0) + return r; + } + + SET_FOREACH(pattern, c->log_filter_denied_patterns) { + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_BOOLEAN("isAllowList", false), + SD_JSON_BUILD_PAIR_STRING("pattern", pattern)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int syslog_facility_build_json(sd_json_variant **ret, const char *name, void *userdata) { + int log_facility = PTR_TO_INT(userdata); + _cleanup_free_ char *s = NULL; + int r; + + assert(ret); + assert(name); + + r = log_facility_unshifted_to_string_alloc(log_facility, &s); + if (r < 0) + return log_debug_errno(r, "Failed to convert log facility to string: %m"); + + return sd_json_variant_new_string(ret, s); +} + +static int load_credential_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + Hashmap *load_credentials = userdata; + ExecLoadCredential *lc; + int r; + + assert(ret); + assert(name); + + bool encrypted = streq(name, "LoadCredentialEncrypted"); + HASHMAP_FOREACH(lc, load_credentials) { + if (lc->encrypted != encrypted) + continue; + + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("id", lc->id), + SD_JSON_BUILD_PAIR_STRING("path", lc->path)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int import_credential_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + OrderedSet *import_credentials = userdata; + ExecImportCredential *ic; + int r; + + assert(ret); + + ORDERED_SET_FOREACH(ic, import_credentials) { + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("glob", ic->glob), + JSON_BUILD_PAIR_STRING_NON_EMPTY("rename", ic->rename)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +static int set_credential_build_json(sd_json_variant **ret, const char *name, void *userdata) { + _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL; + Hashmap *set_credentials = userdata; + ExecSetCredential *sc; + int r; + + assert(ret); + assert(name); + + bool encrypted = streq(name, "SetCredentialEncrypted"); + HASHMAP_FOREACH(sc, set_credentials) { + if (sc->encrypted != encrypted) + continue; + + r = sd_json_variant_append_arraybo( + &v, + SD_JSON_BUILD_PAIR_STRING("id", sc->id), + SD_JSON_BUILD_PAIR_BASE64("value", sc->data, sc->size)); + if (r < 0) + return r; + } + + *ret = TAKE_PTR(v); + return 0; +} + +int unit_exec_context_build_json(sd_json_variant **ret, const char *name, void *userdata) { + Unit *u = ASSERT_PTR(userdata); + ExecContext *c = unit_get_exec_context(u); + if (!c) { + *ret = NULL; + return 0; + } + + return sd_json_buildo( + ASSERT_PTR(ret), + + /* Paths */ + JSON_BUILD_PAIR_STRV_NON_EMPTY("ExecSearchPath", c->exec_search_path), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("WorkingDirectory", working_directory_build_json, c), + JSON_BUILD_PAIR_STRING_NON_EMPTY("RootDirectory", c->root_directory), + JSON_BUILD_PAIR_STRING_NON_EMPTY("RootImage", c->root_image), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("RootImageOptions", root_image_options_build_json, c->root_image_options), + SD_JSON_BUILD_PAIR_BOOLEAN("RootEphemeral", c->root_ephemeral), + JSON_BUILD_PAIR_BASE64_NON_EMPTY("RootHash", c->root_hash, c->root_hash_size), + JSON_BUILD_PAIR_STRING_NON_EMPTY("RootHashPath", c->root_hash_path), + JSON_BUILD_PAIR_BASE64_NON_EMPTY("RootHashSignature", c->root_hash_sig, c->root_hash_sig_size), + JSON_BUILD_PAIR_STRING_NON_EMPTY("RootHashSignaturePath", c->root_hash_sig_path), + JSON_BUILD_PAIR_STRING_NON_EMPTY("RootVerity", c->root_verity), + SD_JSON_BUILD_PAIR_CALLBACK("RootImagePolicy", image_policy_build_json, c->root_image_policy), + SD_JSON_BUILD_PAIR_CALLBACK("MountImagePolicy", image_policy_build_json, c->mount_image_policy), + SD_JSON_BUILD_PAIR_CALLBACK("ExtensionImagePolicy", image_policy_build_json, c->extension_image_policy), + JSON_BUILD_PAIR_YES_NO("MountAPIVFS", exec_context_get_effective_mount_apivfs(c)), + SD_JSON_BUILD_PAIR_BOOLEAN("BindLogSockets", exec_context_get_effective_bind_log_sockets(c)), + SD_JSON_BUILD_PAIR_STRING("ProtectProc", protect_proc_to_string(c->protect_proc)), + SD_JSON_BUILD_PAIR_STRING("ProcSubset", proc_subset_to_string(c->proc_subset)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("BindPaths", bind_paths_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("BindReadOnlyPaths", bind_paths_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("MountImages", mount_images_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("ExtensionImages", extension_images_build_json, c), + JSON_BUILD_PAIR_STRV_NON_EMPTY("ExtensionDirectories", c->extension_directories), + + /* User/Group Identity */ + JSON_BUILD_PAIR_STRING_NON_EMPTY("User", c->user), + JSON_BUILD_PAIR_STRING_NON_EMPTY("Group", c->group), + SD_JSON_BUILD_PAIR_BOOLEAN("DynamicUser", c->dynamic_user), + JSON_BUILD_PAIR_STRV_NON_EMPTY("SupplementaryGroups", c->supplementary_groups), + JSON_BUILD_PAIR_TRISTATE_NON_NULL("SetLoginEnvironment", c->set_login_environment), + JSON_BUILD_PAIR_STRING_NON_EMPTY("PAMName", c->pam_name), + + /* Capabilities */ + JSON_BUILD_PAIR_CALLBACK_NON_NULL("CapabilityBoundingSet", capability_set_build_json, INT64_TO_PTR(c->capability_bounding_set)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("AmbientCapabilities", capability_set_build_json, INT64_TO_PTR(c->capability_ambient_set)), + + /* Security */ + SD_JSON_BUILD_PAIR_BOOLEAN("NoNewPrivileges", c->no_new_privileges), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SecureBits", secure_bits_build_json, INT_TO_PTR(c->secure_bits)), + + /* Mandatory Access Control */ + SD_JSON_BUILD_PAIR_CONDITION(!!c->selinux_context, "SELinuxContext", + SD_JSON_BUILD_OBJECT( + SD_JSON_BUILD_PAIR_BOOLEAN("ignore", c->selinux_context_ignore), + SD_JSON_BUILD_PAIR_STRING("context", c->selinux_context))), + SD_JSON_BUILD_PAIR_CONDITION(!!c->apparmor_profile, "AppArmorProfile", + SD_JSON_BUILD_OBJECT( + SD_JSON_BUILD_PAIR_BOOLEAN("ignore", c->apparmor_profile_ignore), + SD_JSON_BUILD_PAIR_STRING("profile", c->apparmor_profile))), + SD_JSON_BUILD_PAIR_CONDITION(!!c->smack_process_label, "SmackProcessLabel", + SD_JSON_BUILD_OBJECT( + SD_JSON_BUILD_PAIR_BOOLEAN("ignore", c->smack_process_label_ignore), + SD_JSON_BUILD_PAIR_STRING("label", c->smack_process_label))), + + /* Process Properties */ + SD_JSON_BUILD_PAIR_CALLBACK("Limits", rlimit_table_with_defaults_build_json, u), + JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("UMask", c->umask), + JSON_BUILD_PAIR_UNSIGNED_NON_ZERO("CoredumpFilter", exec_context_get_coredump_filter(c)), + SD_JSON_BUILD_PAIR_STRING("KeyringMode", exec_keyring_mode_to_string(c->keyring_mode)), + JSON_BUILD_PAIR_INTEGER_NON_ZERO("OOMScoreAdjust", exec_context_get_oom_score_adjust(c)), + JSON_BUILD_PAIR_UNSIGNED_NOT_EQUAL("TimerSlackNSec", exec_context_get_timer_slack_nsec(c), NSEC_INFINITY), + JSON_BUILD_PAIR_STRING_NON_EMPTY("Personality", personality_to_string(c->personality)), + SD_JSON_BUILD_PAIR_BOOLEAN("IgnoreSIGPIPE", c->ignore_sigpipe), + + /* Scheduling */ + SD_JSON_BUILD_PAIR_INTEGER("Nice", exec_context_get_nice(c)), + SD_JSON_BUILD_PAIR_CALLBACK("CPUSchedulingPolicy", cpu_sched_class_build_json, c), + SD_JSON_BUILD_PAIR_INTEGER("CPUSchedulingPriority", exec_context_get_cpu_sched_priority(c)), + SD_JSON_BUILD_PAIR_BOOLEAN("CPUSchedulingResetOnFork", c->cpu_sched_reset_on_fork), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("CPUAffinity", cpu_affinity_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("NUMAPolicy", numa_policy_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("NUMAMask", numa_mask_build_json, c), + SD_JSON_BUILD_PAIR_CALLBACK("IOSchedulingClass", ioprio_class_build_json, c), + SD_JSON_BUILD_PAIR_INTEGER("IOSchedulingPriority", ioprio_prio_data(exec_context_get_effective_ioprio(c))), + + /* Sandboxing */ + SD_JSON_BUILD_PAIR_STRING("ProtectSystem", protect_system_to_string(c->protect_system)), + SD_JSON_BUILD_PAIR_STRING("ProtectHome", protect_home_to_string(c->protect_home)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("RuntimeDirectory", exec_dir_build_json, &c->directories[EXEC_DIRECTORY_RUNTIME]), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("StateDirectory", exec_dir_build_json, &c->directories[EXEC_DIRECTORY_STATE]), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("CacheDirectory", exec_dir_build_json, &c->directories[EXEC_DIRECTORY_CACHE]), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogsDirectory", exec_dir_build_json, &c->directories[EXEC_DIRECTORY_LOGS]), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("ConfigurationDirectory", exec_dir_build_json, &c->directories[EXEC_DIRECTORY_CONFIGURATION]), + SD_JSON_BUILD_PAIR_STRING("RuntimeDirectoryPreserve", exec_preserve_mode_to_string(c->runtime_directory_preserve_mode)), + JSON_BUILD_PAIR_FINITE_USEC("TimeoutCleanUSec", c->timeout_clean_usec), + JSON_BUILD_PAIR_STRV_NON_EMPTY("ReadWritePaths", c->read_write_paths), + JSON_BUILD_PAIR_STRV_NON_EMPTY("ReadOnlyPaths", c->read_only_paths), + JSON_BUILD_PAIR_STRV_NON_EMPTY("InaccessiblePaths", c->inaccessible_paths), + JSON_BUILD_PAIR_STRV_NON_EMPTY("ExecPaths", c->exec_paths), + JSON_BUILD_PAIR_STRV_NON_EMPTY("NoExecPaths", c->no_exec_paths), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("TemporaryFileSystem", temporary_filesystems_build_json, c), + /* XXX should we make all these Private/Protect strings??? */ + SD_JSON_BUILD_PAIR_STRING("PrivateTmp", private_tmp_to_string(c->private_tmp)), + JSON_BUILD_PAIR_YES_NO("PrivateDevices", c->private_devices), + JSON_BUILD_PAIR_YES_NO("PrivateNetwork", c->private_network), + JSON_BUILD_PAIR_STRING_NON_EMPTY("NetworkNamespacePath", c->network_namespace_path), + JSON_BUILD_PAIR_YES_NO("PrivateIPC", c->private_ipc), + JSON_BUILD_PAIR_STRING_NON_EMPTY("IPCNamespacePath", c->ipc_namespace_path), + JSON_BUILD_PAIR_TRISTATE_NON_NULL("MemoryKSM", c->memory_ksm), + SD_JSON_BUILD_PAIR_STRING("PrivatePIDs", private_pids_to_string(c->private_pids)), + SD_JSON_BUILD_PAIR_STRING("PrivateUsers", private_users_to_string(c->private_users)), + SD_JSON_BUILD_PAIR_STRING("ProtectHostname", protect_hostname_to_string(c->protect_hostname)), + JSON_BUILD_PAIR_YES_NO("ProtectClock", c->protect_clock), + JSON_BUILD_PAIR_YES_NO("ProtectKernelTunables", c->protect_kernel_tunables), + JSON_BUILD_PAIR_YES_NO("ProtectKernelModules", c->protect_kernel_modules), + JSON_BUILD_PAIR_YES_NO("ProtectKernelLogs", c->protect_kernel_logs), + SD_JSON_BUILD_PAIR_STRING("ProtectControlGroups", protect_control_groups_to_string(c->protect_control_groups)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("RestrictAddressFamilies", address_families_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("RestrictFileSystems", restrict_filesystems_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("RestrictNamespaces", namespace_flags_build_json, ULONG_TO_PTR(c->restrict_namespaces)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("DelegateNamespaces", namespace_flags_build_json, ULONG_TO_PTR(c->delegate_namespaces)), + SD_JSON_BUILD_PAIR_STRING("PrivatePBF", private_bpf_to_string(c->private_bpf)), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("BPFDelegateCommands", private_bpf_delegate_commands_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("BPFDelegateMaps", private_bpf_delegate_maps_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("BPFDelegatePrograms", private_bpf_delegate_programs_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("BPFDelegateAttachments", private_bpf_delegate_attachments_build_json, c), + SD_JSON_BUILD_PAIR_BOOLEAN("LockPersonality", c->lock_personality), + SD_JSON_BUILD_PAIR_BOOLEAN("MemoryDenyWriteExecute", c->memory_deny_write_execute), + SD_JSON_BUILD_PAIR_BOOLEAN("RestrictRealtime", c->restrict_realtime), + SD_JSON_BUILD_PAIR_BOOLEAN("RestrictSUIDSGID", c->restrict_suid_sgid), + SD_JSON_BUILD_PAIR_BOOLEAN("RemoveIPC", c->remove_ipc), + JSON_BUILD_PAIR_TRISTATE_NON_NULL("PrivateMounts", c->private_mounts), + JSON_BUILD_PAIR_STRING_NON_EMPTY("MountFlags", mount_propagation_flag_to_string(c->mount_propagation_flag)), + + /* System Call Filtering */ + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SystemCallFilter", syscall_filter_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SystemCallErrorNumber", syscall_error_number_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SystemCallArchitectures", syscall_archs_build_json, c), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SystemCallLog", syscall_log_build_json, c), + + /* Environment */ + JSON_BUILD_PAIR_STRV_NON_EMPTY("Environment", c->environment), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("EnvironmentFiles", environment_files_build_json, c->environment_files), + JSON_BUILD_PAIR_STRV_NON_EMPTY("PassEnvironment", c->pass_environment), + JSON_BUILD_PAIR_STRV_NON_EMPTY("UnsetEnvironment", c->unset_environment), + + /* Logging and Standard Input/Output */ + SD_JSON_BUILD_PAIR_STRING("StandardInput", exec_input_to_string(c->std_input)), + SD_JSON_BUILD_PAIR_STRING("StandardOutput", exec_output_to_string(c->std_output)), + SD_JSON_BUILD_PAIR_STRING("StandardError", exec_output_to_string(c->std_error)), + JSON_BUILD_PAIR_STRING_NON_EMPTY("StandardInputFileDescriptorName", exec_context_fdname(c, STDIN_FILENO)), + JSON_BUILD_PAIR_STRING_NON_EMPTY("StandardOutputFileDescriptorName", exec_context_fdname(c, STDOUT_FILENO)), + JSON_BUILD_PAIR_STRING_NON_EMPTY("StandardErrorFileDescriptorName", exec_context_fdname(c, STDERR_FILENO)), + JSON_BUILD_PAIR_BASE64_NON_EMPTY("StandardInputData", c->stdin_data, c->stdin_data_size), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogLevelMax", log_level_build_json, INT_TO_PTR(exec_log_level_max(c))), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogExtraFields", log_extra_fields_build_json, c), + JSON_BUILD_PAIR_RATELIMIT_ENABLED("LogRateLimit", &c->log_ratelimit), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LogFilterPatterns", log_filter_patterns_build_json, c), + JSON_BUILD_PAIR_STRING_NON_EMPTY("LogNamespace", c->log_namespace), + JSON_BUILD_PAIR_STRING_NON_EMPTY("SyslogIdentifier", c->syslog_identifier), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SyslogFacility", syslog_facility_build_json, INT_TO_PTR(LOG_FAC(c->syslog_priority))), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SyslogLevel", log_level_build_json, INT_TO_PTR(LOG_PRI(c->syslog_priority))), + SD_JSON_BUILD_PAIR_BOOLEAN("SyslogLevelPrefix", c->syslog_level_prefix), + JSON_BUILD_PAIR_STRING_NON_EMPTY("TTYPath", c->tty_path), + JSON_BUILD_PAIR_CONDITION_BOOLEAN(!!c->tty_path, "TTYReset", c->tty_reset), + JSON_BUILD_PAIR_CONDITION_BOOLEAN(!!c->tty_path, "TTYVHangup", c->tty_vhangup), + JSON_BUILD_PAIR_CONDITION_UNSIGNED(!!c->tty_path, "TTYRows", c->tty_rows), + JSON_BUILD_PAIR_CONDITION_UNSIGNED(!!c->tty_path, "TTYColumns", c->tty_cols), + JSON_BUILD_PAIR_CONDITION_BOOLEAN(!!c->tty_path, "TTYVTDisallocate", c->tty_vt_disallocate), + + /* Credentials */ + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LoadCredential", load_credential_build_json, c->load_credentials), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("LoadCredentialEncrypted", load_credential_build_json, c->load_credentials), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("ImportCredential", import_credential_build_json, c->import_credentials), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SetCredential", set_credential_build_json, c->set_credentials), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("SetCredentialEncrypted", set_credential_build_json, c->set_credentials), + + /* System V Compatibility */ + JSON_BUILD_PAIR_STRING_NON_EMPTY("UtmpIdentifier", c->utmp_id), + SD_JSON_BUILD_PAIR_STRING("UtmpMode", exec_utmp_mode_to_string(c->utmp_mode))); +} diff --git a/src/core/varlink-execute.h b/src/core/varlink-execute.h new file mode 100644 index 0000000000..86b0285509 --- /dev/null +++ b/src/core/varlink-execute.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "forward.h" + +int unit_exec_context_build_json(sd_json_variant **ret, const char *name, void *userdata); diff --git a/src/core/varlink-unit.c b/src/core/varlink-unit.c index eb7191ffb4..a63e405b41 100644 --- a/src/core/varlink-unit.c +++ b/src/core/varlink-unit.c @@ -14,6 +14,8 @@ #include "strv.h" #include "unit.h" #include "varlink-cgroup.h" +#include "varlink-common.h" +#include "varlink-execute.h" #include "varlink-unit.h" #include "varlink-util.h" @@ -182,8 +184,8 @@ static int unit_context_build_json(sd_json_variant **ret, const char *name, void SD_JSON_BUILD_PAIR_BOOLEAN("Perpetual", u->perpetual), SD_JSON_BUILD_PAIR_BOOLEAN("DebugInvocation", u->debug_invocation), - /* CGroup */ - JSON_BUILD_PAIR_CALLBACK_NON_NULL("CGroup", unit_cgroup_context_build_json, u)); + JSON_BUILD_PAIR_CALLBACK_NON_NULL("CGroup", unit_cgroup_context_build_json, u), + JSON_BUILD_PAIR_CALLBACK_NON_NULL("Exec", unit_exec_context_build_json, u)); // TODO follow up PRs: // JSON_BUILD_PAIR_CALLBACK_NON_NULL("Exec", exec_context_build_json, u) diff --git a/src/libsystemd/sd-json/json-util.h b/src/libsystemd/sd-json/json-util.h index d5e8f57e4a..c163a54a76 100644 --- a/src/libsystemd/sd-json/json-util.h +++ b/src/libsystemd/sd-json/json-util.h @@ -250,6 +250,12 @@ enum { #define JSON_BUILD_PAIR_TRISTATE(name, i) SD_JSON_BUILD_PAIR(name, JSON_BUILD_TRISTATE(i)) #define JSON_BUILD_PAIR_PIDREF(name, p) SD_JSON_BUILD_PAIR(name, JSON_BUILD_PIDREF(p)) #define JSON_BUILD_PAIR_DEVNUM(name, d) SD_JSON_BUILD_PAIR(name, JSON_BUILD_DEVNUM(d)) +#define JSON_BUILD_PAIR_YES_NO(name, b) SD_JSON_BUILD_PAIR(name, SD_JSON_BUILD_STRING(yes_no(b))) + +#define JSON_BUILD_PAIR_CONDITION_UNSIGNED(condition, name, value) \ + SD_JSON_BUILD_PAIR_CONDITION(condition, name, SD_JSON_BUILD_UNSIGNED(value)) +#define JSON_BUILD_PAIR_CONDITION_BOOLEAN(condition, name, value) \ + SD_JSON_BUILD_PAIR_CONDITION(condition, name, SD_JSON_BUILD_BOOLEAN(value)) int json_variant_new_pidref(sd_json_variant **ret, PidRef *pidref); int json_variant_new_devnum(sd_json_variant **ret, dev_t devnum); diff --git a/src/shared/nsflags.c b/src/shared/nsflags.c index e14aa09810..b852221c67 100644 --- a/src/shared/nsflags.c +++ b/src/shared/nsflags.c @@ -5,6 +5,7 @@ #include "namespace-util.h" #include "nsflags.h" #include "string-util.h" +#include "strv.h" int namespace_flags_from_string(const char *name, unsigned long *ret) { unsigned long flags = 0; @@ -40,19 +41,41 @@ int namespace_flags_from_string(const char *name, unsigned long *ret) { } int namespace_flags_to_string(unsigned long flags, char **ret) { + _cleanup_strv_free_ char **l = NULL; _cleanup_free_ char *s = NULL; + int r; + + assert(ret); + + r = namespace_flags_to_strv(flags, &l); + if (r < 0) + return r; + + s = strv_join(l, NULL); + if (!s) + return -ENOMEM; + + *ret = TAKE_PTR(s); + return 0; +} + +int namespace_flags_to_strv(unsigned long flags, char ***ret) { + _cleanup_strv_free_ char **s = NULL; unsigned i; + int r; + + assert(ret); for (i = 0; namespace_info[i].proc_name; i++) { if ((flags & namespace_info[i].clone_flag) != namespace_info[i].clone_flag) continue; - if (!strextend_with_separator(&s, " ", namespace_info[i].proc_name)) - return -ENOMEM; + r = strv_extend(&s, namespace_info[i].proc_name); + if (r < 0) + return r; } *ret = TAKE_PTR(s); - return 0; } diff --git a/src/shared/nsflags.h b/src/shared/nsflags.h index 19d3fc195e..f046a9ef8c 100644 --- a/src/shared/nsflags.h +++ b/src/shared/nsflags.h @@ -23,4 +23,5 @@ int namespace_flags_from_string(const char *name, unsigned long *ret); int namespace_flags_to_string(unsigned long flags, char **ret); +int namespace_flags_to_strv(unsigned long flags, char ***ret); const char* namespace_single_flag_to_string(unsigned long flag) _const_; diff --git a/src/shared/securebits-util.c b/src/shared/securebits-util.c index 92c7415337..783953aa60 100644 --- a/src/shared/securebits-util.c +++ b/src/shared/securebits-util.c @@ -6,30 +6,71 @@ #include "extract-word.h" #include "securebits-util.h" #include "string-util.h" +#include "strv.h" -int secure_bits_to_string_alloc(int i, char **s) { - _cleanup_free_ char *str = NULL; - size_t len; +static inline const char* secure_bit_to_string(int i) { + /* match a single bit */ + + switch (i) { + case SECURE_KEEP_CAPS: + return "keep-caps"; + case SECURE_KEEP_CAPS_LOCKED: + return "keep-caps-locked"; + case SECURE_NO_SETUID_FIXUP: + return "no-setuid-fixup"; + case SECURE_NO_SETUID_FIXUP_LOCKED: + return "no-setuid-fixup-locked"; + case SECURE_NOROOT: + return "noroot"; + case SECURE_NOROOT_LOCKED: + return "noroot-locked"; + default: + assert_not_reached(); + } +} + +int secure_bits_to_string_alloc(int i, char **ret) { + _cleanup_strv_free_ char **sv = NULL; + _cleanup_free_ char *joined = NULL; int r; - assert(s); + assert(ret); - r = asprintf(&str, "%s%s%s%s%s%s", - (i & (1 << SECURE_KEEP_CAPS)) ? "keep-caps " : "", - (i & (1 << SECURE_KEEP_CAPS_LOCKED)) ? "keep-caps-locked " : "", - (i & (1 << SECURE_NO_SETUID_FIXUP)) ? "no-setuid-fixup " : "", - (i & (1 << SECURE_NO_SETUID_FIXUP_LOCKED)) ? "no-setuid-fixup-locked " : "", - (i & (1 << SECURE_NOROOT)) ? "noroot " : "", - (i & (1 << SECURE_NOROOT_LOCKED)) ? "noroot-locked " : ""); + r = secure_bits_to_strv(i, &sv); if (r < 0) + return r; + + joined = strv_join(sv, " "); + if (!joined) return -ENOMEM; - len = strlen(str); - if (len != 0) - str[len - 1] = '\0'; + *ret = TAKE_PTR(joined); + return 0; +} - *s = TAKE_PTR(str); +int secure_bits_to_strv(int i, char ***ret) { + _cleanup_strv_free_ char **sv = NULL; + static const int bits[] = { + SECURE_KEEP_CAPS, + SECURE_KEEP_CAPS_LOCKED, + SECURE_NO_SETUID_FIXUP, + SECURE_NO_SETUID_FIXUP_LOCKED, + SECURE_NOROOT, + SECURE_NOROOT_LOCKED, + }; + int r; + assert(ret); + + FOREACH_ELEMENT(bit, bits) { + if (i & (1 << *bit)) { + r = strv_extend(&sv, secure_bit_to_string(*bit)); + if (r < 0) + return r; + } + } + + *ret = TAKE_PTR(sv); return 0; } diff --git a/src/shared/securebits-util.h b/src/shared/securebits-util.h index dc61ecd57e..6251fb7922 100644 --- a/src/shared/securebits-util.h +++ b/src/shared/securebits-util.h @@ -5,7 +5,8 @@ #include "shared-forward.h" -int secure_bits_to_string_alloc(int i, char **s); +int secure_bits_to_strv(int i, char ***ret); +int secure_bits_to_string_alloc(int i, char **ret); int secure_bits_from_string(const char *s); static inline bool secure_bits_is_valid(int i) { diff --git a/src/shared/varlink-io.systemd.Unit.c b/src/shared/varlink-io.systemd.Unit.c index 9283831e29..ec6cf89b1e 100644 --- a/src/shared/varlink-io.systemd.Unit.c +++ b/src/shared/varlink-io.systemd.Unit.c @@ -4,6 +4,7 @@ #include "varlink-idl-common.h" #include "varlink-io.systemd.Unit.h" +/* CGroupContext */ static SD_VARLINK_DEFINE_STRUCT_TYPE( CGroupTasksMax, SD_VARLINK_FIELD_COMMENT("The maximum amount of tasks"), @@ -237,6 +238,485 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_FIELD_COMMENT("Reflects whether to forward coredumps for processes that crash within this cgroup"), SD_VARLINK_DEFINE_FIELD(CoredumpReceive, SD_VARLINK_BOOL, 0)); +/* ExecContext */ +static SD_VARLINK_DEFINE_STRUCT_TYPE( + WorkingDirectory, + SD_VARLINK_FIELD_COMMENT("The path to the working directory"), + SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Whether the path to the working directory is allowed to not exist"), + SD_VARLINK_DEFINE_FIELD(missingOK, SD_VARLINK_BOOL, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + PartitionMountOptions, + SD_VARLINK_FIELD_COMMENT("The partition designator to which the options apply"), + SD_VARLINK_DEFINE_FIELD(partitionDesignator, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The mount options for this partition"), + SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + BindPath, + SD_VARLINK_FIELD_COMMENT("The mount source path"), + SD_VARLINK_DEFINE_FIELD(source, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The mount destination path"), + SD_VARLINK_DEFINE_FIELD(destination, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Whether a missing source path should be ignored"), + SD_VARLINK_DEFINE_FIELD(ignoreEnoent, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("Mount options"), + SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, SD_VARLINK_ARRAY)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + MountImage, + SD_VARLINK_FIELD_COMMENT("The path to the image to mount"), + SD_VARLINK_DEFINE_FIELD(source, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The destination path where to mount the image"), + SD_VARLINK_DEFINE_FIELD(destination, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Whether failure to find the image is considered fatal"), + SD_VARLINK_DEFINE_FIELD(ignoreEnoent, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The mount options to use for the partitions of the image"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(mountOptions, PartitionMountOptions, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ExtensionImage, + SD_VARLINK_FIELD_COMMENT("The path to the extension image"), + SD_VARLINK_DEFINE_FIELD(source, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Whether failure to find the extension image is considered fatal"), + SD_VARLINK_DEFINE_FIELD(ignoreEnoent, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The mount options to use for the partitions of the extension image"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(mountOptions, PartitionMountOptions, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + SELinuxContext, + SD_VARLINK_FIELD_COMMENT("Whether failure to set the SELinux context is ignored"), + SD_VARLINK_DEFINE_FIELD(ignore, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The SELinux context"), + SD_VARLINK_DEFINE_FIELD(context, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + AppArmorProfile, + SD_VARLINK_FIELD_COMMENT("Whether failure to configure the apparmor profile will be ignored"), + SD_VARLINK_DEFINE_FIELD(ignore, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The AppArmor profile"), + SD_VARLINK_DEFINE_FIELD(profile, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + SmackProcessLabel, + SD_VARLINK_FIELD_COMMENT("Whether failure to configure the smack process label will be ignored"), + SD_VARLINK_DEFINE_FIELD(ignore, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The smack process label"), + SD_VARLINK_DEFINE_FIELD(label, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + CPUAffinity, + SD_VARLINK_FIELD_COMMENT("CPU affinity of the executed processes"), + SD_VARLINK_DEFINE_FIELD(affinity, SD_VARLINK_INT, SD_VARLINK_ARRAY), + SD_VARLINK_FIELD_COMMENT("CPU affinity from NUMA"), + SD_VARLINK_DEFINE_FIELD(fromNUMA, SD_VARLINK_BOOL, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ExecDirectoryQuota, + SD_VARLINK_FIELD_COMMENT("Whether the quota is accounted"), + SD_VARLINK_DEFINE_FIELD(accounting, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("Whether the quota is enforced"), + SD_VARLINK_DEFINE_FIELD(enforce, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The absolute quota in bytes"), + SD_VARLINK_DEFINE_FIELD(quotaAbsolute, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("The scaling factor for the quota"), + SD_VARLINK_DEFINE_FIELD(quotaScale, SD_VARLINK_INT, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ExecDirectoryPath, + SD_VARLINK_FIELD_COMMENT("The path to the directory"), + SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("A list of symlinks pointing to the directory"), + SD_VARLINK_DEFINE_FIELD(symlinks, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ExecDirectory, + SD_VARLINK_FIELD_COMMENT("Exec directory paths"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(paths, ExecDirectoryPath, SD_VARLINK_ARRAY), + SD_VARLINK_FIELD_COMMENT("The access mode of the directory"), + SD_VARLINK_DEFINE_FIELD(mode, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("The quota for the directory"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(quota, ExecDirectoryQuota, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + TemporaryFilesystem, + SD_VARLINK_FIELD_COMMENT("The destination path where the temporary filesystem should be mounted"), + SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The mount options for the temporary filesystem"), + SD_VARLINK_DEFINE_FIELD(options, SD_VARLINK_STRING, SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + AddressFamilyList, + SD_VARLINK_FIELD_COMMENT("Whether the list of address families is an allow list"), + SD_VARLINK_DEFINE_FIELD(isAllowList, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The list of address families"), + SD_VARLINK_DEFINE_FIELD(addressFamilies, SD_VARLINK_STRING, SD_VARLINK_ARRAY)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + FilesystemList, + SD_VARLINK_FIELD_COMMENT("Whether the list of filesystems is an allow list"), + SD_VARLINK_DEFINE_FIELD(isAllowList, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The list of filesystems"), + SD_VARLINK_DEFINE_FIELD(filesystems, SD_VARLINK_STRING, SD_VARLINK_ARRAY)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + SystemCallList, + SD_VARLINK_FIELD_COMMENT("Whether the list of system calls is an allow list"), + SD_VARLINK_DEFINE_FIELD(isAllowList, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The list of system calls"), + SD_VARLINK_DEFINE_FIELD(systemCalls, SD_VARLINK_STRING, SD_VARLINK_ARRAY)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + EnvironmentFile, + SD_VARLINK_FIELD_COMMENT("The path to the environment file"), + SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("Whether failure to read the environment file is fatal or not"), + SD_VARLINK_DEFINE_FIELD(graceful, SD_VARLINK_BOOL, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + LogFilterPattern, + SD_VARLINK_FIELD_COMMENT("Whether this pattern is an allow pattern"), + SD_VARLINK_DEFINE_FIELD(isAllowList, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("The filtering pattern"), + SD_VARLINK_DEFINE_FIELD(pattern, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + LoadCredential, + SD_VARLINK_FIELD_COMMENT("The credential ID"), + SD_VARLINK_DEFINE_FIELD(id, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The credential path"), + SD_VARLINK_DEFINE_FIELD(path, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ImportCredential, + SD_VARLINK_FIELD_COMMENT("The glob pattern to find credentials"), + SD_VARLINK_DEFINE_FIELD(glob, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The rename pattern to which matching credentials should be renamed"), + SD_VARLINK_DEFINE_FIELD(rename, SD_VARLINK_STRING, SD_VARLINK_NULLABLE)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + SetCredential, + SD_VARLINK_FIELD_COMMENT("The credential ID"), + SD_VARLINK_DEFINE_FIELD(id, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The credential value encoded in base64"), + SD_VARLINK_DEFINE_FIELD(value, SD_VARLINK_STRING, 0)); + +static SD_VARLINK_DEFINE_STRUCT_TYPE( + ExecContext, + + /* Paths + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Paths */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ExecSearchPath="), + SD_VARLINK_DEFINE_FIELD(ExecSearchPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#WorkingDirectory="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(WorkingDirectory, WorkingDirectory, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootDirectory="), + SD_VARLINK_DEFINE_FIELD(RootDirectory, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootImage="), + SD_VARLINK_DEFINE_FIELD(RootImage, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootImageOptions="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RootImageOptions, PartitionMountOptions, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootEphemeral="), + SD_VARLINK_DEFINE_FIELD(RootEphemeral, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootHash="), + SD_VARLINK_DEFINE_FIELD(RootHash, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootHash="), + SD_VARLINK_DEFINE_FIELD(RootHashPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootHashSignature="), + SD_VARLINK_DEFINE_FIELD(RootHashSignature, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootHashSignature="), + SD_VARLINK_DEFINE_FIELD(RootHashSignaturePath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootVerity="), + SD_VARLINK_DEFINE_FIELD(RootVerity, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootImagePolicy="), + SD_VARLINK_DEFINE_FIELD(RootImagePolicy, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootImagePolicy="), + SD_VARLINK_DEFINE_FIELD(MountImagePolicy, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RootImagePolicy="), + SD_VARLINK_DEFINE_FIELD(ExtensionImagePolicy, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#MountAPIVFS="), + SD_VARLINK_DEFINE_FIELD(MountAPIVFS, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BindLogSockets="), + SD_VARLINK_DEFINE_FIELD(BindLogSockets, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectProc="), + SD_VARLINK_DEFINE_FIELD(ProtectProc, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProcSubset="), + SD_VARLINK_DEFINE_FIELD(ProcSubset, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BindPaths="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(BindPaths, BindPath, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BindPaths="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(BindReadOnlyPaths, BindPath, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#MountImages="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(MountImages, MountImage, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ExtensionImages="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(ExtensionImages, ExtensionImage, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ExtensionDirectories="), + SD_VARLINK_DEFINE_FIELD(ExtensionDirectories, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + + /* User/Group Identity + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#User/Group%20Identity */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#User="), + SD_VARLINK_DEFINE_FIELD(User, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#User="), + SD_VARLINK_DEFINE_FIELD(Group, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#DynamicUser="), + SD_VARLINK_DEFINE_FIELD(DynamicUser, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SupplementaryGroups="), + SD_VARLINK_DEFINE_FIELD(SupplementaryGroups, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SetLoginEnvironment="), + SD_VARLINK_DEFINE_FIELD(SetLoginEnvironment, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PAMName="), + SD_VARLINK_DEFINE_FIELD(PAMName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + + /* Capabilities + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Capabilities */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#CapabilityBoundingSet="), + SD_VARLINK_DEFINE_FIELD(CapabilityBoundingSet, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#AmbientCapabilities="), + SD_VARLINK_DEFINE_FIELD(AmbientCapabilities, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + + /* Security + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Security */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#NoNewPrivileges="), + SD_VARLINK_DEFINE_FIELD(NoNewPrivileges, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SecureBits="), + SD_VARLINK_DEFINE_FIELD(SecureBits, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + + /* Mandatory Access Control + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Mandatory%20Access%20Control */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SELinuxContext="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SELinuxContext, SELinuxContext, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#AppArmorProfile="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(AppArmorProfile, AppArmorProfile, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SmackProcessLabel="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SmackProcessLabel, SmackProcessLabel, SD_VARLINK_NULLABLE), + + /* Process Properties + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Process%20Properties */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LimitCPU="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Limits, ResourceLimitTable, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#UMask="), + SD_VARLINK_DEFINE_FIELD(UMask, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#CoredumpFilter="), + SD_VARLINK_DEFINE_FIELD(CoredumpFilter, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#KeyringMode="), + SD_VARLINK_DEFINE_FIELD(KeyringMode, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#OOMScoreAdjust="), + SD_VARLINK_DEFINE_FIELD(OOMScoreAdjust, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TimerSlackNSec="), + SD_VARLINK_DEFINE_FIELD(TimerSlackNSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#Personality="), + SD_VARLINK_DEFINE_FIELD(Personality, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#IgnoreSIGPIPE="), + SD_VARLINK_DEFINE_FIELD(IgnoreSIGPIPE, SD_VARLINK_BOOL, 0), + + /* Scheduling + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Scheduling */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#Nice="), + SD_VARLINK_DEFINE_FIELD(Nice, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#CPUSchedulingPolicy="), + SD_VARLINK_DEFINE_FIELD(CPUSchedulingPolicy, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#CPUSchedulingPriority="), + SD_VARLINK_DEFINE_FIELD(CPUSchedulingPriority, SD_VARLINK_INT, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#CPUSchedulingResetOnFork="), + SD_VARLINK_DEFINE_FIELD(CPUSchedulingResetOnFork, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#CPUAffinity="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(CPUAffinity, CPUAffinity, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#NUMAPolicy="), + SD_VARLINK_DEFINE_FIELD(NUMAPolicy, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#NUMAMask="), + SD_VARLINK_DEFINE_FIELD(NUMAMask, SD_VARLINK_INT, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#IOSchedulingClass="), + SD_VARLINK_DEFINE_FIELD(IOSchedulingClass, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#IOSchedulingPriority="), + SD_VARLINK_DEFINE_FIELD(IOSchedulingPriority, SD_VARLINK_INT, 0), + + /* Sandboxing + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Sandboxing */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectSystem="), + SD_VARLINK_DEFINE_FIELD(ProtectSystem, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectHome="), + SD_VARLINK_DEFINE_FIELD(ProtectHome, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RuntimeDirectory="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RuntimeDirectory, ExecDirectory, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RuntimeDirectory="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(StateDirectory, ExecDirectory, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RuntimeDirectory="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(CacheDirectory, ExecDirectory, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RuntimeDirectory="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LogsDirectory, ExecDirectory, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RuntimeDirectory="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(ConfigurationDirectory, ExecDirectory, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RuntimeDirectoryPreserve="), + SD_VARLINK_DEFINE_FIELD(RuntimeDirectoryPreserve, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TimeoutCleanSec="), + SD_VARLINK_DEFINE_FIELD(TimeoutCleanUSec, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ReadWritePaths="), + SD_VARLINK_DEFINE_FIELD(ReadWritePaths, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ReadWritePaths="), + SD_VARLINK_DEFINE_FIELD(ReadOnlyPaths, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ReadWritePaths="), + SD_VARLINK_DEFINE_FIELD(InaccessiblePaths, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ReadWritePaths="), + SD_VARLINK_DEFINE_FIELD(ExecPaths, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ReadWritePaths="), + SD_VARLINK_DEFINE_FIELD(NoExecPaths, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TemporaryFileSystem="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(TemporaryFileSystem, TemporaryFilesystem, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivateTmp="), + SD_VARLINK_DEFINE_FIELD(PrivateTmp, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivateDevices="), + SD_VARLINK_DEFINE_FIELD(PrivateDevices, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivateNetwork="), + SD_VARLINK_DEFINE_FIELD(PrivateNetwork, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#NetworkNamespacePath="), + SD_VARLINK_DEFINE_FIELD(NetworkNamespacePath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivateIPC="), + SD_VARLINK_DEFINE_FIELD(PrivateIPC, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#IPCNamespacePath="), + SD_VARLINK_DEFINE_FIELD(IPCNamespacePath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#MemoryKSM="), + SD_VARLINK_DEFINE_FIELD(MemoryKSM, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivatePIDs="), + SD_VARLINK_DEFINE_FIELD(PrivatePIDs, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivateUsers="), + SD_VARLINK_DEFINE_FIELD(PrivateUsers, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectHostname="), + SD_VARLINK_DEFINE_FIELD(ProtectHostname, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectClock="), + SD_VARLINK_DEFINE_FIELD(ProtectClock, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectKernelTunables="), + SD_VARLINK_DEFINE_FIELD(ProtectKernelTunables, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectKernelModules="), + SD_VARLINK_DEFINE_FIELD(ProtectKernelModules, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectKernelLogs="), + SD_VARLINK_DEFINE_FIELD(ProtectKernelLogs, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ProtectControlGroups="), + SD_VARLINK_DEFINE_FIELD(ProtectControlGroups, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RestrictAddressFamilies="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RestrictAddressFamilies, AddressFamilyList, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RestrictFileSystems="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(RestrictFilesystems, FilesystemList, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RestrictNamespaces="), + SD_VARLINK_DEFINE_FIELD(RestrictNamespaces, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#DelegateNamespaces="), + SD_VARLINK_DEFINE_FIELD(DelegateNamespaces, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivatePBF="), + SD_VARLINK_DEFINE_FIELD(PrivatePBF, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BPFDelegateCommands="), + SD_VARLINK_DEFINE_FIELD(BPFDelegateCommands, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BPFDelegateMaps="), + SD_VARLINK_DEFINE_FIELD(BPFDelegateMaps, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BPFDelegatePrograms="), + SD_VARLINK_DEFINE_FIELD(BPFDelegatePrograms, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#BPFDelegateAttachments="), + SD_VARLINK_DEFINE_FIELD(BPFDelegateAttachments, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LockPersonality="), + SD_VARLINK_DEFINE_FIELD(LockPersonality, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#MemoryDenyWriteExecute="), + SD_VARLINK_DEFINE_FIELD(MemoryDenyWriteExecute, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RestrictRealtime="), + SD_VARLINK_DEFINE_FIELD(RestrictRealtime, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#RestrictSUIDSGID="), + SD_VARLINK_DEFINE_FIELD(RestrictSUIDSGID, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("Whether to remove all System V and POSIX IPC objects owned by the user and group this unit runs under"), + SD_VARLINK_DEFINE_FIELD(RemoveIPC, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PrivateMounts="), + SD_VARLINK_DEFINE_FIELD(PrivateMounts, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#MountFlags="), + SD_VARLINK_DEFINE_FIELD(MountFlags, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + + /* System Call Filtering + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#System%20Call%20Filtering */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SystemCallFilter="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SystemCallFilter, SystemCallList, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SystemCallErrorNumber="), + SD_VARLINK_DEFINE_FIELD(SystemCallErrorNumber, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SystemCallArchitectures="), + SD_VARLINK_DEFINE_FIELD(SystemCallArchitectures, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SystemCallLog="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SystemCallLog, SystemCallList, SD_VARLINK_NULLABLE), + + /* Environment + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Environment */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#Environment="), + SD_VARLINK_DEFINE_FIELD(Environment, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#EnvironmentFile="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(EnvironmentFiles, EnvironmentFile, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#PassEnvironment="), + SD_VARLINK_DEFINE_FIELD(PassEnvironment, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#UnsetEnvironment="), + SD_VARLINK_DEFINE_FIELD(UnsetEnvironment, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + + /* Logging and Standard Input/Output + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Logging%20and%20Standard%20Input/Output */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#StandardInput="), + SD_VARLINK_DEFINE_FIELD(StandardInput, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#StandardOutput="), + SD_VARLINK_DEFINE_FIELD(StandardOutput, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#StandardError="), + SD_VARLINK_DEFINE_FIELD(StandardError, SD_VARLINK_STRING, 0), + SD_VARLINK_FIELD_COMMENT("The file descriptor name to connect standard input to"), + SD_VARLINK_DEFINE_FIELD(StandardInputFileDescriptorName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The file descriptor name to connect standard output to"), + SD_VARLINK_DEFINE_FIELD(StandardOutputFileDescriptorName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The file descriptor name to connect standard error to"), + SD_VARLINK_DEFINE_FIELD(StandardErrorFileDescriptorName, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#StandardInputText="), + SD_VARLINK_DEFINE_FIELD(StandardInputData, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LogLevelMax="), + SD_VARLINK_DEFINE_FIELD(LogLevelMax, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LogExtraFields="), + SD_VARLINK_DEFINE_FIELD(LogExtraFields, SD_VARLINK_STRING, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LogRateLimitIntervalSec="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LogRateLimit, RateLimit, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LogFilterPatterns="), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LogFilterPatterns, LogFilterPattern, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LogNamespace="), + SD_VARLINK_DEFINE_FIELD(LogNamespace, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SyslogIdentifier="), + SD_VARLINK_DEFINE_FIELD(SyslogIdentifier, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SyslogFacility="), + SD_VARLINK_DEFINE_FIELD(SyslogFacility, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SyslogLevel="), + SD_VARLINK_DEFINE_FIELD(SyslogLevel, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SyslogLevelPrefix="), + SD_VARLINK_DEFINE_FIELD(SyslogLevelPrefix, SD_VARLINK_BOOL, 0), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TTYPath="), + SD_VARLINK_DEFINE_FIELD(TTYPath, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TTYReset="), + SD_VARLINK_DEFINE_FIELD(TTYReset, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TTYVHangup="), + SD_VARLINK_DEFINE_FIELD(TTYVHangup, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TTYRows="), + SD_VARLINK_DEFINE_FIELD(TTYRows, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TTYRows="), + SD_VARLINK_DEFINE_FIELD(TTYColumns, SD_VARLINK_INT, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#TTYVTDisallocate="), + SD_VARLINK_DEFINE_FIELD(TTYVTDisallocate, SD_VARLINK_BOOL, SD_VARLINK_NULLABLE), + + /* Credentials + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#Credentials */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LoadCredential=ID:PATH"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LoadCredential, LoadCredential, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#LoadCredential=ID:PATH"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(LoadCredentialEncrypted, LoadCredential, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#ImportCredential=GLOB"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(ImportCredential, ImportCredential, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SetCredential=ID:VALUE"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SetCredential, SetCredential, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#SetCredential=ID:VALUE"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(SetCredentialEncrypted, SetCredential, SD_VARLINK_ARRAY|SD_VARLINK_NULLABLE), + + /* System V Compatibility + * https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#System%20V%20Compatibility */ + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#UtmpIdentifier="), + SD_VARLINK_DEFINE_FIELD(UtmpIdentifier, SD_VARLINK_STRING, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("https://www.freedesktop.org/software/systemd/man"PROJECT_VERSION_STR"systemd.exec.html#UtmpMode="), + SD_VARLINK_DEFINE_FIELD(UtmpMode, SD_VARLINK_STRING, 0)); + +/* UnitContext */ static SD_VARLINK_DEFINE_STRUCT_TYPE( Condition, SD_VARLINK_FIELD_COMMENT("The condition type"), @@ -388,8 +868,12 @@ static SD_VARLINK_DEFINE_STRUCT_TYPE( SD_VARLINK_DEFINE_FIELD(Perpetual, SD_VARLINK_BOOL, 0), SD_VARLINK_FIELD_COMMENT("When true, logs about this unit will be at debug level regardless of other log level settings"), SD_VARLINK_DEFINE_FIELD(DebugInvocation, SD_VARLINK_BOOL, 0), + + /* Other contexts */ SD_VARLINK_FIELD_COMMENT("The cgroup context of the unit"), - SD_VARLINK_DEFINE_FIELD_BY_TYPE(CGroup, CGroupContext, SD_VARLINK_NULLABLE)); + SD_VARLINK_DEFINE_FIELD_BY_TYPE(CGroup, CGroupContext, SD_VARLINK_NULLABLE), + SD_VARLINK_FIELD_COMMENT("The exec context of the unit"), + SD_VARLINK_DEFINE_FIELD_BY_TYPE(Exec, ExecContext, SD_VARLINK_NULLABLE)); static SD_VARLINK_DEFINE_STRUCT_TYPE( ActivationDetails, @@ -554,6 +1038,8 @@ SD_VARLINK_DEFINE_INTERFACE( &vl_type_ActivationDetails, SD_VARLINK_SYMBOL_COMMENT("An object for referencing UNIX processes"), &vl_type_ProcessId, + + /* CGroupContext */ &vl_type_CGroupTasksMax, &vl_type_CGroupIODeviceWeight, &vl_type_CGroupIODeviceLimit, @@ -568,5 +1054,34 @@ SD_VARLINK_DEFINE_INTERFACE( &vl_type_CGroupContext, SD_VARLINK_SYMBOL_COMMENT("CGroup runtime of a unit"), &vl_type_CGroupRuntime, + + /* ExecContext */ + &vl_type_WorkingDirectory, + &vl_type_PartitionMountOptions, + &vl_type_BindPath, + &vl_type_MountImage, + &vl_type_ExtensionImage, + &vl_type_SELinuxContext, + &vl_type_AppArmorProfile, + &vl_type_SmackProcessLabel, + &vl_type_ResourceLimit, + &vl_type_ResourceLimitTable, + &vl_type_CPUAffinity, + &vl_type_ExecDirectoryQuota, + &vl_type_ExecDirectoryPath, + &vl_type_ExecDirectory, + &vl_type_TemporaryFilesystem, + &vl_type_AddressFamilyList, + &vl_type_FilesystemList, + &vl_type_SystemCallList, + &vl_type_EnvironmentFile, + &vl_type_LogFilterPattern, + &vl_type_LoadCredential, + &vl_type_ImportCredential, + &vl_type_SetCredential, + SD_VARLINK_SYMBOL_COMMENT("Exec context of a unit"), + &vl_type_ExecContext, + + /* Errors */ SD_VARLINK_SYMBOL_COMMENT("No matching unit found"), &vl_error_NoSuchUnit); diff --git a/src/test/test-secure-bits.c b/src/test/test-secure-bits.c index 37771d0ce8..d217876e2c 100644 --- a/src/test/test-secure-bits.c +++ b/src/test/test-secure-bits.c @@ -15,20 +15,27 @@ static const char * const string_bits[] = { }; TEST(secure_bits_basic) { - _cleanup_free_ char *joined = NULL, *str = NULL; + _cleanup_free_ char *joined = NULL, *str = NULL, *joined_ssv = NULL; + _cleanup_strv_free_ char **ssv = NULL; int r; /* Check if converting each bit from string and back to string yields * the same value */ STRV_FOREACH(bit, string_bits) { _cleanup_free_ char *s = NULL; + _cleanup_strv_free_ char **sv = NULL; r = secure_bits_from_string(*bit); assert_se(r > 0); assert_se(secure_bits_is_valid(r)); + assert_se(secure_bits_to_string_alloc(r, &s) >= 0); printf("%s = 0x%x = %s\n", *bit, (unsigned)r, s); ASSERT_STREQ(*bit, s); + + ASSERT_OK(secure_bits_to_strv(r, &sv)); + ASSERT_EQ(strv_length(sv), (size_t) 1); + ASSERT_STREQ(*bit, sv[0]); } /* Ditto, but with all bits at once */ @@ -41,7 +48,12 @@ TEST(secure_bits_basic) { printf("%s = 0x%x = %s\n", joined, (unsigned)r, str); ASSERT_STREQ(joined, str); + ASSERT_OK(secure_bits_to_strv(r, &ssv)); + joined_ssv = strv_join(ssv, " "); + ASSERT_STREQ(joined, joined_ssv); + str = mfree(str); + ssv = strv_free(ssv); /* Empty string */ assert_se(secure_bits_from_string("") == 0); @@ -51,8 +63,10 @@ TEST(secure_bits_basic) { assert_se(secure_bits_from_string("foo bar baz") == 0); /* Empty secure bits */ - assert_se(secure_bits_to_string_alloc(0, &str) >= 0); - assert_se(isempty(str)); + ASSERT_OK(secure_bits_to_string_alloc(0, &str)); + ASSERT_TRUE(isempty(str)); + ASSERT_OK(secure_bits_to_strv(0, &ssv)); + ASSERT_TRUE(strv_isempty(ssv)); str = mfree(str);