[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

superfluous environment variables



Hi,

I’ve noticed that sysvinit/sysv-rc start dæmons with a *lot* of
superfluous environment variables compared to manual invocation
with an environment cleaner of mine:

# cleanenv / env | sort
HOME=/
LC_ALL=C.UTF-8
PATH=/bin:/usr/bin:/sbin:/usr/sbin

I checked /proc/<pid>/environ for (exemplarily) cron from bootup
and from a manual 'cleanenv / /etc/init.d/cron st{op,art}' and
found these:

--- e1	2022-12-12 18:02:21.549735648 +0000
+++ e2	2022-12-12 18:02:21.049737965 +0000
@@ -1,20 +1,5 @@
-BOOT_IMAGE=/vmlinuz-5.10.0-19-amd64
-CONSOLE=/dev/console
 HOME=/
-INIT_VERSION=sysvinit-2.96
 LANG=C.UTF-8
+LC_ALL=C.UTF-8
 PATH=/bin:/usr/bin:/sbin:/usr/sbin
-PREVLEVEL=N
-PWD=/
-RUNLEVEL=2
-SHELL=/bin/sh
-SHLVL=1
-TERM=linux
-VERBOSE=yes
 _=/sbin/start-stop-daemon
-drop_caps=
-init=/sbin/init
-ip=xxx.xxx.xxx.xx::xxx.xxx.xxx.1:255.255.255.0:xxxx.xxxxxx.xxx::off:xxx.xxx.xxx.xx:xxx.xxx.x.xx:xxx.xxx.xxx.xx
-previous=N
-rootmnt=/root
-runlevel=2

This means that, even for a manual invocation, these are added:

• LANG=C.UTF-8
• _=/sbin/start-stop-daemon

The former is set, but not exported, in /etc/default/locale and
therefore this is (probably) “as expected”, the second is from
the shell.

However, sysvinit at boot does extra things:

• The kernel commandline parameters are added:
  ‣ /proc/cmdline
    BOOT_IMAGE, ip (but not the others!)
• The pid 1 environ is added, but I wonder at its contents;
  it seems to me that pid 1 is adding stuff over the kernel?
  ‣ HOME=/, PATH, PWD=/, SHLVL=1, TERM=linux, drop_caps=,
    init=/sbin/init, rootmnt=/root
  ‣ I wouldn’t expect *anything* to ever export PWD, as that
    makes no sense, and SHLVL is a GNU bash-specific thing
• Extra exports:
  ‣ CONSOLE, INIT_VERSION, PREVLEVEL, RUNLEVEL, SHELL,
    VERBOSE, previous, runlevel
• PATH is not the same as in pid1 env, but that’s likely okay

I question a *lot* of these things. The kernel sets…

const char *envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };

… plus boot options (see near the end of the eMail).

The remainder is either set by init or, which occurred to me just
as I am writing this, the initrd… so I guess we probably should
include them in this discussion.

On my laptop:
# tr '\0' '\n' </proc/1/environ | sort
BOOT_IMAGE=/SDcardBoot/vmlinuz-5.10.0-19-amd64
HOME=/
PATH=/sbin:/usr/sbin:/bin:/usr/bin
PWD=/
SHLVL=1
TERM=linux
drop_caps=
init=/sbin/init
rootmnt=/root
vga=792

I think this is too much. PWD and SHLVL are utter nōnsense, as I
already indicated. Are BOOT_IMAGE, drop_caps, init, rootmnt used
to communicate values to pid1? I also doubt vga or ip should be
present?

In the same manner, the environment that init scripts are called
is loaded, and even contains runlevel twice. I get why we need
e.g. VERBOSE, but /lib/init/vars.sh or /lib/lsb/init-functions,
which TTBOMK all init scripts are required to source, could load
them so they do not need to be exported. (In fact I think they
already do, because even the manual cleanenv-based invocation is
verbose, but as these parameters are imported because the init
script *runner* exports them, they still get exported.) Some of
the variables probably are used for communication between init
and /etc/rc but aren’t needed in the init scripts.

I guess s-s-d could also strip some but that’s, strictly speaking,
not its job.

Is there any interest in tracking these exports down, one by one,
and checking which are needed where, and which can be stripped
where?

For sake of completeness, I’ll also include below the Debian/GNU
version of my cleanenv script. The script has three modes it’s
supposed to be used. One is “cleanenv command”, which sets UTC and
cleans “most” variables but keeps USER, DISPLAY, TERM and the locale;
it’s intended to be used for cases where you just run a command
but want its output. I use this e.g. as “sudo cleanenv make install”
on MirBSD, to avoid things like $BINMODE if set leaking into that.
The second (cleanenv - command) and third (cleanenv / command) mode
clean everything then set from a whitelist; the third also cd(1)s
to / to avoid things like “sudo pg_dump” in /root complaining about
not being able to get the currnet working directory.

-----BEGIN cutting here may damage your screen surface-----
#!/bin/sh
# $MirOS: src/scripts/cleanenv,v 1.7+xorg 2022/05/24 03:34:20 tg Exp $

p=/bin:/usr/bin:/sbin:/usr/sbin

a1=$1

if test x"$a1" = x"/"; then
	cd /
	a1=-
fi

if test x"$a1" = x"-"; then
	shift
	exec /usr/bin/env -i \
	    PATH=$p HOME=/ LC_ALL=C.UTF-8 \
	    "$@"
fi

lc=$(locale 2>/dev/null | fgrep LC_CTYPE | sed 's/="\(.*\)"$/=\1/')
exec /usr/bin/env -i \
    PATH=$p TZ=UTC ${lc:+"$lc"} \
    DISPLAY="$DISPLAY" HOME="${HOME:-/}" TERM="${TERM:-vt100}" USER="${USER}" \
    "$@"
-----END cutting here may damage your screen surface-----

The BSD version mostly differs in the definition of $p (adding
/usr/X11R6/bin).

Note how this uses a whitelist approach to environment filtering
instead of a blacklist approach. Given the kernel passes its
commandline (mostly) in the environment (unknown_bootoption in
init/main.c), this is needed at *some* point during boot, too.
AIUI all parameters are still available via /proc/cmdline anyway
so the only reason to keep things in the environment is if they
are part of an “interface” between caller and callee.

I only can think of one system at work I have ssh+root on that
runs systemd, and it’s a *buntu jammy system, but, for comparison,
the env of cron there is:

INVOCATION_ID=8420b4861ee34808a8eab08ee778191a
JOURNAL_STREAM=8:18703
LANG=de_DE.UTF-8
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
SYSTEMD_EXEC_PID=414

So, rather cleaner and definitely a whitelist approach, though
I wonder whether the absence of HOME can be trouble or avoid it.

This means that individual services are prepared for this reduction
already, it’s only the init scripts and the init systems’ infra‐
structure that needs checking.

bye,
//mirabilos
-- 
Infrastrukturexperte • tarent solutions GmbH
Am Dickobskreuz 10, D-53121 Bonn • http://www.tarent.de/
Telephon +49 228 54881-393 • Fax: +49 228 54881-235
HRB AG Bonn 5168 • USt-ID (VAT): DE122264941
Geschäftsführer: Dr. Stefan Barth, Kai Ebenrett, Boris Esser, Alexander Steeg

                        ****************************************************
/⁀\ The UTF-8 Ribbon
╲ ╱ Campaign against      Mit dem tarent-Newsletter nichts mehr verpassen:
 ╳  HTML eMail! Also,     https://www.tarent.de/newsletter
╱ ╲ header encryption!
                        ****************************************************


Reply to: