User-mode Linux/System testing with UML
Obtaining User-Mode Linux
Before you can use user-mode Linux, you must be using a non-NPTL profile, and you must be using < (less than) glibc-2.4. Follow the instructions for changing profiles. You will need to run emerge -e @world after switching to a non-NPTL profile.
As the user-mode Linux website states, user-mode Linux allows a user to "run Linux inside itself". Specifically, user-mode Linux provides a virtual machine on which a user can "[r]un buggy software, experiment with new Linux kernels or distributions, and poke around in the internals of Linux, all without risking your main Linux setup." Experimental changes to Gentoo core packages such as sys-apps/baselayout or sys-libs/glibc have the potential to break the system and render it unbootable; with user-mode Linux we can test these changes without having to worry about breaking the live system.
Most 2.6 kernels have UML support. Although you can use your current kernel sources, it might be wiser to keep the UML kernel tree(s) separate. After all, you'll be building a new kernel with a different configuration and you might want to have heterogeneous systems on your main Linux system (several different UML kernels).
So download a nice kernel tree (like the vanilla one from kernel.org) and extract it to some local development location.
Next, configure this UML kernel as you would do for any other system, but append
ARCH=um so that the kernel build software knows that the kernel is meant to run as a guest process on the main system.
cp linux /usr/local/bin/linux
The ARCH=um fragment is extremely important!
On a default Gentoo system, /usr/local/bin is in your
$PATH. If it isn't, you should find a definition of
PATH in the /etc/profile and fix it:
echo $PATH | grep /usr/local/bin
Don't forget to run
source /etc/profile for the change to take effect.
For the user-mode Linux kernel to properly boot a Gentoo system the kernel needs to be configured to not automatically mount /dev (devfs) by default. Also, you will almost certainly want to make sure that you have tmpfs (the "Virtual Memory Filesystem") compiled in, since by default the Gentoo Linux bootscripts store their information in a small tmpfs partition. (The binary kernels available from the user-mode website do automatically mount /dev, and they don't have tmpfs compiled in; don't bother with them).
I highly recommend reading the user-mode Linux documentation, but the basic idea is that running the /usr/local/bin/linux program boots the user-mode kernel and tries to bring up the system stored in the file root_fs that should be located in the current working directory.
It won't hurt to also install the user-mode Linux tools.
emerge --ask sys-apps/usermode-utilities
These tools facilitate networking (among other things) between the user-mode Linux virtual system and the host Linux system.
Making the Gentoo chroot
The root_fs file needed for user-mode Linux is a single file that contains an entire Gentoo Linux file system. To generate this file you will need to have loopback device support enabled in the host (non-user-mode) kernel.
Generating the root_fs file itself will be our last step. First we will generate a Gentoo file system in an ordinary chroot. We need the stage tarball available, which could be downloaded separately, extracted from an Installation CD, or extracted from an Installation CD .iso.
mount -o loop /path/to/install-<TAB>.iso /mnt/loop
Setting up the chroot is essentially identical to an ordinary Gentoo Linux build.
tar xvjpf /path/to/stage3.*.tar.bz2
Go ahead and unmount the .iso. You don't need it anymore.
Build the system in the usual fashion: chroot into /mnt/gentoo and follow the Gentoo installation instructions.
Add any additional packages you desire. Feel free to give your virtual Gentoo system a hostname, if you so desire. In /etc/fstab you will want /dev/ROOT to be /dev/ubda, with a fs type of either ext2, ext3, or reiserfs. Set /dev/SWAP to be /dev/ubdb, and comment out /dev/BOOT.
At this point, remember to set your root password.
Now we need to make some changes to the boot scripts. Remove consolefont and keymaps from the boot runlevel:
rc-update del consolefont boot
rc-update del keymaps boot
Exit the chroot, unmount all of the bind mounts, tar up the new Gentoo distro, and clean up.
tar cvjpf ~/gentoo.tbz2 *
rm -rf /mnt/gentoo
Our Gentoo chroot is nearly 300 MB in size, so root_fs needs to be at least that size. We'll choose 0.5 GB as a reasonable size.
dd if=/dev/zero of=root_fs seek=500 count=1 bs=1M
mke2fs -F root_fs
mount -o loop root_fs /mnt/loop
tar xvjpf gentoo.tbz2 -C /mnt/loop
It would also be nice to have a 0.5 GB swap partition.
dd if=/dev/zero of=swap_fs seek=500 count=1 bs=1M
mkswap -f swap_fs
Now see if it works!
linux ubd0=root_fs ubd1=swap_fs
User-mode Linux uses xterms for the virtual consoles that are run at boot time, so you need to make sure that the terminal from which you run user-mode Linux has $DISPLAY properly set (along with proper xhost/xauth permissions).
With any luck you should be able to log into your user-mode Linux Gentoo system. The only thing keeping this user-mode Linux version of Gentoo from being fully functional is networking from the virtual machine to the host.
If you receive "No space left on device" errors, you may need to allocate more memory to your user mode system by appending
mem=xxxMBto the end of the kernel thread line. For example:
linux ubd0=root_fs ubd1=swap_fs mem=128MB.
Using an Existing Network
Make sure that the host kernel has the following settings compiled as modules:
Networking --> IP: Netfilter Configuration --> IP tables support --> Full NAT --> <M> MASQUERADE target support Network Device Support --> <M> TUN/TAP Support
Run the following commands on the host machine:
If you receive a FATAL error here, try deleting /dev/net/tun and retry.
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward
The iptables line sets up IP Masquerading between the private network that our user-mode system will be on and the internet (reachable via
eth0 in our case). The echo line then turns on packet forwarding between the private network and the interface that the default gateway is on (eth0 for us).
Now we bring up the user-mode system and see if networking is functional.
linux ubd0=root_fs ubd1=swap_fs eth0=tuntap,,,192.168.0.254
Login to user-mode system, and then run:
ifconfig eth0 192.168.0.1 up
ping -c 2 192.168.0.254
PING 192.168.0.254 (192.168.0.254): 56 octets data 64 octets from 192.168.0.254: icmp_seq=0 ttl=255 time=0.8 ms 64 octets from 192.168.0.254: icmp_seq=1 ttl=255 time=0.6 ms --- 192.168.0.254 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.6/0.7/0.8 ms
route add default gw 192.168.0.254
Kernel IP routing table Destination Gateway Genmask Flags MSS Window irtt Iface 192.168.0.0 0.0.0.0 255.255.255.0 U 40 0 0 eth0 0.0.0.0 192.168.0.254 0.0.0.0 UG 40 0 0 eth0
scp email@example.com:/etc/resolv.conf /etc/resolv.conf
ping -c 2 www.gentoo.org
PING www.gentoo.org (18.104.22.168): 56 octets data 64 octets from 22.214.171.124: icmp_seq=0 ttl=240 time=119.6 ms 64 octets from 126.96.36.199: icmp_seq=1 ttl=240 time=92.0 ms --- www.gentoo.org ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 92.0/105.8/119.6 ms
On the user-mode system we assign the user-mode eth0 interface the private IP address 192.168.0.1 and bring up the interface. The host has private IP address 192.168.0.254, and we ping it to make sure that our networking is, indeed, up. The route line adds a default gateway, namely our host, we use scp to retrieve a working /etc/resolv.conf (if necessary), and we ping www.gentoo.org to make sure that name resolution (and general access to the internet) is working from our user-mode system. Now the user-mode system can emerge at will!
Using a Virtual Network
UML supports an additional networking facility, accessible only to UML guests. The sys-apps/usermode-utilities package provides a tool called uml_switch which defines the end points of the switch.
If the switch information should stay in the foreground:
uml_switch -unix ~/tmp/switch.sock
If it should be backgrounded:
uml_switch -unix ~/tmp/switch.sock &> ~/tmp/switch.log &
To start the UML instances on the switch, run the next command. Your (virtual) network interface will be connected to the uml_switch process and will be using the given MAC address.
linux ubd0=first_rootfs ubd1=first_swapfs eth0=daemon,10:00:01:02:00:00,,~/tmp/switch.sock
You can still connect the system to the existing network, or have a second process attached to both the virtual one and the existing one:
linux ubd0=second_rootfs ubd1=second_swapfs eth0=daemon,10:00:01:02:00:01,,~/tmp/switch.sock eth1=tuntap,,,192.168.1.43
More information about the tuntap setting can be found in the previous section.
Testing the .iso
Perhaps the true ideal of Gentoo Linux testing would be to boot the .iso with user-mode Linux and do the complete Gentoo install from within the user-mode Linux virtual system.
Booting the .iso, or actually the initrd from the .iso, is pretty straightforward.
mount -o loop /path/to/install-<TAB>.iso /mnt/loop
cp /mnt/loop/isolinux/gentoo.igz .
linux load_ramdisk=1 prompt_ramdisk=0 ramdisk_size=22000 initrd=rescue.gz root=/dev/ram0 ubd0=root_fs ubd1=swap_fs ubd2=/dev/cdroms/cdrom0 eth0=tuntap,,,192.168.0.254
Now you can follow the Gentoo install doc essentially verbatim, although you'll need to know that the root file system will be /dev/ubd/0, the swap "partition" will be /dev/ubd/1, and the CDROM will be /dev/ubd/2.
- http://edeca.net/articles/bridging/index.html - Bridging with UML
- http://user-mode-linux.sourceforge.net/ - UML Homepage
- http://www.theshore.net/~caker/uml/ - Caker's UML Notes
- http://sourceforge.net/mailarchive/forum.php?forum_id=3647 - UML Mailinglist archives
This article is based on a document formerly found on our main website gentoo.org.
The following people have contributed to the original document: Grant Goodyear, John Davis, Sven Vermeulen, and Benny Chuang
They are listed here as the Wiki history does not provide for any attribution. If you edit the Wiki article, please do not add yourself here; your contributions are recorded on the history page.