severity 505440 critical # justification: is the cause of 426465, which is critical clone 505440 -1 reassign -1 sysvinit retitle -1 init should clear environment tag -1 patch thanks
For background, see #426465 and #505440, which is a more general description of #426465. initramfs exports an environment in /init with variables that confuse some initscripts. Ubuntu has fixed this by having upstart clear its environment. It looks like initramfs-tools should be fixed by having it export a smaller environment, but we can and probably should also fix the problems it causes by having init clear its environment in child processes. The attached patch does this. upstart passes on two environment variables, PATH and TERM, so this patch does the same. Applying this change breaks an old-fashioned practice in initscripts of getting certain variables from the kernel command line by expecting them to be exported in the environment. An Ubuntu bug from 2006 (https://bugs.launchpad.net/bugs/74664) describes a situation where this cropped up when they implemented the change. The correct way for an initscript to do this is to look in /proc/cmdline, as e.g. the initscripts package does in /etc/init.d/stop-bootlogd-single. It's possible that some packages still use the old-fashioned practice. Once this patch or another fix is uploaded, bugs #426465 and #505440 in initramfs-tools can be downgraded. Greg
#! /bin/sh /usr/share/dpatch/dpatch-run ## 95_clear_environment.dpatch by Greg Price Clear the environment when spawning a process. @DPATCH@ diff -urNad trunk~/src/init.c trunk/src/init.c --- trunk~/src/init.c 2008-12-13 20:35:24.000000000 -0500 +++ trunk/src/init.c 2008-12-13 20:35:24.000000000 -0500 @@ -188,6 +188,8 @@ struct { {NULL,0} }; +char * const default_env_vars[] = {"PATH", "TERM", NULL}; + #define NR_EXTRA_ENV 16 char *extra_env[NR_EXTRA_ENV]; @@ -782,13 +784,27 @@ char **init_buildenv(int child) char **e; int n, i; - for (n = 0; environ[n]; n++) - ; + if (child) { + for (n = 0; default_env_vars[n]; n++) + ; + } else { + for (n = 0; environ[n]; n++) + ; + } n += NR_EXTRA_ENV + 8; e = calloc(n, sizeof(char *)); - for (n = 0; environ[n]; n++) - e[n] = istrdup(environ[n]); + if (child) { + for (n = 0; default_env_vars[n]; n++) { + char *key = default_env_vars[n]; + char *value = getenv(key); + e[n] = imalloc(strlen(key) + strlen(value) + 2); + sprintf(e[n], "%s=%s", key, value); + } + } else { + for (n = 0; environ[n]; n++) + e[n] = istrdup(environ[n]); + } for (i = 0; i < NR_EXTRA_ENV; i++) if (extra_env[i])