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:
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "capability-util.h"
|
||||
#include "cpu-set-util.h"
|
||||
#include "copy.h"
|
||||
#include "dropin.h"
|
||||
#include "errno-list.h"
|
||||
#include "fd-util.h"
|
||||
@@ -28,6 +29,7 @@
|
||||
#include "static-destruct.h"
|
||||
#include "stat-util.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "unit.h"
|
||||
#include "user-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);
|
||||
}
|
||||
|
||||
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) {
|
||||
#if defined(__x86_64__)
|
||||
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_user),
|
||||
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[] = {
|
||||
entry(test_exec_dynamicuser),
|
||||
entry(test_exec_specifier),
|
||||
entry(test_exec_execsearchpath_specifier),
|
||||
entry(test_exec_systemcallfilter_system),
|
||||
{},
|
||||
};
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "alloc-util.h"
|
||||
#include "exec-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "macro.h"
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
@@ -14,6 +15,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tests.h"
|
||||
#include "tmpfile-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static void test_print_paths(void) {
|
||||
@@ -201,15 +203,18 @@ static void test_path_equal_root(void) {
|
||||
|
||||
static void test_find_executable_full(void) {
|
||||
char *p;
|
||||
char* test_file_name;
|
||||
_cleanup_close_ int fd = -1;
|
||||
char fn[] = "/tmp/test-XXXXXX";
|
||||
|
||||
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);
|
||||
assert_se(streq(basename(p), "sh"));
|
||||
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);
|
||||
assert_se(streq(basename(p), "sh"));
|
||||
free(p);
|
||||
@@ -221,18 +226,31 @@ static void test_find_executable_full(void) {
|
||||
|
||||
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);
|
||||
assert_se(streq(basename(p), "sh"));
|
||||
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);
|
||||
assert_se(streq(basename(p), "sh"));
|
||||
free(p);
|
||||
|
||||
if (oldpath)
|
||||
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) {
|
||||
@@ -277,7 +295,7 @@ static void test_find_executable_exec_one(const char *path) {
|
||||
pid_t pid;
|
||||
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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user