Introduction

This howto describes in a very short way how to use "User Mode Linux" with networking.

I know there are more detailed howtos around the web but sometimes it is much more helpful to have a short overview on how to get things running. Here it is:

Let's prepare a directory and get the Linux kernel sources

hanez@phantom ~ % mkdir linux                                                          
hanez@phantom ~ % cd linux
hanez@phantom linux % wget http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.13.tar.bz2
--00:33:09--  http://kernel.org/pub/linux/kernel/v2.6/linux-2.6.23.13.tar.bz2
           => `linux-2.6.23.13.tar.bz2'
Resolving kernel.org... 204.152.191.5, 204.152.191.37
Connecting to kernel.org|204.152.191.5|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 45,473,072 (43M) [application/x-bzip2]

100%[====================================>] 45,473,072   574.14K/s    ETA 00:00

00:34:30 (556.48 KB/s) - `linux-2.6.23.13.tar.bz2' saved [45473072/45473072]

hanez@phantom linux % tar -xjf linux-2.6.23.13.tar.bz2 
hanez@phantom linux % cd linux-2.6.23.13 
hanez@phantom linux-2.6.23.13 % 

Now, we will build the kernel

First of all we need to configure the kernel. In this example I am using the default kernel configuration to make things fast... ;) If you don't want the default kernel configuration you could do the configuration as normal. But take care that you enable all functions needed for UML. The following command will configure the kernel automatically and adds support for User Mode Linux.

hanez@phantom linux-2.6.23.13 % make ARCH=um defconfig

Compile the kernel

hanez@phantom linux-2.6.23.13 % make ARCH=um

Since we are running this kernel in "user mode" we don't need to install it to some place. Just run the newly created kernel with the following command:

hanez@phantom linux-2.6.23.13 % ./linux

The output should look something like this:

Core dump limits :
        soft - 0
        hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking for tmpfs mount on /dev/shm...OK
Checking PROT_EXEC mmap in /dev/shm/...OK
Checking for the skas3 patch in the host:
  - /proc/mm...not found: No such file or directory
  - PTRACE_FAULTINFO...not found
  - PTRACE_LDT...not found
UML running in SKAS0 mode
Adding 29028352 bytes to physical memory to account for exec-shield gap
Linux version 2.6.23.13 (hanez@phantom.home.hanez.org) (gcc version 4.1.2 
20070925 (Red Hat 4.1.2-27)) #1 Mon Jan 14 00:51:25 CET 2008
Built 1 zonelists in Zone order.  Total pages: 15160
Kernel command line: root=98:0
PID hash table entries: 256 (order: 8, 1024 bytes)
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 29840k available
Mount-cache hash table entries: 512
Checking for host processor cmov support...Yes
Checking for host processor xmm support...No
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
Using 2.6 host AIO
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
Checking host MADV_REMOVE support...OK
mconsole (version 2) initialized on /home/hanez/.uml/LRi3R2/mconsole
Host TLS support detected
Detected host type: i386
VFS: Disk quotas dquot_6.5.1
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
Initialized stdio console driver
Console initialized on /dev/tty0
console [tty0] enabled
Initializing software serial port version 1
console [mc-1] enabled
Couldn't stat "root_fs" : err = 2
Failed to initialize ubd device 0 :Couldn't determine size of device's file
VFS: Cannot open root device "98:0" or unknown-block(98,0)
Please append a correct "root=" boot option; here are the available partitions:
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(98,0)

EIP: 0073:[] CPU: 0 Not tainted ESP: 007b:00268fc0 EFLAGS: 00200246
    Not tainted
EAX: 00000000 EBX: 000037e4 ECX: 00000013 EDX: 000037e4
ESI: 000037e0 EDI: 00000011 EBP: 00268fd8 DS: 007b ES: 007b
09dc2e6c:  [] show_regs+0xb4/0xb9
09dc2e98:  [] panic_exit+0x25/0x3f
09dc2eac:  [] notifier_call_chain+0x21/0x46
09dc2ecc:  [] __atomic_notifier_call_chain+0x17/0x19
09dc2ee8:  [] atomic_notifier_call_chain+0x15/0x17
09dc2f04:  [] panic+0x52/0xdd
09dc2f24:  [] mount_block_root+0xf8/0x10e
09dc2f78:  [] mount_root+0x4c/0x54
09dc2f9c:  [] prepare_namespace+0x10c/0x133
09dc2fa4:  [] kernel_init+0x79/0x85
09dc2fb4:  [] run_kernel_thread+0x37/0x40
09dc2fe0:  [] new_thread_handler+0x57/0x7e
09dc2ffc:  [] _sinittext+0xf7fb7000/0x88

