Saturday, February 18, 2006

The linux kernel

Linux configuration files

Thursday, February 09, 2006

gdb

Wednesday, February 08, 2006

Host file access from UML

If you want to access files on the host machine from inside UML, you can treat it as a separate machine and either nfs mount directories from the host or copy files into the virtual machine with scp or rcp. However, since UML is running on the the host, it can access those files just like any other process and make them available inside the virtual machine without needing to use the network.

This is now possible with the hostfs virtual filesystem. With it, you can mount a host directory into the UML filesystem and access the files contained in it just as you would on the host.

Note that hostfs is currently not available on 2.5. The reason is that there was an fs.h rework early in 2.5 which required filesystem changes, and I haven't got around to updating hostfs to those changes.

Using hostfs

To begin with, make sure that hostfs is available inside the virtual machine with
UML# cat /proc/filesystems
hostfs should be listed. If it's not, either rebuild the kernel with hostfs configured into it or make sure that hostfs is built as a module and available inside the virtual machine, and insmod it.

Now all you need to do is run mount:

UML# mount none /mnt/host -t hostfs
will mount the host's / on the virtual machine's /mnt/host.

If you don't want to mount the host root directory, then you can specify a subdirectory to mount with the -o switch to mount:

UML# mount none /mnt/home -t hostfs -o /home
will mount the hosts's /home on the virtual machine's /mnt/home.

testing a new system call written for UML

  1. You can write user-level program to test the new system call. You have to compile the test-program with –static and “–I /class/cs153//linux-2.4.23/include” flags. You have to compile this program on your host machine instead of “inside UML” (virtual machine).
  2. Mount your host file system /home and /class file system inside UML as explained in the FAQ page.
  3. Run the test-program binary inside UML.
  4. You should see all the “printk” outputs on your console and it should display the correct time in the format as specified by your test-program.

Adding system call to UML - Different instructions

Adding a System Call to UML

This document describes how to add a system call to User-mode Linux. The original version was written by Alexandros Karypidis. The version presented here is slightly modified to handle 2.6 kernels, specifically this is based on the 2.6.10 kernel. Furthermore, we use output from diff to show what to change.

Further information can be found here:

Define the entry point

The first thing you need to do is modify the file unistd.h in include/asm/arch. In this file, you need to add a line providing an id for your system call. Locate the bunch of lines of the form #define __NR_somename, and add a new entry for your system call. Further, you should increment the total number of available system calls as defined by NR_syscalls.

Download: diff.unistd.h
--- old/include/asm-i386/unistd.h 2005-01-10 09:08:18.000000000 +0100
+++ new/include/asm-i386/unistd.h 2005-03-03 14:33:25.366255000 +0100
@@ -294,8 +294,9 @@
#define __NR_add_key 286
#define __NR_request_key 287
#define __NR_keyctl 288
+#define __NR_somename 289

-#define NR_syscalls 289
+#define NR_syscalls 290

/*
* user-visible error numbers are in the range -1 - -128: see

Next, you must add and entry refering to your call in the system calls table. To do this, modify sys_call_table.c file in arch/um/kernel and edit the following lines:

--- old/arch/um/kernel/sys_call_table.c 2005-01-10 09:08:18.000000000 +0100
+++ new/arch/um/kernel/sys_call_table.c 2005-03-03 14:21:00.580270000 +0100
@@ -19,7 +19,7 @@
#define NFSSERVCTL sys_ni_syscall
#endif

-#define LAST_GENERIC_SYSCALL __NR_vserver
+#define LAST_GENERIC_SYSCALL __NR_somename

#if LAST_GENERIC_SYSCALL > LAST_ARCH_SYSCALL
#define LAST_SYSCALL LAST_GENERIC_SYSCALL
@@ -51,8 +51,12 @@
extern syscall_handler_t old_select;
extern syscall_handler_t sys_modify_ldt;
extern syscall_handler_t sys_rt_sigsuspend;
+extern syscall_handler_t sys_somename;

syscall_handler_t *sys_call_table[] = {
+ /* The following line ensures that we do not get any problems with */
+ /* undefined system calls. */
+ [ 0 ... LAST_GENERIC_SYSCALL ] = (syscall_handler_t *) sys_ni_syscall,
[ __NR_restart_syscall ] = (syscall_handler_t *) sys_restart_syscall,
[ __NR_exit ] (syscall_handler_t *) sys_exit,
[ __NR_fork ] (syscall_handler_t *) sys_fork,
@@ -306,6 +310,7 @@
[ __NR_utimes ] (syscall_handler_t *) sys_utimes,
[ __NR_fadvise64_64 ] (syscall_handler_t *) sys_fadvise64_64,
[ __NR_vserver ] (syscall_handler_t *) sys_ni_syscall,
+ [ __NR_somename ] (syscall_handler_t *) sys_somename,

