Assignment 1 - Kprobe based tracer¶
- Deadline: Wednesday, April 7th 2021, 23:00
Assignment's Objectives¶
- gaining knowledge related to the instrumentation of functions in the Linux kernel (
kretprobes
mechanism) - gaining knowledge regarding the
/proc
file system from the Linux kernel - get familiar with data structures specific to the Linux kernel (
hash table
andlist
)
Statement¶
Build a kernel operations surveillant.
With this surveillant, we aim to intercept:
kmalloc
andkfree
callsschedule
callsup
anddown_interruptible
callsmutex_lock
andmutex_unlock
calls
The surveillant will hold, at the process level, the number of calls for each of the above functions.
For the kmalloc
and kfree
calls the total quantity of allocated and deallocated memory will be
shown.
The surveillant will be implemented as a kernel module with the name tracer.ko
.
Implementation details¶
The interception will be done by recording a sample (kretprobe
) for each of the above functions. The
surveillant will retain a list/hashtable with the monitored processes and will account for
the above information for these processes.
For the control of the list/hashtable with the monitored processes, a char device called /dev/tracer
will be used, with major 10 and minor 42. It will expose an ioctl
interface with two arguments:
the first argument is the request to the monitoring subsystem:
TRACER_ADD_PROCESS
TRACER_REMOVE_PROCESS
the second argument is the PID of the process for which the monitoring request will be executed
In order to create a char device with major 10 you will need to use the miscdevice interface in the kernel. Definitions of related macros can be found in the tracer.h header.
Since the kmalloc
function is inline for instrumenting the allocated amount of memory, the __kmalloc
function will be inspected as follows:
- a
kretprobe
will be used, which will retain the amount of memory allocated and the address of the allocated memory area. - the
.entry_handler
and.handler
fields in thekretprobe
structure will be used to retain information about the amount of memory allocated and the address from which the allocated memory starts.
static struct kretprobe kmalloc_probe = {
.entry_handler = kmalloc_probe_entry_handler, /* entry handler */
.handler = kmalloc_probe_handler, /* return probe handler */
.maxactive = 32,
};
Since the kfree
function only receives the address of the memory area to be freed, in order to determine
the total amount of memory freed, we will need to determine its size based on the address of the area.
This is possible because there is an address-size association made when inspecting the __kmalloc
function.
For the rest of the instrumentation functions it is enough to use a kretprobe
.
static struct kretprobe up_probe = {
.entry_handler = up_probe_handler,
.maxactive = 32,
};
The virtual machine kernel has the CONFIG_DEBUG_LOCK_ALLOC
option enabled where the mutex_lock
symbol
is a macro that expands to mutex_lock_nested
. Thus, in order to obtain information about the mutex_lock
function you will have to instrument the mutex_lock_nested
function.
Processes that have been added to the list/hashtable and that end their execution will be removed
from the list/hashtable. Also, a process will be removed from the dispatch list/hashtable following
the TRACER_REMOVE_PROCESS
operation.
The information retained by the surveillant will be displayed via the procfs file system, in the /proc/tracer
file.
For each monitored process an entry is created in the /proc/tracer
file having as first field the process PID.
The entry will be read-only, and a read operation on it will display the retained results. An example of
displaying the contents of the entry is:
$cat /proc/tracer
PID kmalloc kfree kmalloc_mem kfree_mem sched up down lock unlock
42 12 12 2048 2048 124 2 2 9 9
1099 0 0 0 0 1984 0 0 0 0
1244 0 0 0 0 1221 100 1023 1023 1002
1337 123 99 125952 101376 193821 992 81921 7421 6392
Testing¶
In order to simplify the assignment evaluation process, but also to reduce the mistakes of the submitted assignments, the assignment evaluation will be done automatically with the help of a test script called _checker. The test script assumes that the kernel module is called tracer.
Tips¶
Create the skeleton by running the command below:
$ LABS=assignments/1-tracer make skels
To increase your chances of getting the highest grade, read and follow the Linux kernel coding style described in the Coding Style document.
Also, use the following static analysis tools to verify the code:
- checkpatch.pl
$ linux/scripts/checkpatch.pl --no-tree --terse -f /path/to/your/tracer.c
- sparse
$ sudo apt-get install sparse
$ cd linux
$ make C=2 /path/to/your/tracer.c
- cppcheck
$ sudo apt-get install cppcheck
$ cppcheck /path/to/your/tracer.c
Penalties¶
Information about assigments penalties can be found on the General Directions page. In addition, the following elements will be taken into account:
- -2: missing of proper disposal of resources (
kretprobes
, entries in/proc
) - -2: data synchronization issues for data used by multiple executing instances (e.g. the list/hashtable)
In exceptional cases (the assigment passes the tests but it is not complying with the requirements) and if the assigment does not pass all the tests, the grade may decrease more than mentioned above.
Submitting the assigment¶
The assignment archive will be submitted to vmchecker, according to the rules on the rules page.
From the vmchecker interface choose the Kprobe Based Tracer option for this assigment.
Resources¶
- Documentation/kprobes.txt - description of the
kprobes
subsystem from Linux kernel sources. - samples/kprobes/ - some examples of using
kprobes
from Linux kernel sources.
We recommend that you use gitlab to store your homework. Follow the directions in README and on the dedicated git wiki page.
Questions¶
For questions about the topic, you can consult the mailing list archives or send an e-mail (you must be registered).