intiramfs / initramfs-tools / busybox / dropbear (Ubuntu)
Originally written for Ubuntu 18.04
Changes in Ubuntu 20.04:
- /etc/dropbear-initramfs has moved to /etc/dropbear/initramfs (automatically done by upgrade)
Initramfs Introduction
https://wiki.ubuntu.com/Initramfs
- Kernel unpacks initramfs early in the boot process and calls /init
- Initramfs is cpio packed inital root filesystem
- It is mainly used for measures to mount the real root filesystem.
Examples: load kernel drivers for disk access (raid), or manage encrypted root unlocking - It usually includes busybox shell and commands.
Busybox
https://busybox.net/
https://busybox.net/downloads/BusyBox.html
Many unix programs in simplified form in a single executable.
Note: Ubuntu includes only a very limited version of busybox.
To install full version see: https://www.ullright.org/ullWiki/show/install-full-busybox-in-initramfs-ubuntu-18-04
Ubuntu initramfs-tools
http://manpages.ubuntu.com/manpages/bionic/man8/initramfs-tools.8.html
Handles creation of initramfs.
After changing config, adding hooks or script you have to re-generate initramfs with
- update-initramfs -u
Config file:
-
vi /etc/initramfs-tools/initramfs.conf
View initramfs content:
- lsinitramfs /initrd.img
Extract initramfs to check content of files:
- mkdir /tmp/initramfs-content
- cd /tmp/initramfs-content
- unmkinitramfs /initrd.img .
- # do stuff like ls -la, cat /dir/foo
Useful commands inside initramfs
Get process id by complex name
- ps | grep 'busybox2 crond' | grep -v grep | awk '{ print $1 }'
Kill procress by complex name
- kill $(ps | grep 'busybox2 crond' | grep -v grep | awk '{ print $1 }')
Output to main terminal screen
- echo foo > /dev/tty0
Initramfs generation
There are distribution hooks and scripts in /usr/share/initramfs-tools and custom hooks and scripts can be placed in /etc/initramfs-tools.
The order of the hooks and scripts can be influenced by the prequisites "PREREQ".
But the scripts in /usr/share/initramfs-tools are always executed before the hooks in /etc/initramfs-tools!
Hooks
Initramfs hooks allow to modify initramfs. E.g. install executables or copy files.
System hooks from packages (like dropbear) are in
-
/usr/share/initramfs-tools/hooks/
Custom user defined hooks go into
-
/etc/initramfs-tools/hooks/
It is not possible to prevent execution of distribution hooks in "/usr/share/initramfs-tools/hooks/".
So you can only add a custom hook in /etc/initramfs-tools/hooks/ with fixes, eg. copy a patched file.
Boot Scripts
Scripts are run inside of initramfs at different stages.
Boot scripts from packages are in
-
/usr/share/initramfs-tools/scripts/
Path for custom boot scripts:
-
/etc/initramfs-tools/scripts/
Distribution boot scripts in /usr/share/initramfs-tools/scripts/ can simply be overwritten by putting a script with the same name in /etc/initramfs-tools/scripts/.../...
Subdirectories of different stages:
-
init-top the scripts in this directory are the first scripts to be executed after
sysfs and procfs have been mounted. It also runs the udev hook for populating the
/dev tree (udev will keep running until init-bottom). -
init-premount happens after modules specified by hooks and /etc/initramfs-
tools/modules have been loaded.-
e.g. netconf, dropbear
-
-
local-top OR nfs-top After these scripts have been executed, the root device node
is expected to be present (local) or the network interface is expected to be usable
(NFS).-
eg cryptroot, mdadm
-
-
local-block These scripts are called with the name of a local block device. After
these scripts have been executed, that device node should be present. If the
local-top or local-block scripts fail to create the wanted device node, the local-
block scripts will be called periodically to try again. -
local-premount OR nfs-premount are run after the sanity of the root device has been
verified (local) or the network interface has been brought up (NFS), but before the
actual root fs has been mounted. -
local-bottom OR nfs-bottom are run after the rootfs has been mounted (local) or the
NFS root share has been mounted. -
init-bottom are the last scripts to be executed before procfs and sysfs are moved
to the real rootfs and execution is turned over to the init binary which should now
be found in the mounted rootfs. udev is stopped.
Examples
Package hooks
Interesting examples: (needs "apt install dropbear")
- vi /usr/share/initramfs-tools/hooks/dropbear
- vi /usr/share/initramfs-tools/hooks/cryptroot-unlock
- adds message to /etc/motd (message of the day)
Custom hook to install additional executables
Executables are simply copied from the normal linux system.
If not installed, use "apt install xxx" first.
- vi /etc/initramfs-tools/hooks/addons
-
#!/bin/sh # add hookscripts which need to be executed before this script PREREQ="dropbear" prereqs() { echo "$PREREQ" } case "$1" in prereqs) prereqs exit 0 ;; esac # Load helper functions . /usr/share/initramfs-tools/hook-functions # Helper function to copy an executable to be available in initramfs copy_exec /usr/bin/jq /bin copy_exec /usr/bin/curl /bin copy_exec /usr/bin/dbclient /bin
-
- chmod 755 /etc/initramfs-tools/hooks/addons
- update-initramfs -u
Patch distribution initramfs files
Example: Ubuntu 22.04 /sbin/dhclient-script uses commands/options which are not available in initramfs
Prepare patch file
- cd /etc/initramfs-tools/hooks/
- cp /sbin/dhclient-script /tmp
- vi /tmp/dhclient-script
-
#line 97 # PATCH for initramfs: #if [ -f $resolv_conf ]; then # chown is not available in initramfs #chown --reference=$resolv_conf $new_resolv_conf # initramfs chmod does not have option --reference #chmod --reference=$resolv_conf $new_resolv_conf #fi
-
- diff --unified /sbin/dhclient-script /tmp/dhclient-script > /etc/initramfs-tools/hooks/dhclient-script.22.04.patch
-
You would apply the patch like this
-
patch /mydir/mytarget -i /etc/initramfs-tools/hooks/dhclient-script.22.04.patch
-
-
And check it with:
-
tail --lines=+96 /tmp/dhclient-script | head --lines=10
-
Create hook to apply patch
- vi /etc/initramfs-tools/hooks/dhclient-script-patch
-
#!/bin/sh # Patch dhclient-script to not use commands/options not available in initramfs # $DESTDIR/sbin/dhclient-script is originally copied to initramfs by /usr/share/initramfs-tools/hooks/zz-dhclient # To be idempotent never reverse the patch (--forward) and don't create .rej files # We also swallow the warning "Reversed (or previously applied) patch detected! Skipping patch. 1 out of 1 hunk ignored" with " > /dev/null" # Further more we need to catch the exit code 1 of "hunks ignored". (appended " || [ $? -eq 1 ]") #tail --lines=+96 /sbin/dhclient-script | head --lines=10 #tail --lines=+96 $DESTDIR/sbin/dhclient-script | head --lines=10 patch --silent --forward --reject-file=- -i /etc/initramfs-tools/hooks/dhclient-script.22.04.patch $DESTDIR/sbin/dhclient-script > /dev/null || [ $? -eq 1 ] #tail --lines=+96 /sbin/dhclient-script | head --lines=10 #tail --lines=+96 $DESTDIR/sbin/dhclient-script | head --lines=10
-
-
chmod 755 /etc/initramfs-tools/hooks/dhclient-script-patch
-
update-initramfs -u
dropbearconvert
Converts openssh private key to dropbear format
- usr/lib/dropbear/dropbearconvert
-
All arguments must be specified Usage: /usr/lib/dropbear/dropbearconvert <inputtype> <outputtype> <inputfile> <outputfile> CAUTION: This program is for convenience only, and is not secure if used on untrusted input files, ie it could allow arbitrary code execution. All parameters must be specified in order. The input and output types are one of: openssh dropbear Example: dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key /etc/dropbear_rsa_host_key
-
dropbearkey
Show public key from private key:
- dropbearkey -y -f ./root/ssh/id_dropbear
initramfs / dropbear create user / password
check this out: /usr/share.../hooks/dropbear
- for x in passwd group; do echo "$x: files"; done >"$DESTDIR/etc/nsswitch.conf"
echo "root:*:0:0::${home#$DESTDIR}:/bin/sh" >"$DESTDIR/etc/passwd"
echo "root:!:0:" >"$DESTDIR/etc/group" -
# busybox2 passwd root
Changing password for root
New password:
Bad password: too weak
Retype password:
passwd: password for root changed by root
# cat /etc/passwd
root:$5$A3HlvdYi1hT3drz4$z4DFGusaqsQMQafFpKyuCQDBEOWfEwYCbqzKaioqQlB:0:0::/root:/bin/sh -
echo "foo" | openssl passwd -stdin -6 -salt verySalty
$6$9rQrmF1Y$sMMnndQxV3NQ3T0LRcBS/7ZXHpJOv.M7svlP9sUxcn21yKlcD5ozvFGmu2B4pgesECc7LXP96XfK1FXGjbjra1
dropbear get host key
@initramfs:
-
host key:
-
dropbearkey -y -f /etc/dropbear/dropbear_rsa_host_key
-
Public key portion is: ssh-rsa AAA...1h1 root@myhostname Fingerprint: md5 63:ab...fb:1b
-
-
- user ssh key:
- dropbearkey -y -f /root/.ssh/id_dropbear
@host normally booted:
- dropbearkey -y -f /etc/dropbear-initramfs/dropbear_rsa_host_key
Get only key portion:
- dropbearkey -y -f /etc/dropbear-initramfs/dropbear_rsa_host_key | tail -2 | head -1