</para></listitem>
</varlistentry>
+ <varlistentry>
+ <term><varname>StateDirectory=</varname></term>
+ <term><varname>CacheDirectory=</varname></term>
+ <term><varname>LogsDirectory=</varname></term>
+ <term><varname>ConfigurationDirectory=</varname></term>
+
+ <listitem><para>Takes a whitespace-separated list of directory names. If set, as similar to
+ <varname>RuntimeDirectory=</varname>, one or more directories including their parents by the specified names
+ will be created below <filename>/var/lib</filename>, <filename>/var/cache</filename>, <filename>/var/log</filename>,
+ or <filename>/etc</filename>, respectively, when the unit is started.
+ Unlike <varname>RuntimeDirectory=</varname>, the directories are not removed when the unit is stopped.
+ The lowest subdirectories will be owned by the user and group specified in <varname>User=</varname>
+ and <varname>Group=</varname>. The options imply <varname>ReadWritePaths=</varname>.
+ </para></listitem>
+ </varlistentry>
+
<varlistentry>
<term><varname>RuntimeDirectoryMode=</varname></term>
+ <term><varname>StateDirectoryMode=</varname></term>
+ <term><varname>CacheDirectoryMode=</varname></term>
+ <term><varname>LogsDirectoryMode=</varname></term>
+ <term><varname>ConfigurationDirectoryMode=</varname></term>
<listitem><para>Specifies the access mode of the directories specified in
- <varname>RuntimeDirectory=</varname> as an octal number. Defaults to
- <constant>0755</constant>. See "Permissions" in
+ <varname>RuntimeDirectory=</varname>, <varname>StateDirectory=</varname>, <varname>CacheDirectory=</varname>,
+ <varname>LogsDirectory=</varname>, or <varname>ConfigurationDirectory=</varname>, respectively, as an octal number.
+ Defaults to <constant>0755</constant>. See "Permissions" in
<citerefentry project='man-pages'><refentrytitle>path_resolution</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for a discussion of the meaning of permission bits.
</para></listitem>
services, so that they cannot be used to circumvent the restrictions of this option. Specifically, it is
recommended to combine this option with <varname>SystemCallArchitectures=native</varname> or similar. If
running in user mode, or in system mode, but without the <constant>CAP_SYS_ADMIN</constant> capability
- (e.g. setting <varname>User=</varname>), <varname>NoNewPrivileges=yes</varname> is implied. </para></listitem>
+ (e.g. setting <varname>User=</varname>), <varname>NoNewPrivileges=yes</varname> is implied.</para></listitem>
</varlistentry>
<varlistentry>
case EXIT_KEYRING:
return "KEYRING";
+
+ case EXIT_STATE_DIRECTORY:
+ return "STATE_DIRECTORY";
+
+ case EXIT_CACHE_DIRECTORY:
+ return "CACHE_DIRECTORY";
+
+ case EXIT_LOGS_DIRECTORY:
+ return "LOGS_DIRECTORY";
+
+ case EXIT_CONFIGURATION_DIRECTORY:
+ return "CONFIGURATION_DIRECTORY";
}
}
EXIT_CHOWN,
EXIT_SMACK_PROCESS_LABEL,
EXIT_KEYRING,
+ EXIT_STATE_DIRECTORY,
+ EXIT_CACHE_DIRECTORY,
+ EXIT_LOGS_DIRECTORY, /* 240 */
+ EXIT_CONFIGURATION_DIRECTORY,
};
typedef enum ExitStatusLevel {
SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RuntimeDirectoryPreserve", "s", property_get_exec_preserve_mode, offsetof(ExecContext, runtime_directory_preserve_mode), SD_BUS_VTABLE_PROPERTY_CONST),
- SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].mode), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME].paths), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DataDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("DataDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("CacheDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].paths), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("LogsDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].paths), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
+ SD_BUS_PROPERTY("ConfigurationDirectory", "as", NULL, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].paths), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("MemoryDenyWriteExecute", "b", bus_property_get_bool, offsetof(ExecContext, memory_deny_write_execute), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictRealtime", "b", bus_property_get_bool, offsetof(ExecContext, restrict_realtime), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RestrictNamespaces", "t", bus_property_get_ulong, offsetof(ExecContext, restrict_namespaces), SD_BUS_VTABLE_PROPERTY_CONST),
return 1;
- } else if (streq(name, "RuntimeDirectoryMode")) {
+ } else if (STR_IN_SET(name, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode")) {
mode_t m;
r = sd_bus_message_read(message, "u", &m);
return r;
if (mode != UNIT_CHECK) {
- c->runtime_directory_mode = m;
+ ExecDirectoryType i;
- unit_write_drop_in_private_format(u, mode, name, "RuntimeDirectoryMode=%040o", m);
+ 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);
}
return 1;
- } else if (streq(name, "RuntimeDirectory")) {
+ } else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
_cleanup_strv_free_ char **l = NULL;
char **p;
STRV_FOREACH(p, l) {
if (!filename_is_valid(*p))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Runtime directory is not valid %s", *p);
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s is not valid %s", name, *p);
}
if (mode != UNIT_CHECK) {
_cleanup_free_ char *joined = NULL;
+ char ***dirs = NULL;
+ ExecDirectoryType i;
+
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
+ if (streq(name, exec_directory_type_to_string(i))) {
+ dirs = &c->directories[i].paths;
+ break;
+ }
+
+ assert(dirs);
if (strv_isempty(l)) {
- c->runtime_directory = strv_free(c->runtime_directory);
+ *dirs = strv_free(*dirs);
unit_write_drop_in_private_format(u, mode, name, "%s=", name);
} else {
- r = strv_extend_strv(&c->runtime_directory, l, true);
+ r = strv_extend_strv(dirs, l, true);
if (r < 0)
return -ENOMEM;
- joined = strv_join_quoted(c->runtime_directory);
+ joined = strv_join_quoted(*dirs);
if (!joined)
return -ENOMEM;
return 0;
}
-static int setup_runtime_directory(
+static int setup_exec_directory(
const ExecContext *context,
const ExecParameters *params,
uid_t uid,
- gid_t gid) {
+ gid_t gid,
+ bool manager_is_system,
+ ExecDirectoryType type,
+ int *exit_status) {
+ static const int exit_status_table[_EXEC_DIRECTORY_MAX] = {
+ [EXEC_DIRECTORY_RUNTIME] = EXIT_RUNTIME_DIRECTORY,
+ [EXEC_DIRECTORY_STATE] = EXIT_STATE_DIRECTORY,
+ [EXEC_DIRECTORY_CACHE] = EXIT_CACHE_DIRECTORY,
+ [EXEC_DIRECTORY_LOGS] = EXIT_LOGS_DIRECTORY,
+ [EXEC_DIRECTORY_CONFIGURATION] = EXIT_CONFIGURATION_DIRECTORY,
+ };
char **rt;
int r;
assert(context);
assert(params);
+ assert(type >= 0 && type < _EXEC_DIRECTORY_MAX);
+ assert(exit_status);
- STRV_FOREACH(rt, context->runtime_directory) {
+ if (!params->prefix[type])
+ return 0;
+
+ if (manager_is_system) {
+ if (!uid_is_valid(uid))
+ uid = 0;
+ if (!gid_is_valid(gid))
+ gid = 0;
+ }
+
+ STRV_FOREACH(rt, context->directories[type].paths) {
_cleanup_free_ char *p;
- p = strjoin(params->runtime_prefix, "/", *rt);
- if (!p)
- return -ENOMEM;
+ p = strjoin(params->prefix[type], "/", *rt);
+ if (!p) {
+ r = -ENOMEM;
+ goto fail;
+ }
r = mkdir_parents_label(p, 0755);
if (r < 0)
- return r;
+ goto fail;
- r = mkdir_p_label(p, context->runtime_directory_mode);
+ r = mkdir_p_label(p, context->directories[type].mode);
if (r < 0)
- return r;
+ goto fail;
- r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid);
+ r = chmod_and_chown(p, context->directories[type].mode, uid, gid);
if (r < 0)
- return r;
+ goto fail;
}
return 0;
+
+fail:
+ *exit_status = exit_status_table[type];
+
+ return r;
}
static int setup_smack(
_cleanup_strv_free_ char **l = NULL;
char **rt;
+ ExecDirectoryType i;
/* Compile the list of writable paths. This is the combination of
* the explicitly configured paths, plus all runtime directories. */
- if (strv_isempty(context->read_write_paths) &&
- strv_isempty(context->runtime_directory)) {
- *ret = NULL; /* NOP if neither is set */
- return 0;
+ if (strv_isempty(context->read_write_paths)) {
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
+ if (!strv_isempty(context->directories[i].paths))
+ break;
+
+ if (i == _EXEC_DIRECTORY_MAX) {
+ *ret = NULL; /* NOP if neither is set */
+ return 0;
+ }
}
l = strv_copy(context->read_write_paths);
if (!l)
return -ENOMEM;
- STRV_FOREACH(rt, context->runtime_directory) {
- char *s;
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++) {
+ if (!params->prefix[i])
+ continue;
- s = strjoin(params->runtime_prefix, "/", *rt);
- if (!s)
- return -ENOMEM;
+ STRV_FOREACH(rt, context->directories[i].paths) {
+ char *s;
- if (strv_consume(&l, s) < 0)
- return -ENOMEM;
+ s = strjoin(params->prefix[i], "/", *rt);
+ if (!s)
+ return -ENOMEM;
+
+ if (strv_consume(&l, s) < 0)
+ return -ENOMEM;
+ }
}
*ret = l;
gid_t gid = GID_INVALID;
int i, r, ngids = 0;
unsigned n_fds;
+ ExecDirectoryType dt;
assert(unit);
assert(command);
}
}
- if (!strv_isempty(context->runtime_directory) && params->runtime_prefix) {
- r = setup_runtime_directory(context, params, uid, gid);
- if (r < 0) {
- *exit_status = EXIT_RUNTIME_DIRECTORY;
+ for (dt = 0; dt < _EXEC_DIRECTORY_MAX; dt++) {
+ r = setup_exec_directory(context, params, uid, gid, MANAGER_IS_SYSTEM(unit->manager), dt, exit_status);
+ if (r < 0)
return r;
- }
}
r = build_environment(
}
void exec_context_init(ExecContext *c) {
+ ExecDirectoryType i;
+
assert(c);
c->umask = 0022;
c->ignore_sigpipe = true;
c->timer_slack_nsec = NSEC_INFINITY;
c->personality = PERSONALITY_INVALID;
- c->runtime_directory_mode = 0755;
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
+ c->directories[i].mode = 0755;
c->capability_bounding_set = CAP_ALL;
c->restrict_namespaces = NAMESPACE_FLAGS_ALL;
}
void exec_context_done(ExecContext *c) {
unsigned l;
+ ExecDirectoryType i;
assert(c);
c->syscall_archs = set_free(c->syscall_archs);
c->address_families = set_free(c->address_families);
- c->runtime_directory = strv_free(c->runtime_directory);
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++)
+ c->directories[i].paths = strv_free(c->directories[i].paths);
}
int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) {
if (!runtime_prefix)
return 0;
- STRV_FOREACH(i, c->runtime_directory) {
+ STRV_FOREACH(i, c->directories[EXEC_DIRECTORY_RUNTIME].paths) {
_cleanup_free_ char *p;
p = strjoin(runtime_prefix, "/", *i);
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
char **e, **d;
unsigned i;
+ ExecDirectoryType dt;
int r;
assert(c);
STRV_FOREACH(e, c->pass_environment)
fprintf(f, "%sPassEnvironment: %s\n", prefix, *e);
- fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode);
-
fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode));
- STRV_FOREACH(d, c->runtime_directory)
- fprintf(f, "%sRuntimeDirectory: %s\n", prefix, *d);
+ for (dt = 0; dt < _EXEC_DIRECTORY_MAX; dt++) {
+ fprintf(f, "%s%sMode: %04o\n", prefix, exec_directory_type_to_string(dt), c->directories[dt].mode);
+
+ STRV_FOREACH(d, c->directories[dt].paths)
+ fprintf(f, "%s%s: %s\n", prefix, exec_directory_type_to_string(dt), *d);
+ }
if (c->nice_set)
fprintf(f,
};
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES);
+
+static const char* const exec_directory_type_table[_EXEC_DIRECTORY_MAX] = {
+ [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
+ [EXEC_DIRECTORY_STATE] = "StateDirectory",
+ [EXEC_DIRECTORY_CACHE] = "CacheDirectory",
+ [EXEC_DIRECTORY_LOGS] = "LogsDirectory",
+ [EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
+};
+
+DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
int netns_storage_socket[2];
};
+typedef enum ExecDirectoryType {
+ EXEC_DIRECTORY_RUNTIME = 0,
+ EXEC_DIRECTORY_STATE,
+ EXEC_DIRECTORY_CACHE,
+ EXEC_DIRECTORY_LOGS,
+ EXEC_DIRECTORY_CONFIGURATION,
+ _EXEC_DIRECTORY_MAX,
+ _EXEC_DIRECTORY_INVALID = -1,
+} ExecDirectoryType;
+
+typedef struct ExecDirectory {
+ char **paths;
+ mode_t mode;
+} ExecDirectory;
+
struct ExecContext {
char **environment;
char **environment_files;
Set *address_families;
bool address_families_whitelist:1;
- char **runtime_directory;
- mode_t runtime_directory_mode;
ExecPreserveMode runtime_directory_preserve_mode;
+ ExecDirectory directories[_EXEC_DIRECTORY_MAX];
bool memory_deny_write_execute;
bool restrict_realtime;
CGroupMask cgroup_supported;
const char *cgroup_path;
- const char *runtime_prefix;
+ char **prefix;
const char *confirm_spawn;
const char* exec_preserve_mode_to_string(ExecPreserveMode i) _const_;
ExecPreserveMode exec_preserve_mode_from_string(const char *s) _pure_;
+
+const char* exec_directory_type_to_string(ExecDirectoryType i) _const_;
+ExecDirectoryType exec_directory_type_from_string(const char *s) _pure_;
$1.MountFlags, config_parse_exec_mount_flags, 0, offsetof($1, exec_context)
$1.MountAPIVFS, config_parse_bool, 0, offsetof($1, exec_context.mount_apivfs)
$1.Personality, config_parse_personality, 0, offsetof($1, exec_context.personality)
-$1.RuntimeDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.runtime_directory_mode)
$1.RuntimeDirectoryPreserve, config_parse_runtime_preserve_mode, 0, offsetof($1, exec_context.runtime_directory_preserve_mode)
-$1.RuntimeDirectory, config_parse_runtime_directory, 0, offsetof($1, exec_context.runtime_directory)
+$1.RuntimeDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode)
+$1.RuntimeDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_RUNTIME].paths)
+$1.DataDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].mode)
+$1.DataDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_STATE].paths)
+$1.CacheDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].mode)
+$1.CacheDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CACHE].paths)
+$1.LogsDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].mode)
+$1.LogsDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_LOGS].paths)
+$1.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode)
+$1.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof($1, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].paths)
m4_ifdef(`HAVE_PAM',
`$1.PAMName, config_parse_unit_string_printf, 0, offsetof($1, exec_context.pam_name)',
`$1.PAMName, config_parse_warn_compat, DISABLED_CONFIGURATION, 0')
DEFINE_CONFIG_PARSE_ENUM(config_parse_runtime_preserve_mode, exec_preserve_mode, ExecPreserveMode, "Failed to parse runtime directory preserve mode");
-int config_parse_runtime_directory(
+int config_parse_exec_directories(
const char *unit,
const char *filename,
unsigned line,
if (!path_is_safe(k) || path_is_absolute(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0,
- "Runtime directory is not valid, ignoring assignment: %s", rvalue);
+ "%s is not valid, ignoring assignment: %s", lvalue, rvalue);
continue;
}
int config_parse_exec_smack_process_label(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_address_families(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_runtime_preserve_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_runtime_directory(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_exec_directories(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_set_status(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_namespace_path_strv(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
int config_parse_no_new_privileges(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
#include "sd-daemon.h"
#include "sd-messages.h"
+#include "sd-path.h"
#include "alloc-util.h"
#include "audit-fd.h"
#include "dirent-util.h"
#include "env-util.h"
#include "escape.h"
+#include "execute.h"
#include "exec-util.h"
#include "exit-status.h"
#include "fd-util.h"
return 0;
}
+static int manager_setup_prefix(Manager *m) {
+ struct table_entry {
+ uint64_t type;
+ const char *suffix;
+ };
+
+ static const struct table_entry paths_system[_EXEC_DIRECTORY_MAX] = {
+ [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_SYSTEM_RUNTIME, NULL },
+ [EXEC_DIRECTORY_STATE] = { SD_PATH_SYSTEM_STATE_PRIVATE, NULL },
+ [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL },
+ [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_STATE_LOGS, NULL },
+ [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_SYSTEM_CONFIGURATION, NULL },
+ };
+
+ static const struct table_entry paths_user[_EXEC_DIRECTORY_MAX] = {
+ [EXEC_DIRECTORY_RUNTIME] = { SD_PATH_USER_RUNTIME, NULL },
+ [EXEC_DIRECTORY_STATE] = { SD_PATH_USER_CONFIGURATION, NULL },
+ [EXEC_DIRECTORY_CACHE] = { SD_PATH_SYSTEM_STATE_CACHE, NULL },
+ [EXEC_DIRECTORY_LOGS] = { SD_PATH_SYSTEM_CONFIGURATION, "log" },
+ [EXEC_DIRECTORY_CONFIGURATION] = { SD_PATH_SYSTEM_CONFIGURATION, NULL },
+ };
+
+ const struct table_entry *p;
+ ExecDirectoryType i;
+ int r;
+
+ assert(m);
+
+ if (MANAGER_IS_SYSTEM(m))
+ p = paths_system;
+ else
+ p = paths_user;
+
+ for (i = 0; i < _EXEC_DIRECTORY_MAX; i++) {
+ r = sd_path_home(p[i].type, p[i].suffix, &m->prefix[i]);
+ if (r < 0)
+ return r;
+ }
+
+ return 0;
+}
+
int manager_new(UnitFileScope scope, bool test_run, Manager **_m) {
Manager *m;
int r;
m->taint_usr = dir_is_empty("/usr") > 0;
+ r = manager_setup_prefix(m);
+ if (r < 0)
+ goto fail;
+
*_m = m;
return 0;
.sa.sa_family = AF_UNIX,
};
static const int one = 1;
- const char *e;
/* First free all secondary fields */
m->notify_socket = mfree(m->notify_socket);
fd_inc_rcvbuf(fd, NOTIFY_RCVBUF_SIZE);
- e = manager_get_runtime_prefix(m);
- if (!e) {
- log_error("Failed to determine runtime prefix.");
- return -EINVAL;
- }
-
- m->notify_socket = strappend(e, "/systemd/notify");
+ m->notify_socket = strappend(m->prefix[EXEC_DIRECTORY_RUNTIME], "/systemd/notify");
if (!m->notify_socket)
return log_oom();
return hashmap_get(m->units_requiring_mounts_for, streq(p, "/") ? "" : p);
}
-const char *manager_get_runtime_prefix(Manager *m) {
+int manager_set_exec_params(Manager *m, ExecParameters *p) {
assert(m);
+ assert(p);
+
+ p->environment = m->environment;
+ p->confirm_spawn = manager_get_confirm_spawn(m);
+ p->cgroup_supported = m->cgroup_supported;
+ p->prefix = m->prefix;
- return MANAGER_IS_SYSTEM(m) ?
- "/run" :
- getenv("XDG_RUNTIME_DIR");
+ return 0;
}
int manager_update_failed_units(Manager *m, Unit *u, bool failed) {
const char *invocation_log_format_string;
int first_boot; /* tri-state */
+
+ /* prefixes of e.g. RuntimeDirectory= */
+ char *prefix[_EXEC_DIRECTORY_MAX];
};
#define MANAGER_IS_SYSTEM(m) ((m)->unit_file_scope == UNIT_FILE_SYSTEM)
Set *manager_get_units_requiring_mounts_for(Manager *m, const char *path);
-const char *manager_get_runtime_prefix(Manager *m);
+int manager_set_exec_params(Manager *m, ExecParameters *p);
ManagerState manager_state(Manager *m);
if (r < 0)
return r;
- exec_params.environment = UNIT(m)->manager->environment;
- exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(m)->manager);
- exec_params.cgroup_supported = UNIT(m)->manager->cgroup_supported;
+ r = manager_set_exec_params(UNIT(m)->manager, &exec_params);
+ if (r < 0)
+ return r;
+
exec_params.cgroup_path = UNIT(m)->cgroup_path;
exec_params.cgroup_delegate = m->cgroup_context.delegate;
- exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(m)->manager);
r = exec_spawn(UNIT(m),
c,
exec_runtime_destroy(m->exec_runtime);
m->exec_runtime = exec_runtime_unref(m->exec_runtime);
- exec_context_destroy_runtime_directory(&m->exec_context, manager_get_runtime_prefix(UNIT(m)->manager));
+ exec_context_destroy_runtime_directory(&m->exec_context, UNIT(m)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
unit_unref_uid_gid(UNIT(m), true);
}
}
- final_env = strv_env_merge(2, UNIT(s)->manager->environment, our_env, NULL);
+ r = manager_set_exec_params(UNIT(s)->manager, &exec_params);
+ if (r < 0)
+ return r;
+
+ final_env = strv_env_merge(2, exec_params.environment, our_env, NULL);
if (!final_env)
return -ENOMEM;
exec_params.fd_names = fd_names;
exec_params.n_storage_fds = n_storage_fds;
exec_params.n_socket_fds = n_socket_fds;
- exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
- exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
exec_params.cgroup_path = path;
exec_params.cgroup_delegate = s->cgroup_context.delegate;
- exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
exec_params.watchdog_usec = s->watchdog_usec;
exec_params.selinux_context_net = s->socket_fd_selinux_context_net;
if (s->type == SERVICE_IDLE)
if (s->exec_context.runtime_directory_preserve_mode == EXEC_PRESERVE_NO ||
(s->exec_context.runtime_directory_preserve_mode == EXEC_PRESERVE_RESTART && !service_will_restart(s)))
/* Also, remove the runtime directory */
- exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
+ exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
/* Get rid of the IPC bits of the user */
unit_unref_uid_gid(UNIT(s), true);
if (r < 0)
return r;
+ r = manager_set_exec_params(UNIT(s)->manager, &exec_params);
+ if (r < 0)
+ return r;
+
exec_params.argv = c->argv;
- exec_params.environment = UNIT(s)->manager->environment;
- exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
- exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
exec_params.cgroup_path = UNIT(s)->cgroup_path;
exec_params.cgroup_delegate = s->cgroup_context.delegate;
- exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
r = exec_spawn(UNIT(s),
c,
return r;
*_pid = pid;
+
return 0;
}
exec_runtime_destroy(s->exec_runtime);
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
- exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
+ exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
unit_unref_uid_gid(UNIT(s), true);
r = unit_setup_dynamic_creds(UNIT(s));
if (r < 0)
- return r;
+ goto fail;
r = swap_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), s->timeout_usec));
if (r < 0)
goto fail;
- exec_params.environment = UNIT(s)->manager->environment;
- exec_params.confirm_spawn = manager_get_confirm_spawn(UNIT(s)->manager);
- exec_params.cgroup_supported = UNIT(s)->manager->cgroup_supported;
+ r = manager_set_exec_params(UNIT(s)->manager, &exec_params);
+ if (r < 0)
+ goto fail;
+
exec_params.cgroup_path = UNIT(s)->cgroup_path;
exec_params.cgroup_delegate = s->cgroup_context.delegate;
- exec_params.runtime_prefix = manager_get_runtime_prefix(UNIT(s)->manager);
r = exec_spawn(UNIT(s),
c,
fail:
s->timer_event_source = sd_event_source_unref(s->timer_event_source);
+
return r;
}
exec_runtime_destroy(s->exec_runtime);
s->exec_runtime = exec_runtime_unref(s->exec_runtime);
- exec_context_destroy_runtime_directory(&s->exec_context, manager_get_runtime_prefix(UNIT(s)->manager));
+ exec_context_destroy_runtime_directory(&s->exec_context, UNIT(s)->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
unit_unref_uid_gid(UNIT(s), true);
static int specifier_runtime(char specifier, void *data, void *userdata, char **ret) {
Unit *u = userdata;
- const char *e;
char *n = NULL;
assert(u);
- e = manager_get_runtime_prefix(u->manager);
- if (!e)
- return -EOPNOTSUPP;
- n = strdup(e);
+ n = strdup(u->manager->prefix[EXEC_DIRECTORY_RUNTIME]);
if (!n)
return -ENOMEM;
r = sd_bus_message_close_container(m);
- } else if (streq(field, "RuntimeDirectoryMode")) {
+ } else if (STR_IN_SET(field, "RuntimeDirectoryMode", "StateDirectoryMode", "CacheDirectoryMode", "LogsDirectoryMode", "ConfigurationDirectoryMode")) {
mode_t mode;
r = parse_mode(eq, &mode);
r = sd_bus_message_append(m, "v", "u", mode);
- } else if (streq(field, "RuntimeDirectory")) {
+ } else if (STR_IN_SET(field, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");