HW8: 100 points total, group project
Submission notes
HW8 will be submitted in a single gzipped tarball named group_xx_hw8.tgz
where xx is your two digit group number (with leading zeros, if
applicable)
The top level directory in the tarball must be hw8
. You must track at
least the following files in the repo:
cabinet.c
Makefile
README.txt
Create a new repository for this assignment outside of the kernel source tree
Please use Linux kernel version 4.4.50
You will be implementing a syscall, inspect_cabinet()
, with syscall number 405.
In the skeleton code, we provide a patch that you should apply to your 4.4.50 kernel.
Move ikea.patch
into a fresh Linux 4.4.50 kernel source directory,
and run the following command:
patch -p1 < ikea.patch
Build and install your kernel as you did before using mmk
,
and then run this command to install the uapi/
headers:
sudo make headers_install INSTALL_HDR_PATH=/usr
Now you should be able to #include <linux/cabinet.h>
from userspace!
We’ve provided a tester program named cabinet_inspector
inside of test/
:
Try compiling it to make sure your headers are installed.
You may run cabinet_inspector
as follows:
sudo ./cabinet_inspector [<vaddr> [<pid>]]
See “Tester” section below for usage details.
We’ve also provided a reference_cabinet.ko
which you may insert
to compare against your own code’s functionality.
Please note that module is built with a kernel configuration that has had
make localmodconfig
run on it. Make sure you do this!
In case you have any problems with inserting this module with your own configuration,
we’ve also included an hw8-skel-config
file (generated from the vm17
reference VM)
which you can use to build your kernel, after you copy it to your kernel build directory:
cp hw8-skel-config <kernel/build/path>/.config
For this assignment, you will be implementing the syscall in a module.
Please write your code inside of the provided modules/cabinet.c
file,
and do not modify the provided boilerplate code.
You should start your code in inspect_cabinet()
,
and feel free to define and call any more functions inside your module.
Once you have completed writing your code, you should test it with the given tester.
In your README.txt
, you should describe how you tested your code,
what processes you tested it with, and what you found.
You will be submitting everything inside of the provided module/
directory,
so you should copy those files into your submission directory
and run git init
in there. You should also be submitting a README.txt
.
For example, the following files should be tracked in your hw8
submission directory:
$ git ls-files
cabinet.c
Makefile
README.txt
Note that for this assignment, you will not be submitting a sparse repo.
The function prototype for inspect_cabinet()
is the following:
int inspect_cabinet(pid_t pid, unsigned long vaddr, struct cab_info *inventory);
inspect_cabinet()
will take in three arguments:
pid
: the pid of the process for which the lookup will be performed
pid
is –1, then the syscall will be performed on current process’s PIDvaddr
: the virtual address for which the lookup will be performed
inventory
: a pointer to the struct which will be populated with the found information
inspect_cabinet()
will report the following information about the process with that PID:
The physical address associated with the specified virtual address
The physical addresses of its page frame and all intermediate page tables (PTE, PMD, PUD, PGD)
Whether or not the page containing specified virtual address has been modified
The number of processes that share the specified virtual address
This information will be used to populate the struct cab_info
, which is defined as follows:
struct cab_info {
unsigned long paddr; /* the physical address the virtual address is mapped to */
unsigned long pf_paddr; /* the physical address of its page */
unsigned long pte_paddr; /* the physical address of its PTE */
unsigned long pmd_paddr; /* the physical address of its PMD */
unsigned long pud_paddr; /* the physical address of its PUD */
unsigned long pgd_paddr; /* the physical address of its PGD */
int modified; /* 1 if modified, 0 otherwise */
int refcount; /* number of processes sharing the address */
}
The user calling the syscall must first allocate this struct in userspace, and provide the pointer to it as a parameter.
On success, inspect_cabinet()
should return 0
If the page or any of the intermediate page tables are not present in memory,
then its physical address and those of subsequent page frames should be set to 0.
The value of the modified
and refcount
fields should also be set to 0.
The syscall should still return 0
pmd_paddr
, pte_paddr
, pf_paddr
, paddr
, modified
, and refcount
should all be set to 0, and inspect_cabinet()
should return 0If the user issuing the syscall is not root, return EACCES
If the specified PID is invalid (i.e. < –1), return EINVAL
If the specified PID does not exist, return ESRCH
If the specified virtual address does not exist, return EINVAL
If the pointer to the struct cab_info
is invalid, return EFAULT
The usage for the tester is as follows (it must be run as root):
sudo ./cabinet_inspector [<vaddr> [<pid>]]
The tester will call cabinet_inspector()
with the specified virtual address and PID,
and print out the information returned.
If pid
is omitted, then –1 is used as the pid
argument,
i.e. it will be interpreted as the PID of the calling process
If vaddr
is omitted as well, then the vaddr
argument supplied to the syscall
is the address of a local (stack) variable of the calling process
Example output:
inspecting cabinet for <virtual address> of pid=<pid>
paddr: <physical address>
pf_paddr: <physical address>
pte_paddr: <physical address>
pmd_paddr: <physical address>
pud_paddr: <physical address>
pgd_paddr: <physical address>
modified: [yes|no]
refcount: <reference count>
You may use /proc/<pid>/maps
to find useful virtual memory addresses to test this on.
You may also consult test/session{1,2,3}.txt
for example shell sessions
testing with the cabinet_inspector
.
The README.txt
in test/
will contain more documentation about this.
Below is some online reading material that you may find helpful for this assignment:
Understanding the Linux Virtual Memory Manager: Page Table Management
Stack Overflow: Difference between Kernel Virtual Address and Kernel Logical Address?
The Cabinet assignment and reference implementation are designed and implemented by the following TAs of COMS W4118 Operating Systems I, Spring 2017, Columbia University:
Last updated: 2017–04–23