tar2loop: doing a initrd image without being root

In any situation in which being root is possible this is an overcomplicated solution to a simple problem. However not always being root is possible and in that few cases having an automatic tool which converts a tarball in a loop/ext2 images is very useful. I am going to explain how to create this automatic tool which you can modify to adapt your needs.

Introducing the problem

The fastest way to do a initrd image is mount a loop and populate it:

dd if=/dev/zero of=initrd.img bs=1 count=1 seek=2M
yes | mke2fs initrd.img
mkdir -p /mnt/loop
mount -o loop -t ext2 initrd.img /mnt/loop

but this require root password and to avoid being root /etc/tab should allow it:

/tmp/image /tmp/loop ext2 users,loop,dev 0 0

apart security risks this solution should not work fine for a multi-users enviroment.

In a single user enviroment being root could not a problem but Linux Embedded hackers working in a big company environments could proficiently operate in multi users server environments too. In order to make /etc/fstab multi-user friendly could be changed as follows:

for USER in $ALL-USERS; do
sudo - $USER mkdir -p /tmp/image-$USER /tmp/loop-$USER
echo "/tmp/image-$USER /tmp/loop-$USER ext2 users,loop,dev 0 0" »/etc/fstab
done

Server admin should append one of this row for each $USER it would enable to made initrd images and users should not delete their directories otherwise others could re-create their directories and interfere with their privileges. Even system admin accept this solution, it does not one user but multi task safe. In facts a user could not mount two loops but just one. Finally loop device are finite and could be less than users needs.

Introducing a solution

Linux User Mode could solve all problems related to previous situations and needs. Linux User Mode allow to launch another kernel and create a running jail where user could be a local root. Automation of this process could be done with four parts and two scripts.

user land script

The first is following:

mkdir -p tar2loop
cd tar2loop
cat > tar2loop.sh « EOF

#!/bin/bash 
#  
# (C) 2008, Roberto A. Foglietta <me@roberto.foglietta.name>
#     tar2loop and this script are released under GPL v2 only terms
#
unset DISPLAY XTERM
T2LP=$(dirname $0)/tar2loop
test -d $T2LP/bin || T2LP=$(dirname $0)
export PATH=$PATH:$T2LP/bin
copts="expert noprobe text mem=16M ubda=$T2LP/tar2loop.rootfs"
case "x$1" in
        x--editrc) shift
                   chmod u+w tar2loop.rootfs
                   umlinux $copts ubdb="$1" ubdc="$2"
                   ;;
        x--dumpfs) test -e "$2" || cat tar2loop.rootfs > "$2.tar" 
                   chmod a-w tar2loop.rootfs
                   umlinux ro halt dump $copts ubdc="$2.tar"
                   bzip2 -9 "$2.tar"; ls -al "$2.tar.bz2"
                   ;;
        *) test -e "$1" || exit 1
           test -e "$2" || exit 2
           chmod a-w tar2loop.rootfs
           time umlinux ro halt $copts ubdb="$1" ubdc="$2" 
           ;;
esac

EOF
chmod 755 tar2loop.sh

user mode linux kernel and tools

After that go to downloads page and download the User Mode Linux kernel and User Mode Linux utilities. Kernel could be used in pre compiled form or could be compiled from sources following this manual. Another possibilities is to install User Mode Linux kernel and tools from server distribution package system but this last solution requires your system administrator collaborate.

In order to not annoy the sysadmin with its prime-role dute, serving the users, it is better do it by yourself. Following this always working policy the Use Mode Linux kernel should be copied in file tar2tool/bin/umlinux and make it executable:

mkdir bin
cd bin
wget -c http://user-mode-linux.sourceforge.net/linux-2.6.24-rc7.bz2
bunzip linux-2.6.24-rc7.bz2
mv -f linux-2.6.24-rc7 umlinux
chmod 755 umlinux
cd ..

User Mode Linux tools could not be retrieved just compiled and compile it is necessary, after that copy them in tar2loop/bin directory:

wget http://user-mode-linux.sourceforge.net/uml_utilities_20070815.tar.bz2
tar xvjf uml_utilities_20070815.tar.bz2
cd tools-20070815
make
mkdir _install
make DESTDIR=_install install
cp -f $(find _install -type f) ../bin
cd ..

user mode linux root file system

User Mode Linux needs to run on a root file system which itself a initrd image. This compressed root file system image contains all the utilities busybox and mk2efs and a script /etc/rc.sh which automagically let it able to transform a tarball file into a initrd image. Download and explode it with bunzip2 and save in tar2loop directory together tar2loop.sh script.

If you like to build by yourself this rootfs you need to download busybox and e2fsprogs. About the frist package this config is enought for the purpose and about the second just compiling mke2fs are needed. Please note both of these two packages are needed to be compiled statically linked.

User Mode Linux root file system structure:

  • root directory trees in particular:
    • /etc, /root, /tmp. /proc, /mnt/loop. /var/log
  • devices nodes which populates /dev
  • busybox which populates these:
    • /bin, /sbin. /usr/sbin, /usr/bin and /linuxrc
  • /sbin/mke2fs
  • /etc/fstab soft linked to /proc/mounts
  • /etc/inittab and /etc/shutdown (optional)
  • /etc/rc.sh

rc.sh:

#!/bin/sh
echo 
echo "(C) 2008, Roberto A. Foglietta <me@roberto.foglietta.name>"
echo "    tar2loop and this script are released under GPL v2 only terms"
echo
mount -t proc proc /proc
mount -t tmpfs tmpfs /tmp
mount -o remount,rw /
busybox --install
if cat /proc/mounts 2>/dev/null >/etc/mtab; then
        df
        rm -f /dev/ubd*
        for i in 0 1 2 3 4 5 6 7; do
                mknod /dev/ubd$i b 98 `expr $i \* 16`
        done
else
        echo "**** WARNING: rootfs is in read-only mode"
fi
cat /dev/zero >/dev/ubd2 2>/dev/null
if grep -q " dump " /proc/cmdline; then
        mkdir /tmp/root
        cd /tmp/root
        mkdir -p proc tmp mnt/loop
        tar cvf /tmp/rootfs.tar.bz2 /bin /dev /etc /linuxrc /root /sbin /usr /var proc tmp mnt
        cat /tmp/rootfs.tar.bz2 >/dev/ubd2
else
        if mke2fs /dev/ubd2 2>/dev/null; then
                mkdir -p /mnt/loop
                if mount -t ext2 /dev/ubd2 /mnt/loop; then
                        n=0
                        for i in x xz xj; do
                                cat /dev/ubd1 | tar -C /mnt/loop -$i 2>/tmp/tar.err && break
                                n=`expr $n + 1`
                        done 
                        if [ $n -ge 3 ]; then
                                grep -v "magic" /tmp/tar.err
                                echo "**** ERROR: tar /dev/ubd1 in /mnt/loop fails"
                        else
                                ls -al /mnt/loop
                        fi
                        df -k | grep -v -e "^rootfs" -e "^/dev/root" -e "^tmpfs"
                        umount /mnt/loop
                else
                        echo "**** ERROR: mount /dev/ubd2 fails"
                fi
        else
                echo "**** ERROR: mke2fs /dev/ubd2 fails"
        fi
fi
grep -q " halt " /proc/cmdline && halt

how to build a proper tarball for tar2loop

Once prepared the tar2loop environment there is another problem: build up a tarball contains proper files with proper permission and ownership. In particular it is impossible for any non root user create or manipulate /dev directory content. To do that there are two ways:

  1. enter in tar2loop in —editrc mode in order to produce a tarball containing a /dev structure exits and use tar —append to add others files and directories;
  2. use fakeroot to produce a tarball containing a /dev structure and to manipulate ownership and permission in a proper way.

The second way has been suggested by Alessandro Rubini who explained me that fakeroot is used for making debian packages. This is the best of two and fakeroot worth the time of compiling and installing it on your system. He shown me also genext2fs which is able to produce EXT2 loop image without being root and also to populate /dev at the same time! However tar2loop approach, as any other solution based on virtualization, allows to create a loop file using any kind of filesystem the kernel supports and exactly the same version you would use and debug. Apart these very special requirements fakeroot combined with genext2fs would solve any others needs and probably suck much lesser.

Hey, you may have learned three things: the existence of two nice tools and to read the whole recipe before put your hands on cooking for yourself!!!

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-Share Alike 2.5 License.