I'm building a very minimal Linux system that just consists of the kernel (v4.1-rc5) and an initramfs populated with busybox (v1.23.2). It works fine for the most part, but I observe a difference in behavior of command execution in /init whether I'm using an embedded initramfs vs. an external one.
The /init script is:
#!/bin/sh
dmesg -n 1
mount -t devtmpfs none /dev
mount -t sysfs none /sys
mount -t proc none /proc
echo "Welcome"
while true
do
setsid cttyhack /bin/sh
done
Then I either set the CONFIG_INITRAMFS_SOURCE option in the kernel .config to the directory containing all the folders for the initramfs, or I run
find . | cpio -H newc -o | gzip > ../rootfs.cpio.gz
to build it.
When I then compile the kernel, either with or without CONFIG_INITRAMFS_SOURCE set, I end up with two variants of my system:
-
bzImage with initramfs embedded
-
bzImage + rootfs.cpio.gz (external initramfs)
when I now start those using qemu
qemu-system-x86_64 -enable-kvm -kernel bzImage
or
qemu-system-x86_64 -enable-kvm -kernel bzImage -initrd rootfs.cpio.gz
I get the following difference in behavior:
with version 2 (external initramfs) everything works fine, "Welcome" is displayed and I get a prompt. With version 1 however (embedded initramfs) I get the warning
unable to open an initial console
"Welcome" is not displayed, and I get my prompt.
As far as I understand the process, those two versions of initramfs should contain the same files, since I build it (or have the kernel build it) from an identical folder.
I wonder if anyone can help me with an explanation for this behavior?
* UPDATE *
as mikeserv said in the comments, The kernel includes a minimal embedded initramfs per default. This is still present when using an external one, but gets overwritten if you embed your own. I found that contrary to the specification, this is indeed not empty, but contains a dev folder, a root folder and the /dev/console device. This device then gets used when using an external initramfs, but overwritten if you embed your own. So you have to include the /dev/console device in your initramfs source mknod -m 622 initramfs_src/dev/console c 5 1
when embedding your own.
Thanks a lot to mikeserv, frostschutz and JdeBP for helping me get my head around that!
Best Answer
Are they really identical?
The built-in one you can find in
/usr/src/linux/usr/initramfs_data.cpio.gz
or extract it from the bzImage as described here: https://wiki.gentoo.org/wiki/Custom_Initramfs#SalvagingIf you use that built-in one and use it as external one instead, does it work?
If it's still different, is the kernel itself identical? (compare
/proc/config.gz
for both)There should be some difference. I'm not aware that the kernel cares where the initramfs came from. I'd sooner suspect
qemu
of using different settings when passing the-initrd
parameter...On a sidenote, your
/init
looks like its spawning infinite shells to me.setsid
is notexec
. Am I wrong?