zsh: segmentation fault  ./linux
hanez@phantom linux-2.6.23.13 % 

Since we have no filesystem image for the new kernel it segfaults. We need to prepare the filesystem next...

Download a Filesystem Image

To get a filesystem image go to http://fs.devloop.org.uk/. I have choosen to use a Gentoo image for my tests but you decide, it should work with every distribution. I have tested Fedora 7 and Gentoo.

To get the Gentoo image I am using for this howto run the following commands:

hanez@phantom linux-2.6.23.13 % wget http://uml.nagafix.co.uk/Gentoo-2006.1/Gentoo-2006.1-x86-root_fs.bz2
hanez@phantom linux-2.6.23.13 % bunzip2 Gentoo-2006.1-x86-root_fs.bz2

Now you have the following file in the current directory:

hanez@phantom linux-2.6.23.13 % ls -l Gentoo-2006.1-x86-root_fs 
-rw-r--r-- 1 hanez hanez 2684354560 2008-01-13 04:10 Gentoo-2006.1-x86-root_fs
hanez@phantom linux-2.6.23.13 % 

For me it looks like this:

Booting the GNU/Linux based Gentoo operating system

Run this command to start the whole new system:

hanez@phantom linux-2.6.23.13 % ./vmlinux ubda=./Gentoo-2006.1-x86-root_fs mem=128M umid=gentoo

The parameter "umid" is used later for connecting from the host system to the guest with the use of the uml_console. "mem" is the RAM provided by the host.

There we are, a running Linux system:

Core dump limits :
        soft - 0
        hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking for tmpfs mount on /dev/shm...OK
Checking PROT_EXEC mmap in /dev/shm/...OK
Checking for the skas3 patch in the host:
  - /proc/mm...not found: No such file or directory
  - PTRACE_FAULTINFO...not found
  - PTRACE_LDT...not found
UML running in SKAS0 mode
Adding 14073856 bytes to physical memory to account for exec-shield gap
Linux version 2.6.23.13 (hanez@phantom.home.hanez.org) (gcc version 4.1.2 
20070925 (Red Hat 4.1.2-27)) #1 Mon Jan 14 00:51:25 CET 2008
Built 1 zonelists in Zone order.  Total pages: 35922
Kernel command line: ubda=./Gentoo-2006.1-x86-root_fs mem=128M root=98:0
PID hash table entries: 1024 (order: 10, 4096 bytes)
Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
Memory: 126576k available
Mount-cache hash table entries: 512
Checking for host processor cmov support...Yes
Checking for host processor xmm support...No
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
Using 2.6 host AIO
NET: Registered protocol family 16
NET: Registered protocol family 2
IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
TCP established hash table entries: 8192 (order: 4, 65536 bytes)
TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
TCP reno registered
Checking host MADV_REMOVE support...OK
mconsole (version 2) initialized on /home/hanez/.uml/gentoo/mconsole
Host TLS support detected
Detected host type: i386
VFS: Disk quotas dquot_6.5.1
Dquot-cache hash table entries: 1024 (order 0, 4096 bytes)
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
TCP cubic registered
NET: Registered protocol family 1
NET: Registered protocol family 17
Initialized stdio console driver
Console initialized on /dev/tty0
console [tty0] enabled
Initializing software serial port version 1
console [mc-1] enabled
 ubda: unknown partition table
EXT3-fs: INFO: recovery required on readonly filesystem.
EXT3-fs: write access will be enabled during recovery.
kjournald starting.  Commit interval 5 seconds
EXT3-fs: recovery complete.
EXT3-fs: mounted filesystem with ordered data mode.
VFS: Mounted root (ext3 filesystem) readonly.
line_ioctl: tty0: ioctl KDSIGACCEPT called
INIT: version 2.86 booting
line_ioctl: tty0: ioctl TIOCLINUX called

Gentoo Linux; http://www.gentoo.org/
 Copyright 1999-2007 Gentoo Foundation; Distributed under the GPLv2

