initrd: Don't enable the root shell by default

Starting an authenticated root shell is a security hole, so don't do
it by default.  The kernel command line parameter
‘initrd.shell_on_fail’ restores the original.  (Of course, this only
improves security if you have a password on GRUB to prevent the kernel
command line from being edited by unauthorized users.)
This commit is contained in:
Eelco Dolstra 2013-01-09 22:31:57 +01:00
parent 91bead9c18
commit 93a7a32bab
2 changed files with 48 additions and 30 deletions

View File

@ -16,15 +16,26 @@ systemd:
<variablelist> <variablelist>
<varlistentry><term><literal>initrd.shell_on_fail</literal></term>
<listitem><para>Start a root shell if something goes wrong in
stage 1 of the boot process (the initial ramdisk). This is
disabled by default because there is no authentication for the
root shell.</para></listitem>
</varlistentry>
<varlistentry><term><literal>debug1</literal></term> <varlistentry><term><literal>debug1</literal></term>
<listitem><para>Request an interactive shell in stage 1 of the <listitem><para>Start an interactive shell in stage 1 before
boot process (the initial ramdisk). The shell gets started before
anything useful has been done. That is, no modules have been anything useful has been done. That is, no modules have been
loaded and no file systems have been mounted, except for loaded and no file systems have been mounted, except for
<filename>/proc</filename> and <filename>/proc</filename> and
<filename>/sys</filename>.</para></listitem> <filename>/sys</filename>.</para></listitem>
</varlistentry> </varlistentry>
<varlistentry><term><literal>debugtrace</literal></term>
<listitem><para>Print every shell command executed by the stage 1
and 2 boot scripts.</para></listitem>
</varlistentry>
<varlistentry><term><literal>single</literal></term> <varlistentry><term><literal>single</literal></term>
<listitem><para>Boot into rescue mode (a.k.a. single user mode). <listitem><para>Boot into rescue mode (a.k.a. single user mode).
This will cause systemd to start nothing but the unit This will cause systemd to start nothing but the unit

View File

@ -1,6 +1,7 @@
#! @shell@ #! @shell@
targetRoot=/mnt-root targetRoot=/mnt-root
console=tty1
export LD_LIBRARY_PATH=@extraUtils@/lib export LD_LIBRARY_PATH=@extraUtils@/lib
export PATH=@extraUtils@/bin:@extraUtils@/sbin export PATH=@extraUtils@/bin:@extraUtils@/sbin
@ -17,37 +18,31 @@ An error occured in stage 1 of the boot process, which must mount the
root filesystem on \`$targetRoot' and then start stage 2. Press one root filesystem on \`$targetRoot' and then start stage 2. Press one
of the following keys: of the following keys:
i) to launch an interactive shell; EOF
if [ -n "$allowShell" ]; then cat <<EOF
i) to launch an interactive shell
f) to start an interactive shell having pid 1 (needed if you want to f) to start an interactive shell having pid 1 (needed if you want to
start stage 2's init manually); or start stage 2's init manually)
*) to ignore the error and continue. EOF
fi
cat <<EOF
r) to reboot immediately
*) to ignore the error and continue
EOF EOF
read reply read reply
# Get the console from the kernel cmdline if [ -n "$allowShell" -a "$reply" = f ]; then
console=tty1 exec setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console"
for o in $(cat /proc/cmdline); do elif [ -n "$allowShell" -a "$reply" = i ]; then
case $o in echo "Starting interactive shell..."
console=*) setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail
set -- $(IFS==; echo $o) elif [ "$reply" = r ]; then
params=$2 echo "Rebooting..."
set -- $(IFS=,; echo $params) reboot -f
console=$1 else
;; echo "Continuing..."
esac fi
done
case $reply in
f)
exec setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console" ;;
i)
echo "Starting interactive shell..."
setsid @shell@ -c "@shell@ < /dev/$console >/dev/$console 2>/dev/$console" || fail
;;
*)
echo "Continuing...";;
esac
} }
trap 'fail' 0 trap 'fail' 0
@ -76,6 +71,12 @@ mount -t securityfs none /sys/kernel/security
export stage2Init=/init export stage2Init=/init
for o in $(cat /proc/cmdline); do for o in $(cat /proc/cmdline); do
case $o in case $o in
console=*)
set -- $(IFS==; echo $o)
params=$2
set -- $(IFS=,; echo $params)
console=$1
;;
init=*) init=*)
set -- $(IFS==; echo $o) set -- $(IFS==; echo $o)
stage2Init=$2 stage2Init=$2
@ -84,13 +85,19 @@ for o in $(cat /proc/cmdline); do
# Show each command. # Show each command.
set -x set -x
;; ;;
initrd.shell_on_fail)
allowShell=1
;;
debug1) # stop right away debug1) # stop right away
allowShell=1
fail fail
;; ;;
debug1devices) # stop after loading modules and creating device nodes debug1devices) # stop after loading modules and creating device nodes
allowShell=1
debug1devices=1 debug1devices=1
;; ;;
debug1mounts) # stop after mounting file systems debug1mounts) # stop after mounting file systems
allowShell=1
debug1mounts=1 debug1mounts=1
;; ;;
stage1panic=1) stage1panic=1)
@ -180,7 +187,7 @@ onACPower() {
checkFS() { checkFS() {
local device="$1" local device="$1"
local fsType="$2" local fsType="$2"
# Only check block devices. # Only check block devices.
if [ ! -b "$device" ]; then return 0; fi if [ ! -b "$device" ]; then return 0; fi
@ -219,7 +226,7 @@ checkFS() {
if test $(($fsckResult | 2)) = $fsckResult; then if test $(($fsckResult | 2)) = $fsckResult; then
echo "fsck finished, rebooting..." echo "fsck finished, rebooting..."
sleep 3 sleep 3
reboot reboot -f
fi fi
if test $(($fsckResult | 4)) = $fsckResult; then if test $(($fsckResult | 4)) = $fsckResult; then