ARCH_SYSCALLS
[ LAST_SYSCALL + 1 ... NR_syscalls ] =

LAST_GENERIC_SYSCALL must be changed such that your new system call's id is considered to be within the allowable range.

Next, we add a declaration for your system call in the area where all the other system calls are defined.

The line with [ 0 ... LAST_GENERIC_SYSCALL ] = (syscall_handler_t *) sys_ni_syscall, ensures that system calls which are in the normal kernel, but not in User-mode Linux are defined as not implemented. At least the 2.6.10 kernel are missing more than 10 system calls, and without this change, the kernel could segfault if one of the missing system calls were used.

The last change adds your system call to the system call table, such that it can be called from user space.

Having done all these, an attempt to compile the kernel should fail during linking, as the sys_somename function must now be implemented.

Implementation code

First of all, create a header file somename.h for your system call and place it in arch/um/include as shown here:

Download: somename.h
/*
* somename.h
*/

#ifndef __UML_SOMENAME_H__
#define __UML_SOMENAME_H__

extern int sys_somename(int flag);

#endif

Then, write out the implementation somename.c of your system call in arch/um/kernel as shown here:

Download: somename.c
/*
* somename.c
*/

#include "linux/kernel.h"
#include "linux/unistd.h"

asmlinkage
int sys_somename(int flag) {
printk("Hello from somename! flag=%d.\n", flag);
return 0;
}

Finally, modify the respective Makefile in arch/um/kernel and add somename.o to the list of build targets.

Download: diff.Makefile
--- old/arch/um/kernel/Makefile 2005-01-10 09:08:18.000000000 +0100
+++ new/arch/um/kernel/Makefile 2005-02-09 15:59:14.185985000 +0100
@@ -9,13 +9,13 @@
obj-y = checksum.o config.o exec_kern.o exitcode.o frame_kern.o frame.o helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o mem_user.o physmem.o process.o process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o signal_kern.o signal_user.o smp.o syscall_kern.o syscall_user.o sysrq.o sys_call_table.o tempfile.o time.o time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o - um_arch.o umid.o user_util.o
+ um_arch.o umid.o user_util.o somename.o

obj-$(CONFIG_BLK_DEV_INITRD) += initrd_kern.o initrd_user.o
obj-$(CONFIG_GPROF) += gprof_syms.o
obj-$(CONFIG_GCOV) += gmon_syms.o
obj-$(CONFIG_TTY_LOG) += tty_log.o

Creating a stub for your system call

The listing below shows a program which uses the _syscall macro to create a stub for the system call. It then proceeds to call the stub function. When compiling, be sure to specify the -I option so that gcc will look at the modified version of unistd.h. In the example, the preprocessor looks for the file in asm/arch/unistd.h, so if the UML code is in the directory /uml-code you should compile with -I/uml-code/include.

Download: test_somename.c
/*
* test_somename.c
*
* Note: should be compiled with:
* gcc -I path.to.kernel.tree/linux-2.6.10/include -o test_somename test_somename.c
*/

#include
#include
#include "asm/arch/unistd.h"

_syscall1(int, somename, int, flag);

int main(int argc, char** argv) {
printf("Calling...\n");
somename(1);
}

Tuesday, February 07, 2006

System Call in UML

Define the entry point


The first thing you need to do is modify the file unistd.h in include/asm/arch. In this file, you need to add a line providing an id for your system call. Locate the bunch of lines of the form:


#define __NR_somename NNN

You need to add a new line, replacing ``somename" with your system call's name. Next, you must add and entry refering to your call in the system calls table. To do this, modify sys_call_table.c file in arch/um/kernel and add a line:


[ __NR_somename ] = sys_somename,

In the same file, you must change the ``LAST_GENERIC_SYSCALL" so that your new system call's id is considered to be within the allowable range.


#define LAST_GENERIC_SYSCALL __NR_somename

Finally, add a declaration for your system call in the area where all the other system calls are defined, as shown on the following line:


extern syscall_handler_t sys_somename;

Having done all these, an attempt to compile the kernel should fail during linking, as the ``sys_somename" function must now be implemented.

Implementation code


First of all, create a header file somename.h for your system call and place it in arch/um/include as shown in listing 1.



Then, write out the implementation somename.c of your system call in arch/um/kernel as shown in listing 2.



Finally, modify the respective Makefile in arch/um/kernel and add somename.o to the list of build targets.


