| Adding a System Call to a Linux Kernel |
In this lab, we will add a system call to the kernel source
directory. Today you will create our own KVM image, create
a user account on this image. Then, you will be modifying
the kernel source directory by adding a new system call to
the kernel. Then you will build and install the modified kernel
on this image. Finally, we will test the system call.
| Resources |
| Installing QEMU (No need for this step, if you already have QEMU functional from lab 2) |
For today's lab, you will be directly working on your machine. We won't be needing VirtualBox or PuTTY for today's lab. You can use the host OS of your machine. It can either be Linux, Windows or MacOS.
We will be using QEMU from the command prompt (Windows) or terminal (Linux, MacOS). The commands are the same for the different platforms.
| Creating Your Image |
Like lab2, we will need a base image first. Then, we will create a differential image off the base image.
scp your_ku_online_id@cycle1.eecs.ku.edu:/srv/EECS_678/eecs678_base.qcow .
qemu-img create -f qcow2 -F qcow2 -b eecs678_base.qcow your_first_name.qcow(Screenshot)
| Boot Your Image |
qemu-system-x86_64 -hda your_first_name.qcow -smp 2 -m 2048M(Screenshot)
Here, -smp value denotes the number of cores and -m value denotes the amount of RAM we want to allocate to the QEMU system. This will depend on how many cores and how much memory, you are willing to share from your physical machine with the QEMU system.
| Setting up Your Account |
root@debian:~# adduser your_first_name
Adding user `your_first_name' ...
Adding new group `your_first_name' (1000) ...
Adding new user `your_first_name' (1000) with group `your_first_name' ...
Creating home directory `/home/your_first_name' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for your_first_name
Enter the new value, or press ENTER for the default
Full Name []:
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
root@debian:~#
(Screenshot)
root@debian:~# vi /etc/sudoersThis will open vi on /etc/sudoers. Add your new user to this file as shown:
# User privilege specification root ALL=(ALL) ALL your_first_name ALL=(ALL) ALL
root@debian:~# usermod -a -G sudo your_first_name
root@debian:~# mkdir /home/your_first_name/kernel
root@debian:~# mv ~/linux-2.6.32.60 /home/your_first_name/kernel/
root@debian:~# chown -R your_first_name:your_first_name /home/your_first_name/kernel
root@debian:~# apt-get install sudo
root@debian:~# cp /root/.vimrc /home/your_first_name/ root@debian:~# chown your_first_name:your_first_name /home/your_first_name/.vimrc
root@debian:~# su your_first_name
error: zlib.h: No such file or directory
sudo apt-get install libz-dev
| Adding a System Call to the Linux Kernel |
cd
cd /home/<user>/kernel/linux-2.6.32.60(Screenshot)
mkdir hello(Screenshot)
cd hello
vi hello.c
The hello.c program should contain the following:
asmlinkage -- Tells the gcc compiler that the function should expect all its arguments on the "stack", and not in registers. On 32-bit Linux systems, system calls can have 4 arguments (in addition to the syscall number) that are passed on the stack. Of course, this "asmlinkage" macro is not necessary for our "hello" syscall, since it does not take any argument.
printk -- function to print messages used exclusively for the Linux Kernel. Mostly used for logging messages from the kernel.
vi Makefile(Screenshot)
The Makefile should contain the following:
cd ..Now edit the existing Makefile in the "linux-2.6.32.60" directory, using
vi MakefileOnce you are inside the Makefile, search for "core-y". In Vim/Vi, you can search this by going to the command mode by pressing "Esc" and executing the command /core-y. You can press "n" to go to the next instance of core-y. You should be able to find an instance which looks like the following:
Sometimes, after vi has found your desired search term, it might highlight the term (in this case, core-y) in black. As a result, it might apparently seem that the term core-y is invisible whereas, it has only been highlighted with the same black color as that of the background. So, try to manually look at the found line and check whether it contains the text starting from += upto block/.
These are the directories that will be recursively visited during the kernel compilation to look for source files that need to be compiled according to the individual Makefile in those directories.
cd arch/x86/kernel/Open the file named "syscall_table_32.S" using
vi syscall_table_32.STo add our system call's entry into the system call table, edit the file "syscall_table_32.S" by adding the following at the end of this file:
cd ..Then, go to the "include/asm" directory by doing
cd include/asmThen, open the file named "unistd_32.h" using
vi unistd_32.hNow, look for the line #define __NR_sched_other_rr_getquantum using the following in vi command mode:
/#define __NR_sched_other_rr_getquantumOnce you have found this line, go into the vi insert mode by pressing "i" and after the line
Before adding __NR_hello, the last system call entry was __NR_sched_other_rr_getquatum with the value 337. We add 1 to it and get the __NR_hello entry with 338.
Also, increment the existing NR_syscalls value by 1.
So, NR_syscalls should be 339
cd ../../../..Then, go to the "include/linux" directory using
cd include/linuxOpen the file named "syscalls.h" and add the declaration for our system call, at the end of the file.
vi syscalls.h
Then, add the following:
| Building and Installing Your Kernel |
#!/bin/sh
rev=$1
if [ -z "$rev" ]; then
echo "Usage: build64
"
exit 1
fi
make-kpkg --rootcmd fakeroot --initrd --revision=$rev kernel_image 2>&1 | tee build.log
sudo vi /usr/bin/kvm-kernel-build
#!/bin/sh
rev=$1
if [ -z "$rev" ]; then
echo "Usage: build64
"
exit 1
fi
make-kpkg -j 2 --rootcmd fakeroot --initrd --revision=$rev kernel_image 2>&1 | tee build.log
your_first_name@debian:~$ cd /home/your_first_name/kernel/linux-2.6.32.60/ your_first_name@debian:~/kernel/linux-2.6.32.60$ sudo kvm-kernel-build 1(Screenshot)
your_first_name@debian:~/kernel# su Password: root@debian:home/your_first_name/kernel$ dpkg -i linux-image-2.6.32.60_1_i386.deb Selecting previously deselected package linux-image-2.6.32.60. (Reading database ... 30041 files and directories currently installed.) Unpacking linux-image-2.6.32.60 (from linux-image-2.6.32.60_1_i386.deb) ... Done. Setting up linux-image-2.6.32.60 (1) ... Running depmod. Examining /etc/kernel/postinst.d. run-parts: executing /etc/kernel/postinst.d/initramfs-tools 2.6.32.60 /boot/vmlinuz-2.6.32.60 update-initramfs: Generating /boot/initrd.img-2.6.32.60 run-parts: executing /etc/kernel/postinst.d/zz-update-grub 2.6.32.60 /boot/vmlinuz-2.6.32.60 Generating grub.cfg ... Found linux image: /boot/vmlinuz-2.6.32.60 Found initrd image: /boot/initrd.img-2.6.32.60 Found linux image: /boot/vmlinuz-2.6.32-5-686 Found initrd image: /boot/initrd.img-2.6.32-5-686 doneWhen the command completes, the kernel is installed. Go back to being logged into your user using su your_first_name
(Screenshot)
your_first_name@eecs678-kvm:~/kernel$ cat /boot/grub/grub.cfg | moreYou should see a line that reads:
set default="0"The first 'menuentry' in this file should correspond to the kernel you just built (i.e. the version number should match 2.6.32.60). The next time you boot your kvm, it will have both the original kernel and the newly installed kernel selectable from the boot menu. If you use the -nographic option, you will not have the opportunity to select a kernel from the menu and it will automatically boot the default kernel. To change the default boot kernel, you need to change the GRUB_DEFAULT variable in /etc/default/grub to the number of the kernel in the boot menu that you want to boot into. The kernels in the boot menu are listed in /boot/grub/grub.cfg and are indexed at 0. If you change GRUB_DEFAULT, you need to update the grub menu by running (as root):
your_first_name@debian:~/kernel# su Password: root@debian:/home/your_first_name/kernel# reboot Broadcast message from root@debian (pts/0) (Fri Mar 1 22:31:19 2013): The system is going down for reboot NOW! root@debian:/home/your_first_name/kernel# Connection to localhost closed by remote host. Connection to localhost closed.This will kick you out of your kvm session. You need to wait for the KVM to boot before you can log back in.
root@debian:/home/your_first_name/kernel# reboot
Broadcast message from root@debian (pts/0) (Fri Mar 1 22:31:19 2013):
The system is going down for reboot NOW!
root@debian:/home/your_first_name/kernel# Connection to localhost closed by remote host.
Connection to localhost closed.
Then, you should select the Linux debian 2.6.32.60 option from the blue boot menu. You can log in directly to your newly created user account:
Linux debian 2.6.32.60 #1 SMP PREEMPT Fri Mar 1 21:56:30 CST 2013 i686 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. your_first_name@debian:~$You should see that you are running kernel version 2.6.32.60. If you want to double-check this from the command line inside KVM, you can do:
your_first_name@debian:~$ uname -a Linux eecs678-kvm 2.6.32.60 #1 SMP PREEMPT Fri Mar 1 21:56:30 CST 2013 i686 GNU/Linux
| Testing the System Call |
cd
vi test_syscall.cThe test_syscall.c file should contain the following:
gcc test_syscall.c -o test_syscallNow run test_syscall using the following command.
./test_syscall
This should print "System call sys_hello returned 100\n" based on the hello.c program
(Screenshot - after getting the output from ./test_syscall)dmesg | tail -5
This prints the last 5 lines from the kernel logs. Please look for the "Hello World" message printed in the kernel logs from your system call.
"Hello World" should be printed on the kernel logs based on the printk call in hello.c program
| Package Issues |
If you get the following error during your kernel build process:
root@debian:~# error: zlib.h: No such file or directoryPlease install the libz package by executing the following command:
root@debian:~# apt-get install libz-dev
| Other Important Commands |
your_first_name@debian:~$ scp cycle1.eecs.ku.edu:~/Desktop/foo.txt /home/your_first_name/kernel/linux-2.6.32.60/
amodarre@cycle1.eecs.ku.edu's password:
foo.txt 100% 954KB 954.3KB/s 00:00
your_first_name@debian:~$
This example, which is also run from within the KVM, copies foo.pdf from
the kvm to my Desktop on cycle1.eecs.ku.edu:your_first_name@eecs678-kvm:~$ scp /home/your_first_name/kernel/linux-2.6.32.60/foo.txt cycle1.eecs.ku.edu:~/Desktop/
amodarre@cycle1.eecs.ku.edu's password:
foo.txt 100% 954KB 954.3KB/s 00:00
your_first_name@debian:~$
root@debian:~# dpkg -r linux-image-2.6.32.60 (Reading database ... 30089 files and directories currently installed.) Removing linux-image-2.6.32.60 ... Examining /etc/kernel/prerm.d. Examining /etc/kernel/postrm.d . run-parts: executing /etc/kernel/postrm.d/initramfs-tools 2.6.32.60 /boot/vmlinuz-2.6.32.60 update-initramfs: Deleting /boot/initrd.img-2.6.32.60 run-parts: executing /etc/kernel/postrm.d/zz-update-grub 2.6.32.60 /boot/vmlinuz-2.6.32.60 Generating grub.cfg ... Found linux image: /boot/vmlinuz-2.6.32-5-686 Found initrd image: /boot/initrd.img-2.6.32-5-686 doneNote that you might need to reconfigure your boot loader after you uninstall the kernel package.
root@debian:~# halt Broadcast message from root@kvm (pts/0) (Thu Mar 21 19:58:54 2013): The system is going down for system halt NOW!
| Debugging the Linux Kernel |
Sometimes, it is necessary to add sometime to Linux kernel for experiment or fix a bug in the kernel. Debugging the kernel is a little bit different than debugging an application; because OS doesn't let any access from user to kernel mode directly. The following slides help you to understand how to debug the kernel.
| Submission Requirements |
Each student must submit a single report documenting their work for this lab. The report must include a brief description of your process and all required screenshots indicated throughout this document. Your grade for this lab is based entirely on this report and is worth 100 points.