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:
alexlzhu
2021-09-28 14:52:27 +01:00
committed by Chris Down
parent 5b32e48f6e
commit 8c35c10d20
27 changed files with 360 additions and 13 deletions
+94
View File
@@ -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),
{},
};
+23 -5
View File
@@ -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);