]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
exec-util: in execute_directories, support initial exec environment
authorDimitri John Ledkov <xnox@ubuntu.com>
Wed, 12 Sep 2018 17:19:13 +0000 (18:19 +0100)
committerDimitri John Ledkov <xnox@ubuntu.com>
Mon, 24 Sep 2018 12:40:10 +0000 (13:40 +0100)
src/basic/exec-util.c
src/basic/exec-util.h
src/core/manager.c
src/core/shutdown.c
src/sleep/sleep.c
src/test/test-exec-util.c

index 7e336f9ce1ef3f200387cfb992818e75378ae138..e8af191104f535ee1e56133599d460a4ad690750 100644 (file)
@@ -71,11 +71,12 @@ static int do_execute(
                 gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX],
                 void* const callback_args[_STDOUT_CONSUME_MAX],
                 int output_fd,
-                char *argv[]) {
+                char *argv[],
+                char *envp[]) {
 
         _cleanup_hashmap_free_free_ Hashmap *pids = NULL;
         _cleanup_strv_free_ char **paths = NULL;
-        char **path;
+        char **path, **e;
         int r;
 
         /* We fork this all off from a child process so that we can somewhat cleanly make
@@ -100,6 +101,9 @@ static int do_execute(
         if (timeout != USEC_INFINITY)
                 alarm(DIV_ROUND_UP(timeout, USEC_PER_SEC));
 
+        STRV_FOREACH(e, envp)
+                putenv(*e);
+
         STRV_FOREACH(path, paths) {
                 _cleanup_free_ char *t = NULL;
                 _cleanup_close_ int fd = -1;
@@ -166,7 +170,8 @@ int execute_directories(
                 usec_t timeout,
                 gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX],
                 void* const callback_args[_STDOUT_CONSUME_MAX],
-                char *argv[]) {
+                char *argv[],
+                char *envp[]) {
 
         char **dirs = (char**) directories;
         _cleanup_close_ int fd = -1;
@@ -197,7 +202,7 @@ int execute_directories(
         if (r < 0)
                 return r;
         if (r == 0) {
-                r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv);
+                r = do_execute(dirs, timeout, callbacks, callback_args, fd, argv, envp);
                 _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS);
         }
 
index 823ca6578cf5b0c6b07fffea2b5f17282ef53adf..6ac3c9000a048ceff99ca4d49a7158069b48cdb8 100644 (file)
@@ -19,6 +19,7 @@ int execute_directories(
                 usec_t timeout,
                 gather_stdout_callback_t const callbacks[_STDOUT_CONSUME_MAX],
                 void* const callback_args[_STDOUT_CONSUME_MAX],
-                char *argv[]);
+                char *argv[],
+                char *envp[]);
 
 extern const gather_stdout_callback_t gather_environment[_STDOUT_CONSUME_MAX];
index da05066cdd6ea48802606932cb22e7120366a5cb..f86b924d02412c2744928644fb41f477d8e88c23 100644 (file)
@@ -3788,7 +3788,7 @@ static int manager_run_environment_generators(Manager *m) {
         if (!generator_path_any(paths))
                 return 0;
 
-        return execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL);
+        return execute_directories(paths, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL);
 }
 
 static int manager_run_generators(Manager *m) {
@@ -3820,7 +3820,7 @@ static int manager_run_generators(Manager *m) {
 
         RUN_WITH_UMASK(0022)
                 execute_directories((const char* const*) paths, DEFAULT_TIMEOUT_USEC,
-                                    NULL, NULL, (char**) argv);
+                                    NULL, NULL, (char**) argv, NULL);
 
 finish:
         lookup_paths_trim_generator(&m->lookup_paths);
index 038345b7526b42efcb7f8ce4db3f679ed652c044..5bf332d9a9b9cea7a053b59fbdccd46d70127585 100644 (file)
@@ -435,7 +435,7 @@ int main(int argc, char *argv[]) {
         arguments[0] = NULL;
         arguments[1] = arg_verb;
         arguments[2] = NULL;
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
 
         if (can_initrd) {
                 r = switch_root_initramfs();
index 3b8d4578397e41c4dfc8c3260bb006d92e491fc6..042a44656fe1ff2462c177a73057ae7ab36638c2 100644 (file)
@@ -167,7 +167,7 @@ static int execute(char **modes, char **states) {
                         return log_error_errno(r, "Failed to write mode to /sys/power/disk: %m");;
         }
 
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
 
         log_struct(LOG_INFO,
                    "MESSAGE_ID=" SD_MESSAGE_SLEEP_START_STR,
@@ -184,7 +184,7 @@ static int execute(char **modes, char **states) {
                    "SLEEP=%s", arg_verb);
 
         arguments[1] = (char*) "post";
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments);
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, arguments, NULL);
 
         return r;
 }
index d346a4d6f7d11af8bc1c7f2ede18b918c0b8339f..e74b95231dc18a5313847e52f127d4ba4e28db2f 100644 (file)
@@ -16,6 +16,7 @@
 #include "fs-util.h"
 #include "log.h"
 #include "macro.h"
+#include "path-util.h"
 #include "rm-rf.h"
 #include "string-util.h"
 #include "strv.h"
@@ -116,9 +117,9 @@ static void test_execute_directory(bool gather_stdout) {
         assert_se(chmod(mask2e, 0755) == 0);
 
         if (gather_stdout)
-                execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+                execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL);
         else
-                execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL);
+                execute_directories(dirs, DEFAULT_TIMEOUT_USEC, NULL, NULL, NULL, NULL);
 
         assert_se(chdir(template_lo) == 0);
         assert_se(access("it_works", F_OK) >= 0);
@@ -183,7 +184,7 @@ static void test_execution_order(void) {
         assert_se(chmod(override, 0755) == 0);
         assert_se(chmod(masked, 0755) == 0);
 
-        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL);
+        execute_directories(dirs, DEFAULT_TIMEOUT_USEC, ignore_stdout, ignore_stdout_args, NULL, NULL);
 
         assert_se(read_full_file(output, &contents, NULL) >= 0);
         assert_se(streq(contents, "30-override\n80-foo\n90-bar\nlast\n"));
@@ -265,7 +266,7 @@ static void test_stdout_gathering(void) {
         assert_se(chmod(name2, 0755) == 0);
         assert_se(chmod(name3, 0755) == 0);
 
-        r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL);
+        r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_stdout, args, NULL, NULL);
         assert_se(r >= 0);
 
         log_info("got: %s", output);
@@ -276,7 +277,7 @@ static void test_stdout_gathering(void) {
 static void test_environment_gathering(void) {
         char template[] = "/tmp/test-exec-util.XXXXXXX", **p;
         const char *dirs[] = {template, NULL};
-        const char *name, *name2, *name3;
+        const char *name, *name2, *name3, *old;
         int r;
 
         char **tmp = NULL; /* this is only used in the forked process, no cleanup here */
@@ -322,7 +323,32 @@ static void test_environment_gathering(void) {
         assert_se(chmod(name2, 0755) == 0);
         assert_se(chmod(name3, 0755) == 0);
 
-        r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL);
+        /* When booting in containers or without initramfs there might not be
+         * any PATH in the environ and if there is no PATH /bin/sh built-in
+         * PATH may leak and override systemd's DEFAULT_PATH which is not
+         * good. Force our own PATH in environment, to prevent expansion of sh
+         * built-in $PATH */
+        old = getenv("PATH");
+        r = setenv("PATH", "no-sh-built-in-path", 1);
+        assert_se(r >= 0);
+
+        r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, NULL);
+        assert_se(r >= 0);
+
+        STRV_FOREACH(p, env)
+                log_info("got env: \"%s\"", *p);
+
+        assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
+        assert_se(streq(strv_env_get(env, "B"), "12"));
+        assert_se(streq(strv_env_get(env, "C"), "001"));
+        assert_se(streq(strv_env_get(env, "PATH"), "no-sh-built-in-path:/no/such/file"));
+
+        /* now retest with "default" path passed in, as created by
+         * manager_default_environment */
+        env = strv_free(env);
+        env = strv_new("PATH=" DEFAULT_PATH, NULL);
+
+        r = execute_directories(dirs, DEFAULT_TIMEOUT_USEC, gather_environment, args, NULL, env);
         assert_se(r >= 0);
 
         STRV_FOREACH(p, env)
@@ -331,7 +357,10 @@ static void test_environment_gathering(void) {
         assert_se(streq(strv_env_get(env, "A"), "22:23:24"));
         assert_se(streq(strv_env_get(env, "B"), "12"));
         assert_se(streq(strv_env_get(env, "C"), "001"));
-        assert_se(endswith(strv_env_get(env, "PATH"), ":/no/such/file"));
+        assert_se(streq(strv_env_get(env, "PATH"), DEFAULT_PATH ":/no/such/file"));
+
+        /* reset environ PATH */
+        (void) setenv("PATH", old, 1);
 }
 
 int main(int argc, char *argv[]) {