Press I to enter interactive boot mode

 * Mounting proc at /proc ...                                             [ ok ]
 * Mounting sysfs at /sys ...                                             [ ok ]
 * Mounting /dev for udev ...                                             [ ok ]
 * Seeding /dev with needed nodes ...                                     [ ok ]
 * Starting udevd ...                                                     [ ok ]
 * Populating /dev with existing devices through uevents ...              [ ok ]
 * Letting udev process events ...                                        [ ok ]
 * Finalizing udev configuration ...                                      [ ok ]
 * Mounting devpts at /dev/pts ...                                        [ ok ]
 * Checking root filesystem .../dev/ubda: clean, 197388/327680 files, 
 412750/655360 blocks
                                           [ ok ]
 * Remounting root filesystem read/write ...                              [ ok ]
 * Warning: the current /etc/modules.conf has not been automatically generated
 * Use "update-modules force" to force (re)generation
FATAL: Could not load /lib/modules/2.6.23.13/modules.dep: No such file or 
directory
 * Checking all filesystems ...                                           [ ok ]
 * Mounting local filesystems ...                                         [ ok ]
 * Activating (possible) swap ...                                         [ ok ]
 * Setting system clock using the hardware clock [UML] ...                [ ok ]
 * Configuring kernel parameters ...                                      [ ok ]
 * Updating environment ...                                               [ ok ]
 * Cleaning /var/lock, /var/run ...                                       [ ok ]
 * Cleaning /tmp directory ...                                            [ ok ]
 * Device initiated services: udev-postmount
 * Setting hostname to localhost ...                                      [ ok ]
 * Loading key mappings ...                                               [ ok ]
 * Setting user font ...                                                  [ ok ]
 * Starting lo
 *   Bringing up lo
 *     127.0.0.1/8
                                                                          [ ok ]
 *   Adding routes
 *     127.0.0.0/8 ...                                                    [ ok ]
 * Initializing random number generator ...                               [ ok ]
INIT: Entering runlevel: 3
 * Starting syslog-ng ...                                                 [ ok ]
 * Starting eth0
 *   You are using a deprecated configuration syntax for eth0
 *   You are advised to read /etc/conf.d/net.example and upgrade it accordingly
 *   Bringing up eth0
 *     192.168.0.1
 *     network interface eth0 does not exist
 *     Please verify hardware or kernel module (driver)
                                                                          [ !! ]
                                                                          [ !! ]
 * ERROR:  cannot start netmount as net.eth0 could not start
 * Starting vixie-cron ...                                                [ ok ]
 * Starting local ...                                                     [ ok ]


This is localhost.(none) (Linux i686 2.6.23.13) 00:07:50

localhost login: 

Just login as user "root" without a password. Your new Linux system is running! Jehaaaa!

Please ignore the network configuration errors because my gentoo filesystem image is configured already but the host system does not support networking at this point. Networking will be the next step.

Shut the system down with the normal commands:

localhost ~ # init 0
INIT: Switching to runlevel: 0
INIT: Sending processes the TERM signal
...
System halted.

hanez@phantom linux-2.6.23.13 % 

Prepare host system for networking

Let's check if our system supports tun devices and if we have permissionsfor reading and writing to tun devices:

hanez@phantom linux-2.6.23.13 % ls -l /dev/net 
total 0
crw------- 1 root root 10, 200 2008-01-13 16:31 tun

As you can see, we have tun device support but the tun device is not read-/writeable for users. So let's change this temporary. For security reasons this not a good idea but for getting a network running fast, it is the easiest way... ;)

Become root

hanez@phantom linux-2.6.23.13 % su -
Password:
root@phantom ~ # 

Set permissions on the tun device

root@phantom ~ # chmod 0666 /dev/net/tun
root@phantom ~ # ls -l /dev/net            
total 0
crw-rw-rw- 1 root root 10, 200 2008-01-13 16:31 tun
root@phantom ~ # 

Now we can read and write to tun devices as normal user.

Create tun device

On the host system we need to create a new tun device. In this case I created a tun device for user hanez.

root@phantom ~ # tunctl -u hanez                                    
Set 'tap0' persistent and owned by uid 1000
root@phantom ~ # 

Enable tun device

This newly created tun device is the gateway for the UML system for connecting your network.

root@phantom ~ # ifconfig tap0 192.168.0.254 up
root@phantom ~ # ifconfig tap0
tap1      Link encap:Ethernet  HWaddr 00:FF:92:80:C7:9F  
          inet addr:192.168.0.254  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::2ff:92ff:fe80:c79f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:35 overruns:0 carrier:0
          collisions:0 txqueuelen:500 
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

