From b4c14404b3e8753c41bac0b1d49369230a15c544 Mon Sep 17 00:00:00 2001 From: Filipe Brandenburger Date: Sun, 6 Sep 2015 23:06:53 -0700 Subject: execute: Add new PassEnvironment= directive This directive allows passing environment variables from the system manager to spawned services. Variables in the system manager can be set inside a container by passing `--set-env=...` options to systemd-spawn. Tested with an on-disk test.service unit. Tested using multiple variable names on a single line, with an empty setting to clear the current list of variables, with non-existing variables. Tested using `systemd-run -p PassEnvironment=VARNAME` to confirm it works with transient units. Confirmed that `systemctl show` will display the PassEnvironment settings. Checked that man pages are generated correctly. No regressions in `make check`. --- src/core/execute.c | 43 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) (limited to 'src/core/execute.c') diff --git a/src/core/execute.c b/src/core/execute.c index d751065af0..07979bf8b3 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -1332,6 +1332,34 @@ static int build_environment( return 0; } +static int build_pass_environment(const ExecContext *c, char ***ret) { + _cleanup_strv_free_ char **pass_env = NULL; + size_t n_env = 0, n_bufsize = 0; + char **i; + + STRV_FOREACH(i, c->pass_environment) { + _cleanup_free_ char *x = NULL; + char *v; + + v = getenv(*i); + if (!v) + continue; + x = strjoin(*i, "=", v, NULL); + if (!x) + return -ENOMEM; + if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2)) + return -ENOMEM; + pass_env[n_env++] = x; + pass_env[n_env] = NULL; + x = NULL; + } + + *ret = pass_env; + pass_env = NULL; + + return 0; +} + static bool exec_needs_mount_namespace( const ExecContext *context, const ExecParameters *params, @@ -1412,7 +1440,7 @@ static int exec_child( char **files_env, int *exit_status) { - _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL; + _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL; _cleanup_free_ char *mac_selinux_context_net = NULL; const char *username = NULL, *home = NULL, *shell = NULL, *wd; uid_t uid = UID_INVALID; @@ -1928,9 +1956,16 @@ static int exec_child( return r; } - final_env = strv_env_merge(5, + r = build_pass_environment(context, &pass_env); + if (r < 0) { + *exit_status = EXIT_MEMORY; + return r; + } + + final_env = strv_env_merge(6, params->environment, our_env, + pass_env, context->environment, files_env, pam_env, @@ -2088,6 +2123,7 @@ void exec_context_done(ExecContext *c) { c->environment = strv_free(c->environment); c->environment_files = strv_free(c->environment_files); + c->pass_environment = strv_free(c->pass_environment); for (l = 0; l < ELEMENTSOF(c->rlimit); l++) c->rlimit[l] = mfree(c->rlimit[l]); @@ -2358,6 +2394,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { STRV_FOREACH(e, c->environment_files) fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e); + STRV_FOREACH(e, c->pass_environment) + fprintf(f, "%sPassEnvironment: %s\n", prefix, *e); + fprintf(f, "%sRuntimeDirectoryMode: %04o\n", prefix, c->runtime_directory_mode); STRV_FOREACH(d, c->runtime_directory) -- cgit v1.2.3-54-g00ecf