CSE451 Spring 2008 Project #2

Out: April 17 2008

Due: May 2 2008

Objectives

In the first project you learned how to build and debug the windows kernel, and how to enhance a system call. This second project builds on the first one by requiring more information be safely managed and returned via the query call. The principal objectives of this second project are:

  1. Learn how to use synchronization primitives to ensure your code is properly synchronized for a multi-processor and preemptive kernel environment.
  2. Learn how to manage dynamic data in a kernel.
  3. Learn about buffering data and dealing with unexpected overflow conditions

Getting Started

Some of the new tools that you will need for the project are:

  1. Mutex - Defined in base\ntos\inc\ex.h are a set of routines to manipulate a structured called a FastMutex. A FastMutex is a basic synchronization mechanism used throughout the kernel. It is essentially a binary semaphore but optimized for single ownership.

  1. Pool - Dynamically allocated memory in the kernel is called pool. There are two types of pool “PagedPool” and “NonPagedPool.” PagedPool is memory that is allowed to be paged out to disk, while NonPagedPool must remain in memory at all times. As a rule of thumb allocation should be from PagedPool unless the code accessing the data must not take a page fault. For example, the paging code itself can never take a page fault, otherwise the data can never be read. Another rule of thumb in Windows is to never take a page fault holding a spinlock or with interrupts disabled. The routines to allocate and free memory is called ExAllocatePool and ExFreePool. They are declared in base\ntos\ex.h and their usage is pretty straightforward.

  1. Time - Time in NT is stored in the kernel as a 64 bit integer. The resolution is 100ns. Kernel mode code calls KeQuerySystemTime to get the current time. There are also routines in base\ntos\rtl\time.c to help manipulate times.

This is just a partial list to help you get started, there are definitely more things in the kernel that you can use to help complete this project.

Your assignment:

Start by copying your own solution for Project 1 to a new directory called Project 2. Alternatively you can start with my nominal solution to project 1 which will be available on or after April 17.

  1. Most likely your solution for project 1 did not fully synchronize access to your kernel data structures and therefore the code will not always yield the correct answer on a preemptive kernel or on an MP system. The first part of this assignment is to correct this deficiency by protecting access to all the data structures that you added to project 1. You should use this using the Mutex provided in NT. Granularity (or scope) of the lock is up to you.

  1. We want to enhance the NT API counters logic from project 1 to include the order in which the actual calls and returns take place. To do this you will need to have the system keep a history buffer of these events that will be returned to the user on the query call. Each event needs to have a timestamp and specify an action. Actions are either “Call”, “Return”, or “Buffer Overflow”. Each Call and Return action must also specify its appropriate NT API classification. In addition each return event must specify its returns status classification. The “Buffer Overflow” will denote holes in the timeline where the system was unable to keep a full history because of memory limitations.

  1. Modify your test program to take as input a buffer size. The buffer size is the number of bytes to use when calling NtQuerySystemInformation. The new output can now look like:

API Total

Class Calls Success Information Warning Error

----- -------- ------- -------- ------- ------

NtOpen 56 50 2 3 1

NtRead 123 100 0 0 23

History

-------

yyyy/mm/dd HH:MM:SS.sss NtOpen Call

yyyy/mm/dd HH:MM:SS.sss NtOpen Return Success

yyyy/mm/dd HH:MM:SS.sss NtRead Call

yyyy/mm/dd HH:MM:SS.sss NtQuery Call

Buffer Overflow

yyyy/mm/dd HH:MM:SS.sss NtWrite Return Warning

Turn-in:

Be prepared to turn in the following

  1. Executables images of your test program, and the modified kernel.
  2. Source code for your test program and the modules that you have modified and added to your kernel.

You'll be submitting the source code and executables to Catalyst. Please seperately submit test.exe, wrkx86.exe, and a zip of your entire source directory (After running 'nmake clean').

Grading Criteria:

Your project will be graded based on the following criteria:

  1. [50%] Does it accomplish the assigned task, split evenly between synchronization and history buffering?
  2. [15%] Are your modifications to the kernel clear and easy to understand?
  3. [15%] Are your modifications to the kernel correct?
  4. [10%] Is the output of the test program clear and easy to understand?
  5. [10%] Is the coding of the test program clear and easy to understand?

  1. [10% Extra Credit] Wrote Own Synchronization.