root@phantom ~ # 

Kernel settings

Enable IP forwarding on the host system.

root@phantom ~ # echo 1 > /proc/sys/net/ipv4/ip_forward

Masquerading

We need to activate network address translation (NAT), in Linux called masquerading, on the host system to allow the UML systemconnecting the network. Make also shure that no firewall rules are blocking the newly created network 192.168.0.0/24.

My current output of iptables-save looks like this:

root@phantom ~ # iptables-save 
root@phantom ~ # 

Now, enable masquerading and look at the output again:

root@phantom ~ # iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
root@phantom ~ # iptables-save 
# Generated by iptables-save v1.3.8 on Sat Jan 19 23:45:21 2008
*nat
:PREROUTING ACCEPT [44:4467]
:POSTROUTING ACCEPT [13:1416]
:OUTPUT ACCEPT [64:4618]
-A POSTROUTING -o eth0 -j MASQUERADE 
COMMIT
# Completed on Sat Jan 19 23:45:21 2008
root@phantom ~ # 

The host's routing table

root@phantom ~ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.1     *               255.255.255.255 UH    0      0        0 tap1
192.168.1.0     *               255.255.255.0   U     0      0        0 eth0
192.168.0.0     *               255.255.255.0   U     0      0        0 tap0
default         192.168.1.2     0.0.0.0         UG    0      0        0 eth0
root@phantom ~ # 

Become a normal user again

root@phantom ~ # exit
hanez@phantom linux-2.6.23.13 % 

Now boot the Gentoo based system with networking enabled.

hanez@phantom linux-2.6.23.13 % ./vmlinux ubda=./Gentoo-2006.1-x86-root_fs mem=128M eth0=tuntap,,,192.168.0.254 umid=gentoo

This command creates the network interface eth0 in the UML system with 192.168.0.254 as the TUN/TAP IP backend.

Configure networking on the UML system

Enable the network interface:

localhost ~ # ifconfig eth0 192.168.0.1 up
localhost ~ # ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 9A:05:02:D6:A0:BF  
          inet addr:192.168.0.1  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:97 errors:0 dropped:0 overruns:0 frame:0
          TX packets:38 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:22856 (22.3 Kb)  TX bytes:2496 (2.4 Kb)
          Interrupt:5 

localhost ~ # 

Set the default gateway in the UML system:

localhost# route add default gw 192.168.0.254

The UML system's routing table

localhost ~ # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     0.0.0.0         255.255.255.0   U     0      0        0 eth0
127.0.0.0       0.0.0.0         255.0.0.0       U     0      0        0 lo
0.0.0.0         192.168.0.254   0.0.0.0         UG    0      0        0 eth0
localhost ~ # 

Test the connection

Now let's ping to the host system to check if the network is working like expected:

localhost ~ # ping -c 4 192.168.0.254
PING 192.168.0.254 (192.168.0.254) 56(84) bytes of data.
64 bytes from 192.168.0.254: icmp_seq=1 ttl=64 time=0.242 ms
64 bytes from 192.168.0.254: icmp_seq=2 ttl=64 time=0.182 ms
64 bytes from 192.168.0.254: icmp_seq=3 ttl=64 time=0.178 ms
64 bytes from 192.168.0.254: icmp_seq=4 ttl=64 time=0.179 ms

--- 192.168.0.254 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3003ms
rtt min/avg/max/mdev = 0.178/0.195/0.242/0.028 ms
localhost ~ # 

Set your nameserver for connecting the outside world from your UML system

localhost ~ # echo "nameserver 192.168.1.2" > /etc/resolv.conf 
localhost ~ # cat /etc/resolv.conf 
nameserver 192.168.1.2
localhost ~ # 

Check if it works:

localhost ~ # ping -c 4 kernel.org
PING kernel.org (204.152.191.37) 56(84) bytes of data.
64 bytes from pub2.kernel.org (204.152.191.37): icmp_seq=1 ttl=51 time=205 ms
64 bytes from pub2.kernel.org (204.152.191.37): icmp_seq=2 ttl=51 time=204 ms
64 bytes from pub2.kernel.org (204.152.191.37): icmp_seq=3 ttl=51 time=203 ms
64 bytes from pub2.kernel.org (204.152.191.37): icmp_seq=4 ttl=51 time=204 ms

--- kernel.org ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3008ms
rtt min/avg/max/mdev = 203.822/204.465/205.203/0.709 ms
localhost ~ # 

Links