Listing 3 shows a program which uses the _syscall macro to create a stub for the system call. It then proceeds to call the stub function. When compiling, be sure to specify the -I option so that gcc will look at the modified version of unistd.h. In the example, the preprocessor looks for the file in asm/arch/unistd.h, so if the UML code is in directory /uml-code you should compile with -I/uml-code.

In this step, I have done something different as I do not have the source inside the UML system. I have written a forensic-user.h in /usr/include/sys of slackware.img that includes . I have verified that this unistd.h has my new system calls.

kernel messages / syslog

/etc/syslog.conf tells us where the kernel messages will be stored.

by default, the kernel messages will be written to /var/log/messages, but again, one should consult the syslog.conf file. The messages may be written to /var/log/syslog, or /var/log/dmesg etc.

syslogd and klogd should be running for the messages to be logged. syslogd writes the kernel messages to one of the files synchronously.

User Mode Linux Kernel Home Page

Can find most up-to-date details about UML

Installing UML using Slackware

The previous post has the details of loading Slackware in the slackware.img file specified by /dev/ubd1 in the initial command line:
#linux ubd0=initrd ubd1=slackware.img ubd2r=/dev/cdrom devfs=nomount rw

slackware.img file was created using the following command:
#dd if=/dev/zero of=slackware.img bs=1M count=1 seek=4000
I followed the following initial instructions from the other howto:

--------------------------------------------------------------------------------------------

Instructions for Installing Slackware 10.1/10.2 under UML:

Aims:

  1. Do as little as possible as root (not even mount -o loop...).
  2. Don't use a downloaded image as the base, just the slackware CD.
  3. Run Slackware installer to select packages/system config.

Prerequisites

  1. A Linux kernel. I've tried with 2.6.12.1 and 2.6.13.1 so far.
  2. UML Utilities. I'm using 20040406 (from http://sourceforge.net/project/showfiles.php?group_id=429)
  3. One or both of the slackware CDs, (ISO images will do).

Description:

First unpack and build the UML utilities. No ./configure, just type make, and make sure the port-helper utility is put somewhere in your path.

tar -jxvf uml_utilities_20040406.tar.bz2
cd tools
make
cp port-helper/port-helper /usr/local/bin

You probably also want tunctl, but that's for a future HOWTO.

Next you need to configure your kernel. You don't need to be root to do this, (in fact it's better if you don't do it in /usr/src/linux). I used kernel 2.6.12.1 mostly with defaults, but make sure you have iso9660 and ext2 compiled in. We need ext2 for the initial ram drive and iso9660 for reading the install CD/image. You should also compile in your favourite file system driver, whichever one you normally select in the Slackware install menu (Reiserfs for me):

wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.12.1.tar.bz2
tar -jxf linux-2.6.12.1.tar.bz2
cd linux-2.6.12.1
make menuconfig ARCH=um
make linux ARCH=um

That should give you a linux executable called 'linux'. Go on - run it. It should just complain about the fact that it's missing a root file system. You might need to kill it from another terminal.

Mount the first slackware CD, then copy the installation root fs:

mount /mnt/cdrom
cp /mnt/cdrom/isolinux/initrd.img initrd.gz
gzip -d initrd.gz
chmod 666 initrd
umount /mnt/cdrom

Don't forget to unmount the CD, because UML needs direct access to /dev/cdrom.

Next we need the target file system, created by dd (this is a sparse file, of course):

dd if=/dev/zero of=slackware.img bs=1M count=1 seek=4000

Now, run the linux executable using the Slackware initial ramdrive as root. Make sure you do this in an Xterm, and as a user who has access to the X server, because this will try to throw up some Xterm consoles (unless you foolishly disabled them in the kernel config).

linux mem=128M ubd0=initrd ubd1=slackware.img ubd2r=/dev/cdrom rw

Note: If you want to install both CDs of software then you need to specify a 'real' CD device (/dev/cdrom) instead of an ISO image file. This is because you can't really 'eject' an ISO image, and that is required for the install.

--------------------------------------------------------------------------------------------

Followed the hack for setting up devices in /dev of initrd image first, and then changing the /sbin/probe file of initrd image from outside, and then installing Slackware in slackware.img.

Next I had to create the devices hda, hdb, hdc etc. in the slackware.img OS.. did not know how to do that.. every time i gave the command line:

#linux ubd1=slackware.img ubd2r=/dev/cdrom devfs=nomount root=/dev/ubdb1

it would complain saying that fsck could not find a valid filesystem in /dev/hdb1. And it would give the prompt for root to log in and do the fsck manually..

