Search

User-Mode Linux

Computers run programs. From the earliest behemoth computers with their
hard-wired programs to modern-day disposable calculators and desktop
PCs, all our computers run some kind of program. John von Neumann cooked
up the concept of storing a computer's program just like any other piece
of data, making way for computers to become multipurpose tools no longer
locked in to one hard-wired function. Soon the concept of an operating
system, or a program to abstract common system-level details like device
management and program execution, was born. It didn't take long for
some crafty system programmers to realize that a single CPU could be made
to perform multiple tasks seemingly at the same time. This gave rise to
the first time-sharing and multitasking/multiuser operating systems. All
modern computers still operate on this same stored program concept. In
the case of a modern personal computer, after switching it on, it runs the
stored program in the BIOS, or firmware, which eventually hands off to a
multistage bootloader, which in turn loads the OS kernel. The kernel
executes and sets up an operating environment in which system resources
like CPU time, memory and devices can be used by programs executed
beneath the kernel. It's all a long chain of stored programs.

The kernel is a program just like any other (albeit a rather complex
one). So, what stops you from executing the kernel just like any other
program? Actually, not much at all. This is what user-mode Linux
(UML) is all about.

The Linux kernel normally runs with special privileges, because it needs
direct access to your hardware. User-mode Linux provides a way to
compile the normal Linux kernel sources so that it can be invoked as a
regular binary program on top of the base Linux kernel. When you run
a kernel on top of the base Linux kernel, you are really running one or
more “guest” Linux systems without any special privileges. (There are
some exceptions. Some software must be installed as root for user-mode
Linux to work.) These guest Linux systems are complete systems that run
in a (mostly) safe environment.

How to Do It

In the remainder of this article, I provide a recipe for getting a
UML system up and running on your host Linux box. Then, we explore
some features and have some fun. The host system I am using for this
demonstration is Fedora Core 4 on an Intel P4 with 1GB of memory, but
almost any system and distribution will work, provided it is running a
recent 2.6 kernel and has a minimum of 256MB of memory.

A guest UML system is just like any other Linux system. It is a
combination of a Linux kernel and a collection of small programs,
libraries and files that make up the operating system. These are provided
in two parts, the kernel and a filesystem image. A filesystem image
is a virtual disk partition. This is what will be mounted and used as the
root filesystem of our UML system. You have the choice to create these
two parts yourself or download them off the Net, ready made from popular
distributions. In the interest of instant gratification, we take the
ready-made route; take a look at the UML Wiki for more information on building your
own filesystems (see the on-line Resources).

Kernels and root filesystem images are available in a number of versions
and distributions. Images of Red Hat, Fedora Core, Debian and a number
of special-purpose distributions are available. I use Debian 3.1
for this demonstration.

COWs Are Your Friends

User-mode Linux has one very special feature called a Copy-On-Write
file or COW. Copy on write is a common computer science concept that
defines a mechanism for a chunk of data to remain read-only yet allows
modification by writing changed data blocks to an alternate location.
The filesystem image you download always remains read-only.
Changes made to the filesystem in our running UML system are written
to the COW file. This allows us to boot up multiple UML systems from the
same read-only root filesystem image, provided they all have separate COW
files. Also, if our UML system becomes corrupted, we simply clear the COW
file to start over. The COW files are what is called sparse files;
even though they may appear to be big when viewing the file size, only
non-null data is actually allocated space on the disk.

Collecting the Pieces

Let's start by collecting the components in a freshly
created empty directory. Make sure sufficient disk space
is available; after all, we need to house an entire Debian
installation. Three gigabytes should be sufficient for the
basic system. Download the Debian-3.1-x86-root_fs.bz2 file from
uml.nagafix.co.uk. Then, grab the 2.6.14.3-bs3 UML kernel from
www.user-mode-linux.org/~blaisorblade/binaries. Finally,
grab the UML utilities sources from
user-mode-linux.sourceforge.net/dl-sf.html. If any of these
files are missing, you can find alternate download locations in the
Resources for this article.

