7.4. Init environment
The kernel parses parameters from the kernel command line up to "--"; if it doesn’t recognize a parameter and it doesn’t contain a '.', the parameter gets passed to init: parameters with '=' go into init’s environment, others are passed as command line arguments to init. Everything after "--" is passed as an argument to init.
And you can try it out with our userland/linux/init_env_poweroff.c program:
./run --kernel-cli 'init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2' \
--kernel-cli-after-dash 'go_in_arg=val3 with_dot.after=val4 zxcv'
From the generated QEMU command, we see that the kernel CLI at LKMC 69f5745d3df11d5c741551009df86ea6c61a09cf now contains (or at least would if it weren’t for https://github.com/cirosantilli/linux-kernel-module-cheat/issues/110 oh God), manually indented for readability:
<6>[ 0.000000] Command line: root=/dev/vda nopat console_msg_format=syslog nokaslr norandmaps panic=-1 printk.devkmsg=on printk.time=y rw init=/lkmc/linux/init_env_poweroff.out loglevel=8 go_in_env=val1 with_dot.before=val2 -- go_in_arg=val3 with_dot.after=val4 zxcv
and the init program outputs:
<6>[ 2.728992] Run /lkmc/linux/init_env_poweroff.out as init process <7>[ 2.729587] with arguments: <7>[ 2.729820] /lkmc/linux/init_env_poweroff.out <7>[ 2.730085] lkmc_home=/lkmc <7>[ 2.730259] go_in_arg=val3 <7>[ 2.730432] with_dot.after=val4 <7>[ 2.730623] zxcv <7>[ 2.730767] with environment: <7>[ 2.730960] HOME=/ <7>[ 2.731115] TERM=linux <7>[ 2.731267] go_in_env=val
Tested as of the Linux kernel v5.7 and possibly earlier, boot also shows the init arguments and environment very clearly when using printk at loglevel=8, which is a great addition:
<6>[ 2.777265] Run /lkmc/linux/init_env_poweroff.out as init process <7>[ 2.777729] with arguments: <7>[ 2.777953] /lkmc/linux/init_env_poweroff.out <7>[ 2.778212] lkmc_home=/lkmc <7>[ 2.778391] go_in_arg=val2 <7>[ 2.778554] zxcv <7>[ 2.778705] with environment: <7>[ 2.778901] HOME=/ <7>[ 2.779065] TERM=linux <7>[ 2.779223] go_in_env=val1
As we can see, the passing of environment variables to init is a bit wonky:
-
initandlogleveldidn’t go because they were recognized -
go_in_envwent because it wasn’t
so things can always break in future kernel releases… The only way to guard from this a bit is to use some unique prefix and hope the kernel never decides to use it. We of course use lkmc_* for our variables.
And it is also impossible to pass environment variables that contain dots in them: our with_dot.before is simply gone. Not a common use case, but still, quite insane.