This project is due on Monday, December 14, at 11:59:59 PM (Eastern standard time). You must use the submit to turn in your homework like so: submit cs421_jtang proj2 scrubber.c scrubber-test.c
Your driver code must be named scrubber.c. It will be compiled against a 4.1 Linux kernel source tree, via the Kbuild supplied below. It must not have any compilation warnings; warnings will result in grading penalties. This module code must be properly indented and have a file header comment, as described on the coding conventions page. Prior to submission, use the kernel's indentation script to reformat your code, like so:
~/linux/scripts/Lindent scrubber.c
In addition, you will write a unit test program, scrubber-test.c. This code must also have a file header comment and be properly indented. You will submit this test code along with your module code.
In this project, you will write a Linux driver that operates upon a virtual Internet filter. The user stores an arbitrary list of dirty words in your driver. Your driver then scans incoming network packets for those dirty words. For each found word, censor that word by overwriting it with asterisks.
All instructions hereforth assume you successfully completed the first homework. If you have not done so, go back and finish the homework before proceeding. You have been warned.
To begin, create a directory for your project and download the following files into that directory via wget:
After downloading all of these files, you need to then recompile your kernel:
make cs421_defconfig make -j3 sudo make modules_install install
Now return to your proj2 directory. Run make to compile this project's files. Upon success, run proj2_start.sh (it may ask for your password, as that it runs some sudo commands). This will set up your VM for this project. Rerun this script if you ever need to reboot your VM.
In scrubber.c, you need a data structure to hold the list of dirty words. The kernel linked list is ideal for this. Declare a global variable to hold your list. Because this list will be accessed by many threads, also declare a global spinlock to guard the list.
Next, modify scubber_write()
as per its comments. For
each word within the user buffer, allocate a new list entry
(via kmalloc()
) and store the word. Add that entry to
the dirty word list with the list_add_tail()
macro. Protect all accesses to the list with your spinlock.
When scanning the user buffer for words, do not add empty words to the dirty word list. Assume that words consist of only alphabetic characters. The list may have duplicate words.
Ensure your scrubber_exit()
frees all memory that have
been allocated by the list.
Although not required, you may want to add
a scrubber_read()
that will return the list of dirty
words. This will prove useful when debugging your driver.
Next, you need to add interrupt handling. Read the code xt_filter.c. When this Internet filter is enabled, it will intercept all incoming network packets and raise an interrupt. It is your driver's responsibility to catch those interrupts and scrub the payloads.
In scrubber_init()
, install a threaded interrupt
handler for the interrupt number FILTER_IRQ
. Remove
that handler in
scrubber_exit()
. Implement your interrupt handler as
follows:
/** * scrubber_check() - top-half of scrubber ISR * @irq: IRQ that was invoked * @cookie: Pointer to data that was passed into * register_threader_irq() (ignored) * * If @irq is FILTER_IRQ, then wake up the bottom-half. Otherwise, * return IRQ_NONE. */ static irqreturn_t scrubber_check(int irq, void *cookie); /** * scrubber_handler() - bottom-half to scrubber ISR * @irq: IRQ that was invoked * @cookie: Pointer that was passed into register_threaded_irq() * (ignored) * * For each word in the dirty word list, scan the payload for that * word. For each instance found, case-sensitive matching, overwrite * that part of the payload with asterisks. Afterwords, resume the * Internet filter. * * HINT: use list_for_each_entry() to iterate over the dirty word list * HINT: strnstr()/memcmp() and memset() are useful here. * * WARNING: The payload is not null-terminated. * * Return: always IRQ_HANDLED */ static irqreturn_t scrubber_handler(int irq, void *cookie);
Once you are confident your ISR works,
add filter_enable()
to scrubber_init()
(and likewise disable the filter
in scrubber_exit()
). Install your module, and
check /proc/interrupts to ensure the ISR was
registered.
As stated earlier, ensure you have run proj2_start.sh before proceeding.
In one terminal, run this command: nc -l 4210. In a second terminal, run this command: telnet localhost 4210. Use this second terminal to send strings to the first terminal. Open a third terminal; use this one to write entries to /dev/scrubber.
For example, suppose in the third terminal you ran this:
$ echo "the" > /dev/scrubberThen in the second terminal, send this input:
To be, or not to be, that is the question.Your first terminal should display this:
To be, or not to be, that is *** question.If in the third terminal, you then ran this:
$ echo -e "in\ner" > /dev/scrubberAnd you send this in the second terminal:
Whether 'tis Nobler in the mind to sufferYou should get this in the first terminal:
Whe***r 'tis Nobl** ** *** m**d to suff**Note how for the input Whether, both the words the and er matched. In this case, the word first added to the dirty word list (the) has precedence.
You can close the telnet session by pressing control-] (right bracket) and then typing in close.
Now that you have (in theory) a working driver, you must then write your own unit tests. Read through the code given in scrubber-test.c. Modify the code as follow:
The unit tests must have comments that explain what things are being tested. You will be graded based upon the thoroughness of the tests.
You may earn an additional 20% credit for this assignment by augmenting your scrubber driver. Have your driver create another character device, /dev/scrubber_del. For each word written to this device node (again, newline separated), scan scrubber's list of dirty words. If the string matches an entry (case-sensitive), remove that entry (without leaking any memory). If there are no matching entries for a word, then your driver should ignore that word.
Afterwards, update scrubber-test.c to test this new functionality.
If you choose to perform this extra credit, put a comment at the top of your file, alerting the grader.