Below is a script of the commands for collecting all the parts
and compiling the UML utilities that are available only in source
form. If you are not interested in setting up networking, you can omit
the uml_utilities tarball and skip the compile. All the steps
below can be performed as a normal user except the installation of the UML
utilities, which requires an su to root:

Now we have all the parts collected and are ready to rock 'n' roll. All Linux
systems have a kernel command line. In most systems, this command line
is invoked by the bootloader (GRUB, LILO and so on). In our case, we
compose the command line ourselves to instruct the kernel to use the
Debian root filesystem image and a COW file named Debian1.cow as its
root (/) filesystem. Your current terminal becomes the console of
the guest UML system:

After that command is executed, we see the familiar Linux
kernel boot messages ending with a Debian system waiting for someone to
log in. We can log in as root (there is no password) and poke around
as shown in Listing 1.

Pretty cool, eh? It's your very own Debian 3.1 sandbox to make or break
as you like. You can ignore warnings about hwclock and tty0, as these are
normal for most UML systems because some hardware features are not supported
by UML kernels. Feel free at this point to change the root password to
anything you like.

Next, let's set up networking. You need two free static IP addresses,
one for each side of a tunnel that will be created by the UML utilities
we compiled earlier. I use 192.168.1.100 and 192.168.1.101 here. Use
anything appropriate for your local network. To get started, boot up
your Debian UML again, and use the following command:

Enter a hostname of your choice in the /etc/hostname file and, finally,
copy your resolver settings from /etc/resolv.conf on the host system to
the guest Debian system. Halt the guest system and reboot.

After the guest system is booted, you will be able to ping it from anywhere
on your network. I would suggest doing a couple things to your newly
networked Debian system. First, install OpenSSH, and then update all installed
packages to current versions. To do so, execute the following commands
and answer the simple questions when asked:

apt-get install openssh-server
apt-get upgrade

The possibilities at this point are wide open. Any network service or
application can be run under this guest Debian install. You can use UML
to test applications across many kernel versions and Linux distributions
all on one box. You can place the filesystem image and COW file on a
USB thumbdrive, giving you a stable development environment across all
the computers you use. User-mode Linux makes it easy and painless to
test system changes that otherwise might make a system
unbootable.

Fun—As in Destruction!

Okay, you know you've always wanted to do it. Now, here is your
chance. Bring up a new standalone guest Debian UML system, and do an
rm
-rf /. If you are like me, your fingers start to curl under as you even
consider typing that command. To begin, boot up the new Debian guest
using the following command (notice we are using a different COW file,
because we do not want to disturb the nice networked setup we created
previously):

That's gotta hurt. So, as a lesson, do not do that on a real system. But
because this is a UML guest with a COW file, you simply can delete the
DangerDanger.cow file, and this guest system will boot up back to its
initial state.

More on COW Files

The utility uml_moo included in the UML utilities will read a filesystem
image and an associated COW file and create a new merged filesystem
image. This allows you to merge changes stored in the COW file into a
new master filesystem image. This makes it easy to clone working guest
filesystem images when you have them set up the way you want.

Conclusion

User-mode Linux is fun to play with, but it also has some real-world
uses. You can use it to test unknown or untrusted applications while
limiting possible damage to the running host system. You can create
virtual networks of UMLs by starting up multiple guests at once.
This allows you to create a test-lab-in-a-box environment with very
little time and effort, so you can try all those “Stupid Linux
Tricks”
you were afraid to try on a real system!

Matthew E. Hoskins is a Senior UNIX System Administrator for The New
Jersey Institute of Technology where he maintains many of the corporate
administrative systems. He enjoys trying to get wildly different
systems and software working together, usually with a thin layer of Perl
(locally known as “MattGlue”). When not hacking systems, he often
can be found hacking in the kitchen. Matt is a member of the Society of
Professional Journalists. He is eager to hear your feedback and can be
reached at matt@njit.edu.