mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-11 05:17:44 +03:00
core: Add ExecSearchPath parameter to specify the directory relative to which binaries executed by Exec*= should be found
Currently there does not exist a way to specify a path relative to which all binaries executed by Exec should be found. The only way is to specify the absolute path. This change implements the functionality to specify a path relative to which binaries executed by Exec*= can be found. Closes #6308
This commit is contained in:
parent
5b32e48f6e
commit
8c35c10d20
@ -2737,6 +2737,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
|||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly as NoExecPaths = ['...', ...];
|
readonly as NoExecPaths = ['...', ...];
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
|
readonly as ExecSearchPath = ['...', ...];
|
||||||
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t MountFlags = ...;
|
readonly t MountFlags = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly b PrivateTmp = ...;
|
readonly b PrivateTmp = ...;
|
||||||
@ -3260,6 +3262,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
|||||||
|
|
||||||
<!--property NoExecPaths is not documented!-->
|
<!--property NoExecPaths is not documented!-->
|
||||||
|
|
||||||
|
<!--property ExecSearchPath is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateTmp is not documented!-->
|
<!--property PrivateTmp is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateDevices is not documented!-->
|
<!--property PrivateDevices is not documented!-->
|
||||||
@ -3858,6 +3862,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
|
|||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
||||||
@ -4567,6 +4573,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
|||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly as NoExecPaths = ['...', ...];
|
readonly as NoExecPaths = ['...', ...];
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
|
readonly as ExecSearchPath = ['...', ...];
|
||||||
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t MountFlags = ...;
|
readonly t MountFlags = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly b PrivateTmp = ...;
|
readonly b PrivateTmp = ...;
|
||||||
@ -5118,6 +5126,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
|||||||
|
|
||||||
<!--property NoExecPaths is not documented!-->
|
<!--property NoExecPaths is not documented!-->
|
||||||
|
|
||||||
|
<!--property ExecSearchPath is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateTmp is not documented!-->
|
<!--property PrivateTmp is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateDevices is not documented!-->
|
<!--property PrivateDevices is not documented!-->
|
||||||
@ -5714,6 +5724,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
|
|||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
||||||
@ -6320,6 +6332,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
|||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly as NoExecPaths = ['...', ...];
|
readonly as NoExecPaths = ['...', ...];
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
|
readonly as ExecSearchPath = ['...', ...];
|
||||||
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t MountFlags = ...;
|
readonly t MountFlags = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly b PrivateTmp = ...;
|
readonly b PrivateTmp = ...;
|
||||||
@ -6799,6 +6813,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
|||||||
|
|
||||||
<!--property NoExecPaths is not documented!-->
|
<!--property NoExecPaths is not documented!-->
|
||||||
|
|
||||||
|
<!--property ExecSearchPath is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateTmp is not documented!-->
|
<!--property PrivateTmp is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateDevices is not documented!-->
|
<!--property PrivateDevices is not documented!-->
|
||||||
@ -7313,6 +7329,8 @@ node /org/freedesktop/systemd1/unit/home_2emount {
|
|||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
||||||
@ -8040,6 +8058,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
|||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly as NoExecPaths = ['...', ...];
|
readonly as NoExecPaths = ['...', ...];
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
|
readonly as ExecSearchPath = ['...', ...];
|
||||||
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly t MountFlags = ...;
|
readonly t MountFlags = ...;
|
||||||
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
|
||||||
readonly b PrivateTmp = ...;
|
readonly b PrivateTmp = ...;
|
||||||
@ -8505,6 +8525,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
|||||||
|
|
||||||
<!--property NoExecPaths is not documented!-->
|
<!--property NoExecPaths is not documented!-->
|
||||||
|
|
||||||
|
<!--property ExecSearchPath is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateTmp is not documented!-->
|
<!--property PrivateTmp is not documented!-->
|
||||||
|
|
||||||
<!--property PrivateDevices is not documented!-->
|
<!--property PrivateDevices is not documented!-->
|
||||||
@ -9005,6 +9027,8 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
|
|||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="NoExecPaths"/>
|
||||||
|
|
||||||
|
<variablelist class="dbus-property" generated="True" extra-ref="ExecSearchPath"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="MountFlags"/>
|
||||||
|
|
||||||
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
<variablelist class="dbus-property" generated="True" extra-ref="PrivateTmp"/>
|
||||||
|
@ -89,6 +89,20 @@
|
|||||||
|
|
||||||
<variablelist class='unit-directives'>
|
<variablelist class='unit-directives'>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><varname>ExecSearchPath=</varname></term>
|
||||||
|
|
||||||
|
<listitem><para>Takes a colon separated list of absolute paths relative to which the executable
|
||||||
|
used by the <varname>Exec*=</varname> (e.g. <varname>ExecStart=</varname>,
|
||||||
|
<varname>ExecStop=</varname>, etc.) properties can be found. <varname>ExecSearchPath=</varname>
|
||||||
|
overrides <varname>$PATH</varname> if <varname>$PATH</varname> is not supplied by the user through
|
||||||
|
<varname>Environment=</varname>, <varname>EnvironmentFile=</varname> or
|
||||||
|
<varname>PassEnvironment=</varname>. Assigning an empty string removes previous assignments
|
||||||
|
and setting <varname>ExecSearchPath=</varname> to a value multiple times will append
|
||||||
|
to the previous setting.
|
||||||
|
</para></listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><varname>WorkingDirectory=</varname></term>
|
<term><varname>WorkingDirectory=</varname></term>
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ int verify_executable(Unit *u, const ExecCommand *exec, const char *root) {
|
|||||||
if (exec->flags & EXEC_COMMAND_IGNORE_FAILURE)
|
if (exec->flags & EXEC_COMMAND_IGNORE_FAILURE)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
r = find_executable_full(exec->path, root, false, NULL, NULL);
|
r = find_executable_full(exec->path, root, NULL, false, NULL, NULL);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_unit_error_errno(u, r, "Command %s is not executable: %m", exec->path);
|
return log_unit_error_errno(u, r, "Command %s is not executable: %m", exec->path);
|
||||||
|
|
||||||
|
@ -682,8 +682,8 @@ static int find_executable_impl(const char *name, const char *root, char **ret_f
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_executable_full(const char *name, const char *root, bool use_path_envvar, char **ret_filename, int *ret_fd) {
|
int find_executable_full(const char *name, const char *root, char **exec_search_path, bool use_path_envvar, char **ret_filename, int *ret_fd) {
|
||||||
int last_error, r;
|
int last_error = -ENOENT, r = 0;
|
||||||
const char *p = NULL;
|
const char *p = NULL;
|
||||||
|
|
||||||
assert(name);
|
assert(name);
|
||||||
@ -698,7 +698,27 @@ int find_executable_full(const char *name, const char *root, bool use_path_envva
|
|||||||
if (!p)
|
if (!p)
|
||||||
p = DEFAULT_PATH;
|
p = DEFAULT_PATH;
|
||||||
|
|
||||||
last_error = -ENOENT;
|
if (exec_search_path) {
|
||||||
|
char **element;
|
||||||
|
|
||||||
|
STRV_FOREACH(element, exec_search_path) {
|
||||||
|
_cleanup_free_ char *full_path = NULL;
|
||||||
|
if (!path_is_absolute(*element))
|
||||||
|
continue;
|
||||||
|
full_path = path_join(*element, name);
|
||||||
|
if (!full_path)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
r = find_executable_impl(full_path, root, ret_filename, ret_fd);
|
||||||
|
if (r < 0) {
|
||||||
|
if (r != -EACCES)
|
||||||
|
last_error = r;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return last_error;
|
||||||
|
}
|
||||||
|
|
||||||
/* Resolve a single-component name to a full path */
|
/* Resolve a single-component name to a full path */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -99,9 +99,9 @@ int path_strv_make_absolute_cwd(char **l);
|
|||||||
char** path_strv_resolve(char **l, const char *root);
|
char** path_strv_resolve(char **l, const char *root);
|
||||||
char** path_strv_resolve_uniq(char **l, const char *root);
|
char** path_strv_resolve_uniq(char **l, const char *root);
|
||||||
|
|
||||||
int find_executable_full(const char *name, const char *root, bool use_path_envvar, char **ret_filename, int *ret_fd);
|
int find_executable_full(const char *name, const char *root, char **exec_search_path, bool use_path_envvar, char **ret_filename, int *ret_fd);
|
||||||
static inline int find_executable(const char *name, char **ret_filename) {
|
static inline int find_executable(const char *name, char **ret_filename) {
|
||||||
return find_executable_full(name, /* root= */ NULL, true, ret_filename, NULL);
|
return find_executable_full(name, /* root= */ NULL, NULL, true, ret_filename, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
|
bool paths_check_timestamp(const char* const* paths, usec_t *paths_ts_usec, bool update);
|
||||||
|
@ -1161,6 +1161,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
|
|||||||
SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("InaccessiblePaths", "as", NULL, offsetof(ExecContext, inaccessible_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("ExecPaths", "as", NULL, offsetof(ExecContext, exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("ExecPaths", "as", NULL, offsetof(ExecContext, exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("NoExecPaths", "as", NULL, offsetof(ExecContext, no_exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("NoExecPaths", "as", NULL, offsetof(ExecContext, no_exec_paths), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
|
SD_BUS_PROPERTY("ExecSearchPath", "as", NULL, offsetof(ExecContext, exec_search_path), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
|
SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||||
@ -3140,6 +3141,36 @@ int bus_exec_context_set_transient_property(
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
} else if (streq(name, "ExecSearchPath")) {
|
||||||
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
|
char **p;
|
||||||
|
|
||||||
|
r = sd_bus_message_read_strv(message, &l);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
STRV_FOREACH(p, l) {
|
||||||
|
if (!path_is_absolute(*p) || !path_is_normalized(*p) || strchr(*p, ':'))
|
||||||
|
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
|
||||||
|
}
|
||||||
|
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||||
|
if (strv_isempty(l)) {
|
||||||
|
c->exec_search_path = strv_free(c->exec_search_path);
|
||||||
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ExecSearchPath=");
|
||||||
|
} else {
|
||||||
|
_cleanup_free_ char *joined = NULL;
|
||||||
|
r = strv_extend_strv(&c->exec_search_path, l, true);
|
||||||
|
if (r < 0)
|
||||||
|
return -ENOMEM;
|
||||||
|
joined = strv_join(c->exec_search_path, ":");
|
||||||
|
if (!joined)
|
||||||
|
return log_oom();
|
||||||
|
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ExecSearchPath=%s", joined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
|
||||||
} else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
|
} else if (STR_IN_SET(name, "RuntimeDirectory", "StateDirectory", "CacheDirectory", "LogsDirectory", "ConfigurationDirectory")) {
|
||||||
_cleanup_strv_free_ char **l = NULL;
|
_cleanup_strv_free_ char **l = NULL;
|
||||||
char **p;
|
char **p;
|
||||||
|
@ -3742,7 +3742,7 @@ static int exec_child(
|
|||||||
int user_lookup_fd,
|
int user_lookup_fd,
|
||||||
int *exit_status) {
|
int *exit_status) {
|
||||||
|
|
||||||
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **replaced_argv = NULL;
|
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **joined_exec_search_path = NULL, **accum_env = NULL, **replaced_argv = NULL;
|
||||||
int r, ngids = 0, exec_fd;
|
int r, ngids = 0, exec_fd;
|
||||||
_cleanup_free_ gid_t *supplementary_gids = NULL;
|
_cleanup_free_ gid_t *supplementary_gids = NULL;
|
||||||
const char *username = NULL, *groupname = NULL;
|
const char *username = NULL, *groupname = NULL;
|
||||||
@ -4158,8 +4158,31 @@ static int exec_child(
|
|||||||
return log_oom();
|
return log_oom();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The PATH variable is set to the default path in params->environment.
|
||||||
|
* However, this is overridden if user specified fields have PATH set.
|
||||||
|
* The intention is to also override PATH if the user does
|
||||||
|
* not specify PATH and the user has specified ExecSearchPath
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!strv_isempty(context->exec_search_path)) {
|
||||||
|
_cleanup_free_ char *joined = NULL;
|
||||||
|
|
||||||
|
joined = strv_join(context->exec_search_path, ":");
|
||||||
|
if (!joined) {
|
||||||
|
*exit_status = EXIT_MEMORY;
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
r = strv_env_assign(&joined_exec_search_path, "PATH", joined);
|
||||||
|
if (r < 0) {
|
||||||
|
*exit_status = EXIT_MEMORY;
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
accum_env = strv_env_merge(params->environment,
|
accum_env = strv_env_merge(params->environment,
|
||||||
our_env,
|
our_env,
|
||||||
|
joined_exec_search_path,
|
||||||
pass_env,
|
pass_env,
|
||||||
context->environment,
|
context->environment,
|
||||||
files_env);
|
files_env);
|
||||||
@ -4350,7 +4373,7 @@ static int exec_child(
|
|||||||
|
|
||||||
_cleanup_free_ char *executable = NULL;
|
_cleanup_free_ char *executable = NULL;
|
||||||
_cleanup_close_ int executable_fd = -1;
|
_cleanup_close_ int executable_fd = -1;
|
||||||
r = find_executable_full(command->path, /* root= */ NULL, false, &executable, &executable_fd);
|
r = find_executable_full(command->path, /* root= */ NULL, context->exec_search_path, false, &executable, &executable_fd);
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
|
if (r != -ENOMEM && (command->flags & EXEC_COMMAND_IGNORE_FAILURE)) {
|
||||||
log_unit_struct_errno(unit, LOG_INFO, r,
|
log_unit_struct_errno(unit, LOG_INFO, r,
|
||||||
@ -4926,6 +4949,7 @@ void exec_context_done(ExecContext *c) {
|
|||||||
c->inaccessible_paths = strv_free(c->inaccessible_paths);
|
c->inaccessible_paths = strv_free(c->inaccessible_paths);
|
||||||
c->exec_paths = strv_free(c->exec_paths);
|
c->exec_paths = strv_free(c->exec_paths);
|
||||||
c->no_exec_paths = strv_free(c->no_exec_paths);
|
c->no_exec_paths = strv_free(c->no_exec_paths);
|
||||||
|
c->exec_search_path = strv_free(c->exec_search_path);
|
||||||
|
|
||||||
bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
|
bind_mount_free_many(c->bind_mounts, c->n_bind_mounts);
|
||||||
c->bind_mounts = NULL;
|
c->bind_mounts = NULL;
|
||||||
@ -5597,6 +5621,7 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
|
|||||||
strv_dump(f, prefix, "InaccessiblePaths", c->inaccessible_paths);
|
strv_dump(f, prefix, "InaccessiblePaths", c->inaccessible_paths);
|
||||||
strv_dump(f, prefix, "ExecPaths", c->exec_paths);
|
strv_dump(f, prefix, "ExecPaths", c->exec_paths);
|
||||||
strv_dump(f, prefix, "NoExecPaths", c->no_exec_paths);
|
strv_dump(f, prefix, "NoExecPaths", c->no_exec_paths);
|
||||||
|
strv_dump(f, prefix, "ExecSearchPath", c->exec_search_path);
|
||||||
|
|
||||||
for (size_t i = 0; i < c->n_bind_mounts; i++)
|
for (size_t i = 0; i < c->n_bind_mounts; i++)
|
||||||
fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
|
fprintf(f, "%s%s: %s%s:%s:%s\n", prefix,
|
||||||
|
@ -254,6 +254,7 @@ struct ExecContext {
|
|||||||
char *smack_process_label;
|
char *smack_process_label;
|
||||||
|
|
||||||
char **read_write_paths, **read_only_paths, **inaccessible_paths, **exec_paths, **no_exec_paths;
|
char **read_write_paths, **read_only_paths, **inaccessible_paths, **exec_paths, **no_exec_paths;
|
||||||
|
char **exec_search_path;
|
||||||
unsigned long mount_flags;
|
unsigned long mount_flags;
|
||||||
BindMount *bind_mounts;
|
BindMount *bind_mounts;
|
||||||
size_t n_bind_mounts;
|
size_t n_bind_mounts;
|
||||||
|
@ -105,6 +105,7 @@
|
|||||||
{{type}}.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.inaccessible_paths)
|
{{type}}.InaccessiblePaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.inaccessible_paths)
|
||||||
{{type}}.ExecPaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.exec_paths)
|
{{type}}.ExecPaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.exec_paths)
|
||||||
{{type}}.NoExecPaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.no_exec_paths)
|
{{type}}.NoExecPaths, config_parse_namespace_path_strv, 0, offsetof({{type}}, exec_context.no_exec_paths)
|
||||||
|
{{type}}.ExecSearchPath, config_parse_colon_separated_paths, 0, offsetof({{type}}, exec_context.exec_search_path)
|
||||||
{{type}}.BindPaths, config_parse_bind_paths, 0, offsetof({{type}}, exec_context)
|
{{type}}.BindPaths, config_parse_bind_paths, 0, offsetof({{type}}, exec_context)
|
||||||
{{type}}.BindReadOnlyPaths, config_parse_bind_paths, 0, offsetof({{type}}, exec_context)
|
{{type}}.BindReadOnlyPaths, config_parse_bind_paths, 0, offsetof({{type}}, exec_context)
|
||||||
{{type}}.TemporaryFileSystem, config_parse_temporary_filesystems, 0, offsetof({{type}}, exec_context)
|
{{type}}.TemporaryFileSystem, config_parse_temporary_filesystems, 0, offsetof({{type}}, exec_context)
|
||||||
|
@ -305,6 +305,64 @@ int config_parse_unit_path_printf(
|
|||||||
return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
|
return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int config_parse_colon_separated_paths(
|
||||||
|
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) {
|
||||||
|
char ***sv = data;
|
||||||
|
const Unit *u = userdata;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert(filename);
|
||||||
|
assert(lvalue);
|
||||||
|
assert(rvalue);
|
||||||
|
assert(data);
|
||||||
|
|
||||||
|
if (isempty(rvalue)) {
|
||||||
|
/* Empty assignment resets the list */
|
||||||
|
*sv = strv_free(*sv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const char *p = rvalue;;) {
|
||||||
|
_cleanup_free_ char *word = NULL, *k = NULL;
|
||||||
|
|
||||||
|
r = extract_first_word(&p, &word, ":", EXTRACT_DONT_COALESCE_SEPARATORS);
|
||||||
|
if (r == -ENOMEM)
|
||||||
|
return log_oom();
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to extract first word, ignoring: %s", rvalue);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (r == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
r = unit_path_printf(u, word, &k);
|
||||||
|
if (r < 0) {
|
||||||
|
log_syntax(unit, LOG_WARNING, filename, line, r,
|
||||||
|
"Failed to resolve unit specifiers in '%s', ignoring: %m", word);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE, unit, filename, line, lvalue);
|
||||||
|
if (r < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
r = strv_consume(sv, TAKE_PTR(k));
|
||||||
|
if (r < 0)
|
||||||
|
return log_oom();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int config_parse_unit_path_strv_printf(
|
int config_parse_unit_path_strv_printf(
|
||||||
const char *unit,
|
const char *unit,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
@ -5915,6 +5973,7 @@ void unit_dump_config_items(FILE *f) {
|
|||||||
{ config_parse_string, "STRING" },
|
{ config_parse_string, "STRING" },
|
||||||
{ config_parse_path, "PATH" },
|
{ config_parse_path, "PATH" },
|
||||||
{ config_parse_unit_path_printf, "PATH" },
|
{ config_parse_unit_path_printf, "PATH" },
|
||||||
|
{ config_parse_colon_separated_paths, "PATH" },
|
||||||
{ config_parse_strv, "STRING [...]" },
|
{ config_parse_strv, "STRING [...]" },
|
||||||
{ config_parse_exec_nice, "NICE" },
|
{ config_parse_exec_nice, "NICE" },
|
||||||
{ config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
|
{ config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
|
||||||
|
@ -19,6 +19,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_obsolete_unit_deps);
|
|||||||
CONFIG_PARSER_PROTOTYPE(config_parse_unit_string_printf);
|
CONFIG_PARSER_PROTOTYPE(config_parse_unit_string_printf);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_unit_strv_printf);
|
CONFIG_PARSER_PROTOTYPE(config_parse_unit_strv_printf);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_printf);
|
CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_printf);
|
||||||
|
CONFIG_PARSER_PROTOTYPE(config_parse_colon_separated_paths);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_strv_printf);
|
CONFIG_PARSER_PROTOTYPE(config_parse_unit_path_strv_printf);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_documentation);
|
CONFIG_PARSER_PROTOTYPE(config_parse_documentation);
|
||||||
CONFIG_PARSER_PROTOTYPE(config_parse_socket_listen);
|
CONFIG_PARSER_PROTOTYPE(config_parse_socket_listen);
|
||||||
|
@ -1714,6 +1714,7 @@ static int run(int argc, char* argv[]) {
|
|||||||
if (!strv_isempty(arg_cmdline) &&
|
if (!strv_isempty(arg_cmdline) &&
|
||||||
arg_transport == BUS_TRANSPORT_LOCAL &&
|
arg_transport == BUS_TRANSPORT_LOCAL &&
|
||||||
!strv_find_startswith(arg_property, "RootDirectory=") &&
|
!strv_find_startswith(arg_property, "RootDirectory=") &&
|
||||||
|
!strv_find_startswith(arg_property, "ExecSearchPath=") &&
|
||||||
!strv_find_startswith(arg_property, "RootImage=")) {
|
!strv_find_startswith(arg_property, "RootImage=")) {
|
||||||
/* Patch in an absolute path to fail early for user convenience, but only when we can do it
|
/* Patch in an absolute path to fail early for user convenience, but only when we can do it
|
||||||
* (i.e. we will be running from the same file system). This also uses the user's $PATH,
|
* (i.e. we will be running from the same file system). This also uses the user's $PATH,
|
||||||
|
@ -969,6 +969,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
|
|||||||
"InaccessiblePaths",
|
"InaccessiblePaths",
|
||||||
"ExecPaths",
|
"ExecPaths",
|
||||||
"NoExecPaths",
|
"NoExecPaths",
|
||||||
|
"ExecSearchPath",
|
||||||
"RuntimeDirectory",
|
"RuntimeDirectory",
|
||||||
"StateDirectory",
|
"StateDirectory",
|
||||||
"CacheDirectory",
|
"CacheDirectory",
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include "capability-util.h"
|
#include "capability-util.h"
|
||||||
#include "cpu-set-util.h"
|
#include "cpu-set-util.h"
|
||||||
|
#include "copy.h"
|
||||||
#include "dropin.h"
|
#include "dropin.h"
|
||||||
#include "errno-list.h"
|
#include "errno-list.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
@ -28,6 +29,7 @@
|
|||||||
#include "static-destruct.h"
|
#include "static-destruct.h"
|
||||||
#include "stat-util.h"
|
#include "stat-util.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
#include "tmpfile-util.h"
|
||||||
#include "unit.h"
|
#include "unit.h"
|
||||||
#include "user-util.h"
|
#include "user-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@ -273,6 +275,93 @@ static void test_exec_workingdirectory(Manager *m) {
|
|||||||
(void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
|
(void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_exec_execsearchpath(Manager *m) {
|
||||||
|
assert_se(mkdir_p("/tmp/test-exec_execsearchpath", 0755) >= 0);
|
||||||
|
|
||||||
|
assert_se(copy_file("/bin/ls", "/tmp/test-exec_execsearchpath/ls_temp", 0, 0777, 0, 0, COPY_REPLACE) >= 0);
|
||||||
|
|
||||||
|
test(m, "exec-execsearchpath.service", 0, CLD_EXITED);
|
||||||
|
|
||||||
|
assert_se(rm_rf("/tmp/test-exec_execsearchpath", REMOVE_ROOT|REMOVE_PHYSICAL) >= 0);
|
||||||
|
|
||||||
|
test(m, "exec-execsearchpath.service", EXIT_EXEC, CLD_EXITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_exec_execsearchpath_specifier(Manager *m) {
|
||||||
|
test(m, "exec-execsearchpath-unit-specifier.service", 0, CLD_EXITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_exec_execsearchpath_environment(Manager *m) {
|
||||||
|
test(m, "exec-execsearchpath-environment.service", 0, CLD_EXITED);
|
||||||
|
test(m, "exec-execsearchpath-environment-path-set.service", 0, CLD_EXITED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_exec_execsearchpath_environment_files(Manager *m) {
|
||||||
|
static const char path_not_set[] =
|
||||||
|
"VAR1='word1 word2'\n"
|
||||||
|
"VAR2=word3 \n"
|
||||||
|
"# comment1\n"
|
||||||
|
"\n"
|
||||||
|
"; comment2\n"
|
||||||
|
" ; # comment3\n"
|
||||||
|
"line without an equal\n"
|
||||||
|
"VAR3='$word 5 6'\n"
|
||||||
|
"VAR4='new\nline'\n"
|
||||||
|
"VAR5=password\\with\\backslashes";
|
||||||
|
|
||||||
|
static const char path_set[] =
|
||||||
|
"VAR1='word1 word2'\n"
|
||||||
|
"VAR2=word3 \n"
|
||||||
|
"# comment1\n"
|
||||||
|
"\n"
|
||||||
|
"; comment2\n"
|
||||||
|
" ; # comment3\n"
|
||||||
|
"line without an equal\n"
|
||||||
|
"VAR3='$word 5 6'\n"
|
||||||
|
"VAR4='new\nline'\n"
|
||||||
|
"VAR5=password\\with\\backslashes\n"
|
||||||
|
"PATH=/usr";
|
||||||
|
|
||||||
|
int r;
|
||||||
|
|
||||||
|
r = write_string_file("/tmp/test-exec_execsearchpath_environmentfile.conf", path_not_set, WRITE_STRING_FILE_CREATE);
|
||||||
|
|
||||||
|
assert_se(r == 0);
|
||||||
|
|
||||||
|
test(m, "exec-execsearchpath-environmentfile.service", 0, CLD_EXITED);
|
||||||
|
|
||||||
|
(void) unlink("/tmp/test-exec_environmentfile.conf");
|
||||||
|
|
||||||
|
|
||||||
|
r = write_string_file("/tmp/test-exec_execsearchpath_environmentfile-set.conf", path_set, WRITE_STRING_FILE_CREATE);
|
||||||
|
|
||||||
|
assert_se(r == 0);
|
||||||
|
|
||||||
|
test(m, "exec-execsearchpath-environmentfile-set.service", 0, CLD_EXITED);
|
||||||
|
|
||||||
|
(void) unlink("/tmp/test-exec_environmentfile-set.conf");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_exec_execsearchpath_passenvironment(Manager *m) {
|
||||||
|
assert_se(setenv("VAR1", "word1 word2", 1) == 0);
|
||||||
|
assert_se(setenv("VAR2", "word3", 1) == 0);
|
||||||
|
assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
|
||||||
|
assert_se(setenv("VAR4", "new\nline", 1) == 0);
|
||||||
|
assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
|
||||||
|
|
||||||
|
test(m, "exec-execsearchpath-passenvironment.service", 0, CLD_EXITED);
|
||||||
|
|
||||||
|
assert_se(setenv("PATH", "/usr", 1) == 0);
|
||||||
|
test(m, "exec-execsearchpath-passenvironment-set.service", 0, CLD_EXITED);
|
||||||
|
|
||||||
|
assert_se(unsetenv("VAR1") == 0);
|
||||||
|
assert_se(unsetenv("VAR2") == 0);
|
||||||
|
assert_se(unsetenv("VAR3") == 0);
|
||||||
|
assert_se(unsetenv("VAR4") == 0);
|
||||||
|
assert_se(unsetenv("VAR5") == 0);
|
||||||
|
assert_se(unsetenv("PATH") == 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_exec_personality(Manager *m) {
|
static void test_exec_personality(Manager *m) {
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
|
test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
|
||||||
@ -1089,11 +1178,16 @@ int main(int argc, char *argv[]) {
|
|||||||
entry(test_exec_unsetenvironment),
|
entry(test_exec_unsetenvironment),
|
||||||
entry(test_exec_user),
|
entry(test_exec_user),
|
||||||
entry(test_exec_workingdirectory),
|
entry(test_exec_workingdirectory),
|
||||||
|
entry(test_exec_execsearchpath),
|
||||||
|
entry(test_exec_execsearchpath_environment),
|
||||||
|
entry(test_exec_execsearchpath_environment_files),
|
||||||
|
entry(test_exec_execsearchpath_passenvironment),
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
static const test_entry system_tests[] = {
|
static const test_entry system_tests[] = {
|
||||||
entry(test_exec_dynamicuser),
|
entry(test_exec_dynamicuser),
|
||||||
entry(test_exec_specifier),
|
entry(test_exec_specifier),
|
||||||
|
entry(test_exec_execsearchpath_specifier),
|
||||||
entry(test_exec_systemcallfilter_system),
|
entry(test_exec_systemcallfilter_system),
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "alloc-util.h"
|
#include "alloc-util.h"
|
||||||
#include "exec-util.h"
|
#include "exec-util.h"
|
||||||
#include "fd-util.h"
|
#include "fd-util.h"
|
||||||
|
#include "fs-util.h"
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
#include "path-util.h"
|
#include "path-util.h"
|
||||||
#include "process-util.h"
|
#include "process-util.h"
|
||||||
@ -14,6 +15,7 @@
|
|||||||
#include "string-util.h"
|
#include "string-util.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "tests.h"
|
#include "tests.h"
|
||||||
|
#include "tmpfile-util.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
static void test_print_paths(void) {
|
static void test_print_paths(void) {
|
||||||
@ -201,15 +203,18 @@ static void test_path_equal_root(void) {
|
|||||||
|
|
||||||
static void test_find_executable_full(void) {
|
static void test_find_executable_full(void) {
|
||||||
char *p;
|
char *p;
|
||||||
|
char* test_file_name;
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
char fn[] = "/tmp/test-XXXXXX";
|
||||||
|
|
||||||
log_info("/* %s */", __func__);
|
log_info("/* %s */", __func__);
|
||||||
|
|
||||||
assert_se(find_executable_full("sh", NULL, true, &p, NULL) == 0);
|
assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0);
|
||||||
puts(p);
|
puts(p);
|
||||||
assert_se(streq(basename(p), "sh"));
|
assert_se(streq(basename(p), "sh"));
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
assert_se(find_executable_full("sh", NULL, false, &p, NULL) == 0);
|
assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0);
|
||||||
puts(p);
|
puts(p);
|
||||||
assert_se(streq(basename(p), "sh"));
|
assert_se(streq(basename(p), "sh"));
|
||||||
free(p);
|
free(p);
|
||||||
@ -221,18 +226,31 @@ static void test_find_executable_full(void) {
|
|||||||
|
|
||||||
assert_se(unsetenv("PATH") == 0);
|
assert_se(unsetenv("PATH") == 0);
|
||||||
|
|
||||||
assert_se(find_executable_full("sh", NULL, true, &p, NULL) == 0);
|
assert_se(find_executable_full("sh", NULL, NULL, true, &p, NULL) == 0);
|
||||||
puts(p);
|
puts(p);
|
||||||
assert_se(streq(basename(p), "sh"));
|
assert_se(streq(basename(p), "sh"));
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
assert_se(find_executable_full("sh", NULL, false, &p, NULL) == 0);
|
assert_se(find_executable_full("sh", NULL, NULL, false, &p, NULL) == 0);
|
||||||
puts(p);
|
puts(p);
|
||||||
assert_se(streq(basename(p), "sh"));
|
assert_se(streq(basename(p), "sh"));
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
if (oldpath)
|
if (oldpath)
|
||||||
assert_se(setenv("PATH", oldpath, true) >= 0);
|
assert_se(setenv("PATH", oldpath, true) >= 0);
|
||||||
|
|
||||||
|
assert_se((fd = mkostemp_safe(fn)) >= 0);
|
||||||
|
assert_se(fchmod(fd, 0755) >= 0);
|
||||||
|
|
||||||
|
test_file_name = basename(fn);
|
||||||
|
|
||||||
|
assert_se(find_executable_full(test_file_name, NULL, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p, NULL) == 0);
|
||||||
|
puts(p);
|
||||||
|
assert_se(streq(p, fn));
|
||||||
|
free(p);
|
||||||
|
|
||||||
|
(void) unlink(fn);
|
||||||
|
assert_se(find_executable_full(test_file_name, NULL, STRV_MAKE("/doesnotexist", "/tmp", "/bin"), false, &p, NULL) == -ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_find_executable(const char *self) {
|
static void test_find_executable(const char *self) {
|
||||||
@ -277,7 +295,7 @@ static void test_find_executable_exec_one(const char *path) {
|
|||||||
pid_t pid;
|
pid_t pid;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = find_executable_full(path, NULL, false, &t, &fd);
|
r = find_executable_full(path, NULL, NULL, false, &t, &fd);
|
||||||
|
|
||||||
log_info_errno(r, "%s: %s → %s: %d/%m", __func__, path, t ?: "-", fd);
|
log_info_errno(r, "%s: %s → %s: %d/%m", __func__, path, t ?: "-", fd);
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ AllowedMemoryNodes=
|
|||||||
AmbientCapabilities=
|
AmbientCapabilities=
|
||||||
AppArmorProfile=
|
AppArmorProfile=
|
||||||
BPFProgram=
|
BPFProgram=
|
||||||
|
ExecSearchPath=
|
||||||
BindPaths=
|
BindPaths=
|
||||||
BindReadOnlyPaths=
|
BindReadOnlyPaths=
|
||||||
BlockIOAccounting=
|
BlockIOAccounting=
|
||||||
|
@ -31,6 +31,7 @@ AssertUser=
|
|||||||
AssertVirtualization=
|
AssertVirtualization=
|
||||||
BPFProgram=
|
BPFProgram=
|
||||||
Before=
|
Before=
|
||||||
|
ExecSearchPath=
|
||||||
BindTo=
|
BindTo=
|
||||||
BindsTo=
|
BindsTo=
|
||||||
CollectMode=
|
CollectMode=
|
||||||
|
@ -7,6 +7,7 @@ AmbientCapabilities=
|
|||||||
AppArmorProfile=
|
AppArmorProfile=
|
||||||
BPFProgram=
|
BPFProgram=
|
||||||
Backlog=
|
Backlog=
|
||||||
|
ExecSearchPath=
|
||||||
BindIPv6Only=
|
BindIPv6Only=
|
||||||
BindPaths=
|
BindPaths=
|
||||||
BindReadOnlyPaths=
|
BindReadOnlyPaths=
|
||||||
|
@ -5,6 +5,7 @@ AllowedMemoryNodes=
|
|||||||
AmbientCapabilities=
|
AmbientCapabilities=
|
||||||
AppArmorProfile=
|
AppArmorProfile=
|
||||||
BPFProgram=
|
BPFProgram=
|
||||||
|
ExecSearchPath=
|
||||||
BindPaths=
|
BindPaths=
|
||||||
BindReadOnlyPaths=
|
BindReadOnlyPaths=
|
||||||
BlockIOAccounting=
|
BlockIOAccounting=
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sh -x -c 'test "$$PATH" = "/usr" && test "$$VAR1" = word3 && test "$$VAR2" = "\\$$word 5 6"'
|
||||||
|
Type=oneshot
|
||||||
|
ExecSearchPath=/tmp:/bin
|
||||||
|
Environment="PATH=/usr" VAR1=word3 "VAR2=$word 5 6"
|
@ -0,0 +1,5 @@
|
|||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$PATH" = "/tmp:/bin"'
|
||||||
|
Type=oneshot
|
||||||
|
ExecSearchPath=/tmp:/bin
|
||||||
|
Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6"
|
@ -0,0 +1,8 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Test for ExecSearchPath with EnvironmentFile where EnvironmentFile sets PATH
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = /usr'
|
||||||
|
Type=oneshot
|
||||||
|
EnvironmentFile=/tmp/test-exec_execsearchpath_environmentfile-set.conf
|
||||||
|
ExecSearchPath=/tmp:/bin
|
@ -0,0 +1,8 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Test for ExecSearchPath with EnvironmentFile where EnvironmentFile does not set PATH
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = "/tmp:/bin"'
|
||||||
|
Type=oneshot
|
||||||
|
ExecSearchPath=/tmp:/bin
|
||||||
|
EnvironmentFile=/tmp/test-exec_execsearchpath_environmentfile.conf
|
@ -0,0 +1,8 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Test for PassEnvironment with ExecSearchPath with PATH set by user
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = "/usr"'
|
||||||
|
Type=oneshot
|
||||||
|
PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5 PATH
|
||||||
|
ExecSearchPath=/tmp:/bin
|
@ -0,0 +1,8 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Test for PassEnvironment with ExecSearchPath with PATH not set by user
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/bin/sh -x -c 'test "$$VAR1" = "word1 word2" && test "$$VAR2" = word3 && test "$$VAR3" = "\\$$word 5 6" && test "$$VAR4" = "new\nline" && test "$$VAR5" = passwordwithbackslashes && test "$$PATH" = "/tmp:/bin"'
|
||||||
|
Type=oneshot
|
||||||
|
PassEnvironment=VAR1 VAR2 VAR3 VAR4 VAR5
|
||||||
|
ExecSearchPath=/tmp:/bin
|
@ -0,0 +1,7 @@
|
|||||||
|
[Unit]
|
||||||
|
Description=Test for specifiers with exec search path
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=oneshot
|
||||||
|
ExecSearchPath=/tmp:/bin:/usr/bin:%V
|
||||||
|
ExecStart=/bin/sh -x -c 'test %V = /var/tmp && test "$$PATH" = "/tmp:/bin:/usr/bin:/var/tmp"'
|
4
test/test-execute/exec-execsearchpath.service
Normal file
4
test/test-execute/exec-execsearchpath.service
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[Service]
|
||||||
|
ExecStart=ls_temp
|
||||||
|
Type=oneshot
|
||||||
|
ExecSearchPath=/tmp/test-exec_execsearchpath
|
Loading…
Reference in New Issue
Block a user