Custom initrd init script: how to create /dev/initctl

11,246

Solution 1

As phresus answered, init creates /dev/initctl.

The problem I was having was that my /linuxrc script was not running with PID 1. Thus, when it executed init, it also was not running with PID 1. init not running as PID 1 behaves as telinit.

To get /linuxrc to run with PID 1, I needed the following on the kernel boot line: root=/dev/ram0 rw init=/linuxrc, as described in this forum.

Now it's all working. With the VM booted, the output of mount is

aufs on / type aufs (rw)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,gid=5,mode=620)
tmpfs on /dev/shm type tmpfs (rw)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

Yay! BTW, is it kosher to mark my own answer as "the answer"?

Solution 2

If you're already using a virtualization solution, why are you going through all this trouble? The simplest solution would be to use something like LVM on your host, which already has snapshot support, and present a snapshot to your VM. That is:

  • Create a logical volume (LV) that will hold your root filesystem.
  • Create a snapshot of this LV
  • Configure your VM to boot from the snapshot.

If you want to revert back to the clean filesystem, delete the snapshot and recreate it. Easy, and no fiddling about with initrd or aufs -- in fact, it doesn't require any modifications to the guest OS.

Share:
11,246

Related videos on Youtube

dilip
Author by

dilip

Updated on September 17, 2022

Comments

  • dilip
    dilip over 1 year

    I have a virtual machine (VMM is Xen 3.3) equipped with two IDE HDD's (/dev/hda and /dev/hdb). The root file system is in /dev/hda1, where Scientific Linux 5.4 is installed. /dev/hdb contains an empty ext2 file system.

    I want to protect the root file system from writes by the VM by using aufs (AnotherUnionFS) to layer a writable file system on top of the root file system. The changes to / will be written to the file system located on /dev/hdb. (Furthermore, outside the VM, the file backing the /dev/hda will also be set to read-only permissions, so the VMM should also prevent the VM from modifying at that level.) (The purpose of this setup: be able to corrupt a virtual machine using software-implemented fault injection but preserve the file system image in order to quickly reboot the VM to a fault-free state.)

    How do I get an initrd init script to do the necessary mounts to create the union file system?

    I've tried 2 approaches:

    1. I've tried modifying the nash script that mkinitrd creates, but I don't know what setuproot and switchroot do and how to make them use my aufs as the new root. Apparently, nobody else here knows either. (EDIT: I take that back.)

    2. I've tried building a LiveCD (using linux-live-6.3.0) and then modifying the Bash /linuxrc script from the generated initrd, and I got the mounts correct, but the final /sbin/init complains about /dev/initctl.

    Specifically, my /linuxrc mounts the aufs at /union. The last few lines of /linuxrc effectively do the following:

    cd /union
    mkdir -p mnt/live
    pivot_root . mnt/live
    exec sbin/chroot . sbin/init </dev/console >/dev/console 2>&1
    

    When init starts, it outputs something like init: /dev/initctl: No such file or directory. What is supposed to create this FIFO? I found no such filename in the original linuxrc and liblinuxlive scripts.

    I tried creating it via "mkfifo /dev/initctl", but then init complained about a timeout opening or writing to the FIFO.

    Would appreciate any help or pointers. Thanks.

  • dilip
    dilip over 14 years
    Hmm wow. I had no idea LVM could manage <b>writable</b> snapshots. I will consider implementing this option. The LVM HOWTO explicitly mentions this as [a solution for VMs][1]. [1]:tldp.org/HOWTO/LVM-HOWTO/snapshotintro.html
  • dilip
    dilip over 14 years
    there is an initdefault entry in my /etc/inittab. I just discovered by running ash within /linuxrc just before the pivot_root that /linuxrc is not running as PID 1 (its PID was 300). That's odd. Doesn't this mean that when it exec's init, init will behave as telinit, since its PID is not 1? Frustrating.
  • user1283002
    user1283002 over 14 years
    You can either pass init=/linuxrc or rename /linuxrc to /sbin/init (which is just a shell script in the initrd).
  • dilip
    dilip over 14 years
    I tried adding init=/linuxrc and it still didn't run with PID 1. Apparently I also needed root=/dev/ram0 rw. I have no idea why this would make a difference. Any enlightenment would be appreciated!
  • user1283002
    user1283002 over 14 years
    The initrd is pulled out to a ramdisk, and that's treated as your root until switchroot or pivot_root. Why it's necessary for linuxrc to get PID 1, I'm not sure about
  • user1283002
    user1283002 over 14 years
    Go for it! It's your question, after all, and none of us got you all the way there.