mirror of
https://github.com/systemd/systemd.git
synced 2025-01-12 13:18:14 +03:00
rework systemd's own process environment handling/passing
Stop importing non-sensical kernel-exported variables. All parameters in the kernel command line are exported to the initial environment of PID1, but suppressed if they are recognized by kernel built-in code. The EFI booted kernel will add further kernel-internal things which do not belong into userspace. The passed original environ data of the process is not touched and preserved across re-execution, to allow external reading of /proc/self/environ for process properties like container*=.
This commit is contained in:
parent
68fee104e6
commit
e21fea24ae
@ -1113,16 +1113,11 @@
|
||||
<term><varname>systemd.setenv=</varname></term>
|
||||
|
||||
<listitem><para>Takes a string
|
||||
argument in the form
|
||||
VARIABLE=VALUE. May be used to set
|
||||
environment variables for the init
|
||||
process and all its children at boot
|
||||
time. May be used more than once to
|
||||
set multiple variables. If the equal
|
||||
sign and variable are missing it unsets
|
||||
an environment variable which might be
|
||||
passed in from the initial ram
|
||||
disk.</para></listitem>
|
||||
argument in the form VARIABLE=VALUE.
|
||||
May be used to set default environment
|
||||
variables to add to forked child processes.
|
||||
May be used more than once to set multiple
|
||||
variables.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "macro.h"
|
||||
#include "virt.h"
|
||||
#include "fileio.h"
|
||||
#include "strv.h"
|
||||
|
||||
enum {
|
||||
/* We don't list LC_ALL here on purpose. People should be
|
||||
@ -67,7 +68,8 @@ static const char * const variable_names[_VARIABLE_MAX] = {
|
||||
[VARIABLE_LC_IDENTIFICATION] = "LC_IDENTIFICATION"
|
||||
};
|
||||
|
||||
int locale_setup(void) {
|
||||
int locale_setup(char ***environment) {
|
||||
char **env;
|
||||
char *variables[_VARIABLE_MAX] = {};
|
||||
int r = 0, i;
|
||||
|
||||
@ -118,13 +120,16 @@ int locale_setup(void) {
|
||||
}
|
||||
|
||||
for (i = 0; i < _VARIABLE_MAX; i++) {
|
||||
if (variables[i]) {
|
||||
if (setenv(variable_names[i], variables[i], 1) < 0) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
} else
|
||||
unsetenv(variable_names[i]);
|
||||
if (!variables[i])
|
||||
continue;
|
||||
|
||||
env = strv_appendf(*environment, "%s=%s", variable_names[i], variables[i]);
|
||||
if (!env) {
|
||||
r = -ENOMEM;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
*environment = env;
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
@ -21,4 +21,4 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int locale_setup(void);
|
||||
int locale_setup(char ***environment);
|
||||
|
@ -64,7 +64,6 @@
|
||||
#endif
|
||||
#include "hostname-setup.h"
|
||||
#include "machine-id-setup.h"
|
||||
#include "locale-setup.h"
|
||||
#include "selinux-setup.h"
|
||||
#include "ima-setup.h"
|
||||
#include "fileio.h"
|
||||
@ -349,32 +348,21 @@ static int parse_proc_cmdline_word(const char *word) {
|
||||
arg_default_std_error = r;
|
||||
} else if (startswith(word, "systemd.setenv=")) {
|
||||
_cleanup_free_ char *cenv = NULL;
|
||||
char *eq;
|
||||
int r;
|
||||
|
||||
cenv = strdup(word + 15);
|
||||
if (!cenv)
|
||||
return -ENOMEM;
|
||||
|
||||
eq = strchr(cenv, '=');
|
||||
if (!eq) {
|
||||
if (!env_name_is_valid(cenv))
|
||||
log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
|
||||
else {
|
||||
r = unsetenv(cenv);
|
||||
if (r < 0)
|
||||
log_warning("Unsetting environment variable '%s' failed, ignoring: %m", cenv);
|
||||
}
|
||||
} else {
|
||||
if (!env_assignment_is_valid(cenv))
|
||||
log_warning("Environment variable assignment '%s' is not valid. Ignoring.", cenv);
|
||||
else {
|
||||
*eq = 0;
|
||||
r = setenv(cenv, eq + 1, 1);
|
||||
if (r < 0)
|
||||
log_warning("Setting environment variable '%s=%s' failed, ignoring: %m", cenv, eq + 1);
|
||||
}
|
||||
}
|
||||
if (env_assignment_is_valid(cenv)) {
|
||||
char **env;
|
||||
|
||||
env = strv_env_set(arg_default_environment, cenv);
|
||||
if (env)
|
||||
arg_default_environment = env;
|
||||
else
|
||||
log_warning("Setting environment variable '%s' failed, ignoring: %m", cenv);
|
||||
} else
|
||||
log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
|
||||
|
||||
} else if (startswith(word, "systemd.") ||
|
||||
(in_initrd() && startswith(word, "rd.systemd."))) {
|
||||
@ -1445,42 +1433,7 @@ int main(int argc, char *argv[]) {
|
||||
if (serialization)
|
||||
assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
|
||||
|
||||
/* Set up PATH unless it is already set */
|
||||
setenv("PATH",
|
||||
#ifdef HAVE_SPLIT_USR
|
||||
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||
#else
|
||||
"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
|
||||
#endif
|
||||
arg_running_as == SYSTEMD_SYSTEM);
|
||||
|
||||
if (arg_running_as == SYSTEMD_SYSTEM) {
|
||||
/* Unset some environment variables passed in from the
|
||||
* kernel that don't really make sense for us. */
|
||||
unsetenv("HOME");
|
||||
unsetenv("TERM");
|
||||
|
||||
/* When we are invoked by a shell, these might be set,
|
||||
* but make little sense to pass on */
|
||||
unsetenv("PWD");
|
||||
unsetenv("SHLVL");
|
||||
unsetenv("_");
|
||||
|
||||
/* When we are invoked by a chroot-like tool such as
|
||||
* nspawn, these might be set, but make little sense
|
||||
* to pass on */
|
||||
unsetenv("USER");
|
||||
unsetenv("LOGNAME");
|
||||
|
||||
/* We suppress the socket activation env vars, as
|
||||
* we'll try to match *any* open fd to units if
|
||||
* possible. */
|
||||
unsetenv("LISTEN_FDS");
|
||||
unsetenv("LISTEN_PID");
|
||||
|
||||
/* All other variables are left as is, so that clients
|
||||
* can still read them via /proc/1/environ */
|
||||
|
||||
/* Become a session leader if we aren't one yet. */
|
||||
setsid();
|
||||
|
||||
@ -1528,8 +1481,6 @@ int main(int argc, char *argv[]) {
|
||||
log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES ")");
|
||||
|
||||
if (arg_running_as == SYSTEMD_SYSTEM && !skip_setup) {
|
||||
locale_setup();
|
||||
|
||||
if (arg_show_status || plymouth_running())
|
||||
status_welcome();
|
||||
|
||||
@ -1595,7 +1546,7 @@ int main(int argc, char *argv[]) {
|
||||
manager_set_default_rlimits(m, arg_default_rlimit);
|
||||
|
||||
if (arg_default_environment)
|
||||
manager_set_default_environment(m, arg_default_environment);
|
||||
manager_environment_add(m, arg_default_environment);
|
||||
|
||||
manager_set_show_status(m, arg_show_status);
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "util.h"
|
||||
#include "mkdir.h"
|
||||
#include "ratelimit.h"
|
||||
#include "locale-setup.h"
|
||||
#include "mount-setup.h"
|
||||
#include "unit-name.h"
|
||||
#include "dbus-unit.h"
|
||||
@ -454,22 +455,36 @@ static int manager_setup_signals(Manager *m) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void manager_strip_environment(Manager *m) {
|
||||
static int manager_default_environment(Manager *m) {
|
||||
#ifdef HAVE_SPLIT_USR
|
||||
const char *path = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
||||
#else
|
||||
const char *path = "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin";
|
||||
#endif
|
||||
|
||||
assert(m);
|
||||
|
||||
/* Remove variables from the inherited set that are part of
|
||||
* the container interface:
|
||||
* http://www.freedesktop.org/wiki/Software/systemd/ContainerInterface */
|
||||
strv_remove_prefix(m->environment, "container=");
|
||||
strv_remove_prefix(m->environment, "container_");
|
||||
if (m->running_as == SYSTEMD_SYSTEM) {
|
||||
/* The system manager always starts with a clean
|
||||
* environment for its children. It does not import
|
||||
* the kernel or the parents exported variables.
|
||||
*
|
||||
* The initial passed environ is untouched to keep
|
||||
* /proc/self/environ valid; it is used for tagging
|
||||
* the init process inside containers. */
|
||||
m->environment = strv_new(path, NULL);
|
||||
|
||||
/* Remove variables from the inherited set that are part of
|
||||
* the initrd interface:
|
||||
* http://www.freedesktop.org/wiki/Software/systemd/InitrdInterface */
|
||||
strv_remove_prefix(m->environment, "RD_");
|
||||
/* Import locale variables LC_*= from configuration */
|
||||
locale_setup(&m->environment);
|
||||
} else
|
||||
/* The user manager passes its own environment
|
||||
* along to its children. */
|
||||
m->environment = strv_copy(environ);
|
||||
|
||||
/* Drop invalid entries */
|
||||
strv_env_clean(m->environment);
|
||||
if (!m->environment)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
|
||||
@ -505,12 +520,10 @@ int manager_new(SystemdRunningAs running_as, bool reexecuting, Manager **_m) {
|
||||
m->epoll_fd = m->dev_autofs_fd = -1;
|
||||
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
|
||||
|
||||
m->environment = strv_copy(environ);
|
||||
if (!m->environment)
|
||||
r = manager_default_environment(m);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
|
||||
manager_strip_environment(m);
|
||||
|
||||
if (!(m->units = hashmap_new(string_hash_func, string_compare_func)))
|
||||
goto fail;
|
||||
|
||||
@ -2651,7 +2664,7 @@ void manager_undo_generators(Manager *m) {
|
||||
remove_generator_dir(m, &m->generator_unit_path_late);
|
||||
}
|
||||
|
||||
int manager_set_default_environment(Manager *m, char **environment) {
|
||||
int manager_environment_add(Manager *m, char **environment) {
|
||||
|
||||
char **e = NULL;
|
||||
assert(m);
|
||||
|
@ -281,7 +281,7 @@ unsigned manager_dispatch_load_queue(Manager *m);
|
||||
unsigned manager_dispatch_run_queue(Manager *m);
|
||||
unsigned manager_dispatch_dbus_queue(Manager *m);
|
||||
|
||||
int manager_set_default_environment(Manager *m, char **environment);
|
||||
int manager_environment_add(Manager *m, char **environment);
|
||||
int manager_set_default_rlimits(Manager *m, struct rlimit **default_rlimit);
|
||||
|
||||
int manager_loop(Manager *m);
|
||||
|
@ -387,6 +387,21 @@ fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char **strv_appendf(char **l, const char *format, ...) {
|
||||
va_list ap;
|
||||
_cleanup_free_ char *s = NULL;
|
||||
int r;
|
||||
|
||||
va_start(ap, format);
|
||||
r = vasprintf(&s, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
|
||||
return strv_append(l, s);
|
||||
}
|
||||
|
||||
int strv_push(char ***l, char *value) {
|
||||
char **c;
|
||||
unsigned n;
|
||||
|
@ -42,6 +42,7 @@ unsigned strv_length(char * const *l) _pure_;
|
||||
char **strv_merge(char **a, char **b);
|
||||
char **strv_merge_concat(char **a, char **b, const char *suffix);
|
||||
char **strv_append(char **l, const char *s);
|
||||
char **strv_appendf(char **l, const char *format, ...) _printf_attr_(2, 3);
|
||||
int strv_extend(char ***l, const char *value);
|
||||
int strv_push(char ***l, char *value);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user