Then it occured to me that I could use that prompt and create the devices that I wanted. So, this is what I did:

root@(none):/dev# rm hda hdb hdc
rm: cannot remove `hda': Read-only file system
rm: cannot remove `hdb': Read-only file system
rm: cannot remove `hdc': Read-only file system
root@(none):/dev# whoami
root
root@(none):/dev# rm -f hda
rm: cannot remove `hda': Read-only file system
root@(none):/dev# rmdir hda
rmdir: `hda': Read-only file system


(ha.. had to remount / as a rw filesystem)

root@(none):/# mount -o remount,rw /
root@(none):/# mount
/dev/hdb1 on / type ext2 (rw)
root@(none):/# cd dev
root@(none):/dev# rm hda hdb hdc
root@(none):/dev# mknod hda b 98 0
root@(none):/dev# mknod hda1 b 98 1
mknod: `hda1': File exists
root@(none):/dev# rm hda1 hda2 hdb1 hdb2 hdc1 hdc2
root@(none):/dev# mknod hda1 b 98 1
root@(none):/dev# mknod hda2 b 98 2
root@(none):/dev# mknod hdb b 98 16
root@(none):/dev# mknod hdb1 b 98 17
root@(none):/dev# mknod hdb2 b 98 18
root@(none):/dev# mknod hdc b 98 32
root@(none):/dev# mknod hdc1 b 98 33
root@(none):/dev# mknod hdc2 b 98 34
root@(none):/dev# (Ctrl+D)logout
Unmounting file systems.
Rebooting system.
Restarting system.
...

Now it has created multiple virtual consoles. I went ahead and mounted /dev/hdb2 in /srcDisk.. and it is working fine now.

Monday, February 06, 2006

DatuX Usermode Linux with Slackware 9.1 HOWTO

DatuX Usermode Linux with Slackware 9.1 HOWTO

© 2003 http://www.datux.nl/ – Edwin Eefting edwin@datux.nl

Last updated: 10/05/03
Introduction

This document describes how I installed the latest slackware version (currently 9.1) under UML, without using any prepared bootimages or scripts. There is also a link in this document to a ready-to-run slackware 9.1 installer, and a complete ready-to-run basic 9.1 installation. If there's a new version of slackware, you should be able to create the install image yourself with the help of this document.
Why can't I just install slackware under UML?

UML is something different then programs like VMWare. VMWare provides a complete virtual machine, that comes WITH a bios and thus is able to boot a installation CDROM of any type of operating system. (like a normal computer)

However, UML doesn't provide a virtual machine, i only provides a virtual linux environment, by making users able to start the kernel like a normal program. This means that you can't can “boot” from a CD-ROM. However, with a little “fiddeling” (hacking around in the slackware setup scripts) it's still posible to run the slackware setup program under UML. This way you won't need to do the complex stuff to create a root-disk. (according to the UML homepage)
Requirements

*

Before you can start you first need to comiple a UML-kernel binairy like you normally would do when you want to use UML. Look at http://user-mode-linux.sourceforge.net/ for more info about how to do this.
*

If you want to install slackware from scratch: The latest .ISO images of slackware. (currently 9.1) At http://www.slackware.org or at http://slackware.datux.nl There is no need to burn them on a CD, you can just use the plain .ISO images with UML.
*

If you just want a default minimum slackware installation without any hassle just go to http://uml.datux.nl and download the latest UML-image.
*

Coffee, patience and the ability to think.

The quick and painless way

Download the slackware 9.1 preinstalled image from http://uml.datux.nl , extract it and start UML like this:

psy@phattop:~/uml$ /usr/src/uml-2.4.22/linux ubd1=root_fs ubd2r=/dev/cdrom devfs=nomount root=/dev/ubd11
Checking for the skas3 patch in the host...not found
Checking for /proc/mm...not found
tracing thread pid = 12793
Linux version 2.4.22 (root@phattop) (gcc version 3.2.2) #4 Sun Oct 5 14:13:52 Local time zone must be set--see zic manua
....snip snip....

Tadaaah...you're running a complete virutal linux environment (slackware 9.1) inside of your own Linux enviroment. Nice eh?

If you want to know how it's done read on, otherwise just have fun.
Creating a virtual disk

First we need a virtual disk that we can use as installation target in UML. You could use an existing partion as a target place, but i prefer to use plain files. (because they are easier to copy/move/manage/backup etc..) To create a virtual disk named “root_fs” type the following command:

psy@phattop:~/uml$ dd if=/dev/zero of=root_fs bs=$((1024*1024)) count=2000
2000+0 records in
2000+0 records out

