In contemporary operating systems, low-level components, often referred to as kernel mode components, including drivers and the operating system itself, handle critical system operations. For performance and architectural reasons, drivers typically load in an environment in which a loaded driver can access the resources of another loaded driver. Consequently, kernel mode components, such as drivers, are typically highly privileged in the operations that they are allowed to perform. Because of these privileges, the typical operating system cannot provide the same protection mechanisms as it can for higher level components, such as software applications. As a result, even the slightest error in kernel components can corrupt the operating environment and cause a computer system crash.
Determining the cause of a computer system crash so that an appropriate fix may be made can be a difficult, labor-intensive and somewhat unpredictable task, particularly since it is often difficult to replicate the exact conditions under which an error occurred. Additionally, pre-emptive testing of driver functionality in specific scenarios can be difficult for infrequently accessed events. For example, if a thread that previously issued an I/O request exits before the request is completed, a cancel routine associated with the request can be called to clean up resources associated with the previously pending request. Because cancellation of a request is an event that happens infrequently, execution of the cancellation routine may not be thoroughly tested in a typical driver testing environment. Another common error condition can occur when drivers fail to pend requests that can take a long or indefinite amount of time. Failure to appropriately pend requests can result in resources related to the request being released before the request has completed. Premature release of resources related to a request can cause data corruption and result in a system crash.
Another type of error condition occurs when a driver component incorrectly accesses data structures associated with pending I/O requests. For example, when a first driver component transmits an I/O request to a second driver component, the first driver component must correctly handle the case where the second driver returns a “status pending” notification. If the first driver does receive status pending in return, then the first driver must ensure that data structures referenced by the request are not freed until the request completes. Further, after the request completes, the first driver must not reference any fields associated with the request because the request might have previously been freed, and thus the driver would be accessing bad data. This error condition is also difficult to test because a tester of the first driver may not be able to control whether the second driver returns a pending status in response to I/O requests.
Yet another type of error condition occurs when user mode handles are referenced with kernel mode privileges. User mode handles, as non-privileged handles, should be restricted to referencing only objects to which the current user has been granted security access. This restriction facilitates security checks. However, if a user mode handle is referenced as kernel mode by a driver, then the normal security checks that would be applied to the handle are forgone. In such a case, the currently running application can access an object referenced by the handle even when executed by a user in a security context that normally would not allow the user access to the referenced object. Further, the unprivileged process can modify the user handle such that it will reference a second object which is different from the original object referenced by the same handle value. This can cause the privileged kernel code to access the second object even though the handle was intended to access the original object.
Another type of error occurs when unprivileged user mode memory addresses cross the kernel mode security boundary. Accessing user mode memory from kernel mode code can be a security risk because the unprivileged user mode application can free the memory being accessed, change its memory protection, or change the contents of that memory while the kernel mode code is accessing it. There are specific guidelines that all code running in kernel mode at the boundary of the user mode should follow to guard the system from a possible attack or errors propagated from user mode. However, once the boundary of trust has been crossed the kernel mode code is allowed to assume that all the memory addresses it receives from its callers are kernel mode addresses that are fully trusted. Thus, a security risk is created when the user-kernel mode boundary code allows any of the untrusted user memory addresses to cross the boundary of trust. This can result in various types of data corruption, system crashes, or typical security vulnerabilities, such as elevation of privilege, information disclosure, tampering of data or denial of service.
In addition to being deficient in testing error conditions, driver verification tools typically require a system restart when additional drivers are to be tested and/or when the set of checks is modified.
This summary is provided to introduce a selection of concepts in a simplified form that are further described below in the Detailed Description. This summary is not intended to identify key features of the claimed subject matter, nor is it intended to be used as an aid in determining the scope of the claimed subject matter.
In accordance with an aspect of the invention, a method for verifying driver component behavior is provided. The method can be implemented by a driver verification component. In accordance with the method, the driver verification component verifies that a driver component processes I/O requests in a specified amount of time. I/O requests which do not complete immediately are generally classified as “pending.” The driver verification component verifies that pending I/O requests are processed correctly by a driver component. Further, the driver verification component verifies that a set of parameters in a call to a driver component conforms with security requirements.
In accordance with another aspect of the invention, a computer-readable medium having computer-executable modules for verifying driver components is provided. The computer executable modules include a verification test module for determining whether a driver component processes I/O requests in a specified amount of time. Further, the computer executable modules include a verification test module for determining whether pending I/O requests are processed correctly by a driver component. Still further, the computer executable modules include a verification test module for determining whether a set of parameters in a call to a driver component conforms with security requirements.
In accordance with a further aspect of the invention, a method for enabling a driver verification component is provided. A first initialization of the driver verification component is performed. The first initialization includes initialization of data structures associated with the driver verification component. A request to fully enable the driver verification component is obtained. A second initialization of the driver verification component is performed. The second initialization fully enables the driver verification component for selected driver components. Additionally, the settings associated with the driver verification component can be modified.
The foregoing aspects and many of the attendant advantages of this invention will become more readily appreciated as the same become better understood by reference to the following detailed description, when taken in conjunction with the accompanying drawings, wherein:
Generally described, the present invention is directed toward systems and methods for verifying the behavior of user-specified kernel mode components, commonly referred to as drivers. More specifically, in accordance with the present invention, a driver verification component monitors driver processing of requests and ensures that various parameters in a call to a driver component conform with security requirements. Additionally, in another aspect, the driver verification component may be fully initialized when a request to modify the settings of the driver verification component is received. Although the present invention will be described with relation to illustrative verification methods, one skilled in the relevant art will appreciate that the disclosed embodiments are illustrative in nature and should not be construed as limiting.
With reference now to
In an alternative embodiment, a driver component 104 can transmit a request directly to the kernel component 108. Further, the kernel component 108 can transmit a request to an object manager, which in turn transmits a request to the driver verification component 106. It will be appreciated by those skilled in the art that the path by which a request travels to the driver verification component 106, and by which a response travels from the driver verification component 106, is not limiting. Further, requests may originate with the driver component 104 and need not be obtained from a user program component 102.
In an illustrative embodiment, a user program component 102 can be a word-processing program, a spreadsheet program, a media player, a web browser, a program that allows a user to manipulate files, or any other type of program that operates in user mode. Additionally, one skilled in the art will appreciate that a driver component 104 may be a disk driver, a keyboard driver, a mouse driver, a network adapter driver, a filter driver, or any other type of driver. Further, one skilled in the art will appreciate that the kernel component 108 is generally the portion of an operating system which manages memory and files and allocates system resources. Additionally, one skilled in the art will appreciate that a request may be a request to perform an I/O operation or any other type of request.
The computer system 100 can include a variety of computer-readable media. Computer-readable media can be any available media that can be accessed by the computer system 100 and includes both volatile and non-volatile media, removable and non-removable media. By way of example, and not limitation, computer-readable media may comprise computer storage media and communication media. Computer storage media includes, but is not limited to, RAM, ROM, EEPROM, flash memory or other memory technology, CD-ROM, Digital Versatile Disk (DVD) or other optical disk storage, magnetic cassettes, magnetic tape, magnetic disk storage or other magnetic storage devices, or any other medium which can be used to store the desired information and which can be accessed by the computer system 100.
The communication media typically embodies computer-readable instructions, data structures, program modules or other data in a modulated data signal such as a carrier wave or other transport mechanism and includes any information delivery media. The term “modulated data signal” means a signal that has one or more of its characteristics set or changed in such a manner to encode information in the signal. By way of example, and not limitation, communication media includes wired media such as a wired network or direct wired connection, and wireless media such as acoustic, RF, infrared and other wireless media. Combinations of any of the above should also be included within the scope of computer-readable media.
The invention may be described in the general context of computer-executable instructions, such as program modules, executed by one or more computers or other devices. Generally, program modules include routines, programs, objects, components, data structures, etc. that perform particular tasks or implement particular abstract data types. Typically the functionality of the program modules may be combined or distributed as desired in various embodiments.
With reference now to
At block 206, the driver verification component 106 performs a handle verification sub-routine. In an illustrative embodiment, a request made to a driver component 104 may include a handle parameter. Further, in an illustrative embodiment the driver verification component 106 verifies that the handle conforms with security requirements. An exemplary handle verification sub-routine is depicted in
With reference now to
At decision block 304, a test is conducted to determine if execution of a cancellation test is requested. In an illustrative embodiment, a user or administrator can issue a request that results in execution of a cancellation test. If cancellation was requested, a cancellation test is executed at block 306. An exemplary cancellation test is depicted in
With reference now to
If a driver component 104 pended the request and set a cancel routine, a test is conducted at decision block 408 to determine whether cancellation should be forcibly injected. In an illustrative embodiment, a probability parameter can be used to determine whether cancellation should be forcibly injected. For example, a user may configure the probability parameter such that cancellation is forcibly injected a certain percentage of time. In an illustrative embodiment, the probability parameter allows a user to inject forced cancellations into a specified percentage of requests. If, at decision block 408, it is determined that cancellation should be forcibly injected, then a cancellation test is executed at block 410. An exemplary cancellation test is depicted in
With reference now to
With reference now to
At decision block 606, a test is conducted to determine whether the request is pending. In an illustrative embodiment, if the request is pending, then the portion of driver component code which handles pending requests can be exercised without any action on the part of the driver verification component 106. Thus, at block 608, sub-routine 600 returns to routine 200. If the request is not pending, a test is conducted at decision block 610 to determine whether the request status should be forced to pending. In an illustrative embodiment, forced pendings may be injected based on a probability -parameter. For example, a user may choose to inject forced pendings into a certain percentage of requests. In an illustrative embodiment, the driver verification component 106 determines whether status pending should be injected into a request by calculating a random number and comparing it with the probability parameter. If forced pending status is not injected into a request, at block 608, sub-routine 600 returns to routine 200.
In an illustrative embodiment, if pending status is to be forcibly injected, at block 612, the status of the request is saved. In an illustrative embodiment, the driver verification component 106 creates a data structure in which to store the request status. At block 614, the status of the request is set to “pending.” In an illustrative embodiment, setting the status of the request to pending allows a driver component 104 to exercise a portion of code which handles pending requests, which is depicted at block 616. The pending verification sub-routine 600 can be used to ensure that data structures associated with an I/O request are not freed until the request completes. At block 618, the request status stored at block 612 is restored and processing of the request is resumed. At block 620, sub-routine 600 returns to routine 200.
With reference now to
If the handle is not referenced as kernel mode, at block 714, sub-routine 700 returns to routine 200. Otherwise, at decision block 708, a test is conducted to determine whether the handle is a user mode handle. In an illustrative embodiment, a handle may be either a user mode handle or a kernel mode handle. If the handle is not a user mode handle, at block 716, sub-routine 700 returns to routine 200. Alternatively, a user is notified of an error at termination block 710. Error notification may occur through initiation of a bug check, by logging the error, or through other techniques well-known in the art. Thus, sub-routine 700 results in an error notification when user mode handles are referenced as kernel mode. In an illustrative embodiment, a user can select to verify a subset of driver calls. Further, a subset of driver calls may be verified based on system settings.
With reference now to
If the address will not be referenced as kernel mode, at block 814, sub-routine 800 returns to routine 200. Otherwise, at decision block 808, a test is conducted to determine whether the address is a user mode address. In an illustrative embodiment, an address may be either a user mode address or a kernel mode address. If the address is not a user mode address, at block 816, sub-routine 800 returns to routine 200. Alternatively, a user is notified of an error at termination block 810. Error notification may occur through initiation of a bug check, by logging the error, or through other techniques well-known in the art. Thus, sub-routine 800 results in an error notification when user mode addresses will be referenced as kernel mode. In an illustrative embodiment, a user can select to verify a subset of driver calls. Further, a subset of driver calls may be verified based on system settings.
With reference now to
At decision block 904, a test is conducted to determine whether the driver verification component 106 should be fully enabled on system startup. In an illustrative embodiment, a system parameter may be set to signal that the driver verification component 106 is to be fully enabled on system startup. If the driver verification component 106 is to be fully enabled on system startup, at block 906, the driver verification component 106 is fully initialized and enabled for selected drivers. In an illustrative embodiment, a user selects the driver components 104 to be verified. Further, a full initialization can include adding driver component names to the list of drivers to be verified. Still further, a full initialization can include initializing a set of verification checks, initializing verifier sub-modules, and applying verifier hook functions to verified drivers.
At block 910, a test is conducted to determine whether a user requested changes to be made to driver verification component 106 settings. Changes to driver verification component settings can include a user request to add another driver to a verification list. Further, a user can request that a set of verification checks be changed. The driver verification component 106 waits until a user requests modifications before proceeding to block 914.
If the driver verification component 106 is not fully enabled on system startup at block 904, then, a test is conducted at decision block 908 to determine whether a user requested to make changes to driver verification component 106 settings. The test at decision block 908 is similar-to the test conducted at decision block 910 described above. In an illustrative embodiment, if a user did request changes, then the driver verification component is fully initialized and enabled for selected drivers at block 912. Further, the full initialization performed at block 912 is similar to the full initialization performed at block 906. Thus, if the driver verification component 106 is not fully initialized on system startup, then the driver verification component 106 can be fully initialized after a user requests that settings be changed. At block 914, the settings of the driver verification component can be modified.
With reference now to
In an illustrative embodiment, a request to verify a driver component may be obtained after a driver component has been loaded into memory. In such a case, a subset of requested verification checks can be implemented. Whether a replacement function is hooked into a driver can be based on dependencies that can exist between other replacement functions. For example, a replacement function can be hooked if the replacement function does not depend on data from other replacement functions.
In an illustrative embodiment, the driver verification component 106 can simulate a low resource environment. For example, the driver verification component 106 can simulate low memory conditions by failing some of the memory allocation requests made by a driver component 104. A user can specify a custom probability which controls the frequency of failed resource allocation requests. Additionally, the driver verification component 106 allows a user to select one or more user programs 102 for fault injection. For example, a driver component 104 may receive requests from User Program A and User Program B. If desired, the user can configure the driver verification component 106 such that faults will only be injected when the driver component 104 is in communication with User Program A.
In an illustrative embodiment, a user can specify a boot time grace period before which time the driver verification component 106 will not perform any verification checks. For example, a user can specify that verification checks should start no sooner than 2 minutes after the system 100 boots up. Additionally, a user can choose to verify selected code paths of the driver component 104. For example, memory used by a driver component 104 can be tagged with an identification value. In an illustrative embodiment, a user can select tag values to inject with faults.
While illustrative embodiments have been illustrated and described, it will be appreciated that various changes can be made therein without departing from the spirit and scope of the invention.