HW4: Linux System Calls


As with previous assignments, we will be using GitHub to distribute skeleton code and collect submissions. Please refer to our Git Workflow guide for a more details. Note that we will be using multiple tags for this assignment, for each deliverable part.

Part 1: Building a Kernel in Debian Linux



Kernel Compilation in Debian Linux

First, follow the above guide and compile yourself a pristine (unmodified) kernel from the 4.9.153 Linux source provided in the skeleton repo. You should name it 4.9.153-cs4118, and keep it around as your fallback kernel for all future assignments (including this one), in case you run into any trouble booting into the kernel you’re working on.

Additionally, make sure that the CONFIG_BLK_DEV_LOOP option is set to y in your .config file before you build and install your pristine kernel. This will come in handy in later assignments.


Part 2: Reducing Kernel Build Time (optional)

In this part, you will reduce your kernel build time drastically.



A large amount of time is spent compiling and installing kernel modules you never use. You can regenerate .config so that it contains only those modules you are currently using. This will drastically cut down the number of modules. This is how:

  1. First, backup your .config to something like .config.<UNI>-from-lts.

    • Make sure to keep your local version the same as what it was in part 1; that is, your kernel should still be named 4.9.153-cs4118.
  2. Run make localmodconfig in your Linux kernel source tree.

    • This will take your current .config and turn off all modules that you are not using.

    • It will ask you a few questions. You can hit ENTER to accept the defaults, or just have yes do so for you:

      $ yes '' | make localmodconfig
    • Make sure that CONFIG_BLK_DEV_LOOP is still set to y before building and installing this kernel.

    • Also set CRYPTO_CRC32C_INTEL to y. This is needed to ensure the boot process is successful.

      • Disclaimer: We don’t actually know why this works. We are still investigating this issue. But for now, this will get you through this part.

Now you have a much smaller .config. You can follow the rest of the steps starting from make.

Don’t Reinstall Modules

When you are hacking kernel code, you’ll often make simple changes to only a handful of .c files. If you didn’t touch any header files, the modules will not be rebuilt when you run make; thus there is no reason to reinstall all modules every time you rebuild your kernel.


Part 3: The supermom() System Call

Note: You’re about to make changes to the pristine kernel source. This means that what you build from it might not even boot. In order to make sure that you always have the -cs4118 pristine kernel as a fallback to boot into, you should avoid overwriting it by setting the local version in your .config file to something else, like your UNI (for example, -abc1234). Make sure to verify your changes:

$ hw4-<username>/linux/scripts/diffconfig .config.old .config
 LOCALVERSION "-cs4118" -> "-abc1234"

You should use your UNI as the local version for all modified kernels you build for this course from now on.

You are now ready to add some system calls to your kernel.



Implement a new system call, supermom(), which checks if the parent process of the calling process has superuser privileges.

At this time of writing, the Linux kernel has about 330 system calls, though new system calls are constantly being added to the Linux kernel. Let’s leave some room and use 400 as the syscall number for supermom().

The system call should have the following interface:

long supermom(pid_t pid, uid_t *uid);

This is what it should do:

LKD Chapter 5 tells you what you need to do to copy values between kernel and user space.

A few things that you might find helpful:

The purpose of this part is to learn how to add a system call, and get a little bit of practice navigating through kernel code and documentation. As such, we are going to ignore a big issue in correctly implementing a system call – we are going to ignore race conditions. You don’t have to worry about synchronization in implementing supermom().


In order to test your syscall, you should write a test program that performs the syscall from userspace. To learn how to make a syscall, read:

$ man 2 syscall

You may optionally submit your test program under the user/test/ (you will have to create this directory yourself).



To submit this part, push the hw4p3handin tag with the following:

$ git tag -a -m "Completed hw4 part3." hw4p3handin
$ git push origin master
$ git push origin hw4p3handin

Part 4: Moving a system call into a kernel module

By now, you must be tired of rebooting your VM every time you make a small change in system call code. In this part, we will move the code for supermom() into a dynamically loadable kernel module. Our goal is to be able to make modifications to the system call code without having to reboot the machine.



There are two ways to implement a system call using a module. You can try to modify the system call table from the module initialization code. Changes in recent kernels on the mechanics of setting up system calls make this method more cumbersome than it used to be, so we are not going to do this.

Another way is to leave the system call definition in the static kernel code, but have it call another function defined in a module. This is our approach.

Move your implementation of the supermom() syscall to the provided module skeleton code:

Big hint: use function pointers.


Make sure you’re still able to run your test program you wrote in Part 3 before you load your module (deactivated), after you load your module (activated), and after you unload your module (deactivated again). You should check that errors are gracefully handled (i.e. the appropriate errnos are set and checked for).



To submit this part, push the hw4p4handin tag with the following:

$ git tag -a -m "Completed hw4 part4." hw4p4handin
$ git push origin master
$ git push origin hw4p4handin

Good luck!

Last updated: 2019-02-15