This will just create a plain empty file of approx. 2gb. This will be the file that we use as our disk and target to install our slackware.
Modifying the original slackware setup disk

Read this chapter if you want to know how to get the slackware installer running under UML or if there is a newer version of slackware you want to use. Otherwise just skip to the next chapter and download a working initrd from http://uml.datux.nl
Getting the original slackware setup-image

We need to get the slackware setup-image that our kernel will use a root filesystem. Normally the installer CDROM is booted from the bios and the root filesystem is automaticly mounted. This image is stored in isolinux/initrd.img. If you use the file command you will see this file is zipped. Copy it to a nice directory and unzip it so that we can work on it. (you need a copy because we will change it!!)

psy@phattop:~/uml$ file /mnt/cdrom/isolinux/initrd.img
/mnt/cdrom/isolinux/initrd.img: gzip compressed data, from Unix, max compression

psy@phattop:~/uml$ cp /mnt/cdrom/isolinux/initrd.img initrd.gz
psy@phattop:~/uml$ gunzip initrd.gz
psy@phattop:~/uml$ file initrd
initrd: Linux rev 1.0 ext2 filesystem data

So now we have a ext2 disk image which contains the root filesystem that is normally used to setup slackware. (it contains the setup program)
Hacking up the slackware setup-image

Lets try to see what happens if we use this initrd setup-image as our root image. Pay attention to how to create the virtual disks:

*

udb0 will be the installation-image we just unzipped.
*

udb1 will be the target-image we just created. (root_fs)
*

udb2 will be our slackware installation CD-ROM (or iso image)

This is what i got:

psy@phattop:~/uml$ /usr/src/uml-2.4.22/linux ubd0=initrd ubd1=root_fs ubd2r=/dev/cdrom devfs=nomount rw
Checking for the skas3 patch in the host...not found
Checking for /proc/mm...not found
tracing thread pid = 8751
Linux version 2.4.22 (root@phattop) (gcc version 3.2.2) #4 Sun Oct 5 14:13:52 Local time zone must be set--see zic manua
On node 0 totalpages: 8192
zone(0): 8192 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: ubd0=initrd ubd1=root_fs ubd2r=/dev/cdrom devfs=nomount rw root=/dev/ubd0
Calibrating delay loop... 2467.25 BogoMIPS
Memory: 28772k available
Dentry cache hash table entries: 4096 (order: 3, 32768 bytes)
Inode cache hash table entries: 2048 (order: 2, 16384 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 8192 (order: 3, 32768 bytes)
Checking for host processor cmov support...Yes
Checking for host processor xmm support...No
Checking that ptrace can change system call numbers...OK
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
POSIX conformance testing by UNIFIX
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Starting kswapd
VFS: Disk quotas vdquot_6.5.1
Journalled Block Device driver loaded
devfs: v1.12c (20020818) Richard Gooch (rgooch@atnf.csiro.au)
devfs: boot_options: 0x0
JFFS version 1.0, (C) 1999, 2000 Axis Communications AB
JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.
pty: 256 Unix98 ptys configured
SLIP: version 0.8.4-NET3.019-NEWTTY (dynamic channels, max=256).
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
loop: loaded (max 8 devices)
PPP generic driver version 2.4.2
Universal TUN/TAP device driver 1.5 (C)1999-2002 Maxim Krasnyansky
SCSI subsystem driver Revision: 1.00
scsi0 : scsi_debug, Version: 0.61 (20020815), num_devs=1, dev_size_mb=8, opts=0x0
Vendor: Linux Model: scsi_debug Rev: 0004
Type: Direct-Access ANSI SCSI revision: 03
blkmtd: error: missing `device' name

Initializing software serial port version 1
mconsole (version 2) initialized on /home/psy/.uml/cJnBNr/mconsole
Partition check:
ubda: unknown partition table
ubdb: unknown partition table
ubdc: unknown partition table
UML Audio Relay (host dsp = /dev/sound/dsp, host mixer = /dev/sound/mixer)
Initializing stdio console driver
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 2048 bind 4096)
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended
VFS: Mounted root (ext2 filesystem).
init started: BusyBox v0.60.5 (2003.02.16-05:06+0000) multi-call binary
proc on /proc type proc (rw)

Slackware UML links

http://uml.harlowhill.com/index.php/SlackwareHowto
http://64.233.179.104/search?q=cache:XRSs8gssWuwJ:uml.datux.nl/UML-Slackware-HOWTO.html+slackware+makedevs.sh&hl=en&gl=us&ct=clnk&cd=1

Sunday, February 05, 2006

UML installation