CNT4603 - 2019
Assignment 2
No journal due

Assignment: Working with initrd


Today we are going to explore the early runtime of your new Linux installation.

The early runtime of your Linux installation uses an "initrd" as its first file system, before it "pivots" over to the actual filesystem that you have on /dev/sda1.

You can read a bit about how Debian has configured its early runtime. This early filesystem is created using klibc rather than glibc, and is quite different than your ordinary filesystem based on glibc dependencies. (It's also a bit fragile, as illustrated by postings like this.)

For this assignment, we are going to undertake the somewhat delicate task of modifying this filesystem by hand. It resides in your boot directory under a filename beginning with "initrd". It's probably about 2 or 3 megabytes in size.

It's actually an ordinary "cpio" file that's been compressed with gzip. The "cpio" format is actually one of the oldest Unix ones, even predating tar format. It had fallen pretty much into disuse when it was revived by RedHat for its RPM format and for use in creating Linux early runtime systems.

So the first thing to do is boot (or reboot) your Debian machine. You want to catch this boot fairly early, so pressing the up or down arrows might be a good idea while you try to adjust your monitor to the "digital" input source.

Once you get to the boot screen, choose "use advanced options". Scroll down a bit and add "break=premount" to the "linux" boot line after the "ro" bit, to force the kernel to stop before it "pivots", leaving you in the initial RAM filesystem rather than your ordinary root filesystem:

Now you can use F10 to go ahead and continue the boot, which should take you to:

If you do a "cd" into /bin/, you should see that while there are lots of "programs", that these are mostly hard links to busybox (try "ls -li".) It turns out that ip is linked in the directory /sbin/, but not in /bin/.

Let's fix that. Do an "exit", and let your system boot up.

Become root (the su program is handy for this, but if you prefer to use a root login from a virtual terminal, that's fine also — it's the way that I did the assignment).

Create a subdirectory something like "new-initrd"; I used "/tmp/new-initrd", but you can do this in your /root/ home directory if you prefer (if you end up doing this multiple times, you might well appreciate having it around after each reboot!)

Now you can "cd new-initrd && zcat /boot/initrd-somevers.gz | cpio -id" to extract your current initrd to your subdirectory.

Change directory down into "bin/"; there you should see the same exact structure as you saw in premount. Do a "ln busybox ip" to create the new hardlink:

Now create a new gzipped initrd, using "cpio" with both "--create" and "--format='newc'" (the man page for cpio's various format is here) and piping to gzip:

Copy the old version to an "ORIG" file:

Install your new version into "/boot/":

At this point, you might want to do a ls -l /boot to verify that you have your new initrd file there, that you have your backup of the original file there with "-ORIG" appended, and that these two files are roughly the same size.

Now it's time to reboot, again specifying "break=premount":

Change directory into "/bin/", and, voila, you should see your shiny new ip command:

It is very likely that your inode numbers have changed since you have built an entirely new initrd image.