HW4-supermom

HW4: Linux System Calls

Submission

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 Arch Linux

Reading

Task

Kernel Compilation in Arch Linux

First, follow the above guide and compile yourself a pristine (unmodified) kernel from the 4.9.81 Linux source provided in the skeleton repo. You should name it 4.9.81-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.

As you’re doing kernel development, all of those steps will become quite cumbersome. For the deliverable, you will write a script that will automate all the steps in the kernel compilation guide starting from make.

Your shell script should be called mmk (“make my kernel”), and placed in the directory, hw4-<username>/user/scripts/.

The mmk script should be run from the top level Linux kernel source directory, hw4-<username>/kernel/. The script should take two arguments, as follows:

$ ../user/scripts/mmk <kernel-name> <local-version>

For example:

$ ../user/scripts/mmk 4.9.81 cs4118

Make sure you can launch this script as a non-root user; you may use sudo within the script for the commands that require root privileges. At the top of your script, you should use the set -e to ensure that the script will terminate if any of the subsequent commands fail.

Optional tasks (these are optional because this is an OS course, not a shell scripting course, but seriously, any self-respecting hacker should learn to write shell scripts):

Please mention what shell scripting features you implemented in your README.txt, especially if there’s any cool things you did that we didn’t think of.

Submission

Deliverable: hw4-<username>/user/scripts/mmk shell script

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

$ git tag -a -m "Completed hw4 part1." hw4p1handin
$ git push origin master
$ git push origin hw4p1handin

Part 2: Reducing Kernel Build Time

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

Tasks

localmodconfig

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 cut down the number of modules from something like 3000 to under 100. 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.81-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.

Now you have a much smaller .config. You can follow the rest of the steps starting from make. (You can run your mmk script instead of following the steps again manually, of course.)

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.

Make a stripped-down version of your mmk script called mko (“make kernel only”), which does only the following 3 things:

Again, your script should be written in the hw4-<username>/user/scripts/ directory.

Now you have mmk to build the kernel, install modules, and rebuild vboxguest, but much, much faster thanks to the smaller .config produced by localdefconfig. In additional, you have mko for quick build & reboot cycles when you didn’t touch any header files.

Submission

Deliverable: hw4-<username>/user/scripts/mko shell script

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

$ git tag -a -m "Completed hw4 part2." hw4p2handin
$ git push origin master
$ git push origin hw4p2handin

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>/kernel/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.

Reading

Task

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().

Testing

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).

Submission

Deliverables:

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.

Reading

Task

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.

Testing

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).

Submission

Deliverables:

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: 2018-02-24