1. Kb2685811 Download Windows 7 X64
  2. Kernel Mode Driver Framework 111 Download Free

Presentation on theme: 'I/O Request Flaw in WDF Kernel-Mode Driver'— Presentation transcript:

1 I/O Request Flaw in WDF Kernel-Mode Driver
陳俐如 (greener)

Kernel Mode Driver Framework 111 Download

2 The flow of an I/O Request Through the System

Jan 15, 2016 - SCCM OSD issue: Kernel- Mode Driver Framework. Have you seen this error when trying to deploy a new machine model?“Windows could not.

3 Introduction KMDF driver refers to a kernel-mode WDF driver
Framework refers to the kernel-mode driver framework itselfI/O flawHandel requestsFrom application to driverFrom driver to application

4 User-Mode Application I/O Request
Common I/O request issued by applicationsCreate requestsOpen a file object that uniquely represents the new open instance by the process (not the thread)Close requestsReturn a file handle to the OS when application no longer needs to use itRead and write requestsRetrieve data from or provide data to a deviceOperation through data buffer and buffer length in bytesDevice control requestsAllow application to perform operation on deviceRefer to as I/O control requests, device controls, I/O controls, or simply IOCTLsIdentified by the defined control codeSome operation through data bufferWhen a create operation is successful, the system returns a handle to the newly created file object to the caller. Like all handles, this file object handle is specific to the process (not the thread) that created it.In some circumstances, the output buffer provided on a device control request can also be used for input.

5 User-Mode Application I/O Request (cont’d)
Synchronous and asynchronous application requestsDifference between these 2 requestsSynchronous – control returns to the thread from the I/O request call until all processing for that I/O request is completeAsynchronous – control can be returned immediately to the requesting thread without waiting for the results of the unnecessary I/O requestAsynchronous requests are completed asynchronously or synchronouslySynchronous requests are ALWAYS completed synchronouslyRead, write, and device control requests can be issued either synchronously or asynchronously by an application. This choice is typically made as part of the CreateFile call, based on whether a pointer to an OVERLAPPED structure is supplied.Even though an application requests asynchronous processing for a particular open instance of a device, any given I/O request sent on that open instance might be completed either asynchronously or synchronously.

6 I/O Request Path from Application to Driver
Call to the system service dispatcherCalls the corresponding I/O processing function of the Windows I/O ManagerThe I/O Manager builds an I/O request packet (IRP) and sends it to the frameworkThe framework forwards the request to the next-lower driver or the KMDF driverIf KMDF driver receives the request, forwards it to the next-lower driverForwards the request to the next-lower driver as needed to satisfy the request1. When an application issues an I/O request, Windows issues a system service call to the system service dispatcher.2. The system service dispatcher calls the corresponding I/O processing function of the Windows I/O Manager.3. The I/O Manager builds an I/O request packet (IRP) that describes the I/O request issued by the application and sends it to the framework (the KMDF library, Wdfdynam.sys). The framework sorts incoming requests by major function code and, in the case of a read, write, or device control request, sends it to the framework's I/O package for processing. The I/O package validates the request parameters and processes the request according to its type and the driver's configuration of its WDFQUEUE(s).4. If the KMDF driver is a filter driver and has configured its WDFQUEUE(s) to forward requests of this type to the next-lower driver on the underlying driver stack, the framework forwards the request to the next-lower driver. Otherwise, it forwards the request to the KMDF driver.5. If the KMDF driver receives the request, it processes the request and, if necessary, forwards it to the next-lower driver on the underlying stack.6. That driver processes the request and, in turn, forwards the request to the next-lower driver and so on down the driver stack, as needed to satisfy the request.

7 I/O Request Path from Application to Driver (cont’d)
I/O Request Path from user-mode Application to the FrameworkWindows issues a system service call for an application I/O requestThe system service dispatcher calls the I/O managerThe I/O manager builds an IRP and sends it to the frameworkValidating request parameterBuilding the IRPEach I/O stack location contains storage for I/O request parameters that are likely to change from driver to driver as the request is processedThe IRP major function code - identifies the type of I/O operation requestedA description of the user’s data buffer in different waysValidating request parameters. In the process of building the IRP, the I/O Manager validates the parameters that were passed from the user application. Although the checks performed vary according to the type of I/O request, the I/O Manager:* Always checks to ensure that the handle used is valid.* Always checks that the user has appropriate access to the device (that is, the user has read access if a read request is being issued, or write access for a write request).* If the request uses buffers, checks to ensure that the user-supplied data buffer pointers and data buffer lengths are valid.Building the IRP. An IRP has both a fixed-size part and a variable-sized part:* The fixed-sized part of the IRP contains information about the I/O request that is unlikely to change based on the driver processing the request.* The variable-size part of the IRP is referred to as the I/O stack and comprises a specific number of I/O stack locations.When building an IRP to describe a given I/O request, the I/O Manager:* Allocates an IRP of the appropriate size (that is, one with enough I/O stack locations for all drivers in the driver stack).* Initializes the fixed-size part of the IRP.* Initializes the first I/O stack location in the I/O stack. This first I/O stack location contains the request parameters that will be used by the first driver to receive the I/O request. Starting with the first driver, each driver in the stack is responsible for initializing the I/O stack location for the next-lower driver before forwarding the IRP to that driver.

8 I/O Request Path from Application to Driver (cont’d)
Sending the IRP to the frameworkThe I/O Manager passes the IRP to the driver for the target device by calling the kernel-mode function IoCallDriverIf the driver is a KMDF driver, the framework intercepts the requestI/O Request Path from Framework to DriverThe framework routes the request to the appropriate packageThe I/O package checks the I/O request typeThe I/O package further validates request parametersThe framework process the requestThe framework is a kernel-mode DLL that can be shared among multiple KMDF drivers. The framework handles a considerable amount of processing on behalf of KMDF drivers. When a new I/O request for a driver arrives at the framework, it processes the request through its request pipeline.IO Request Path from Framework to Driver:The arriving IRP is first sorted by the framework according to its major function code. IRP_MJ_SYSTEM_CONTROL requests are sent to the framework’s WMI package. IRPs with major function codes IRP_MJ_PNP and IRP_MJ_POWER are sent to the framework's Plug and Play/power package. Each framework package processes the requests it receives according to its particular rules.When the framework's I/O package receives a new request, it first checks to see if the I/O request type is one that is both handled by the driver and supported by the framework. If the arriving I/O request is not supported by the framework or the driver, the framework completes the IRP that describes the arriving request with STATUS_INVALID_DEVICE_REQUEST.If the arriving I/O request is supported by the framework or the driver, the I/O package next performs a series of type-specific checks on the request’s parameters. These can include checks for unusual (yet architecturally valid) buffer descriptions or otherwise invalid buffer descriptions, and are performed in addition to the validations already performed by the I/O Manager.If the arriving request passes the I/O package’s validation checks, the framework processes the request according to its request type and the driver’s configuration of its WDFQUEUE(s) and performs one of the following actions:Handles the request on behalf of the driver.Forwards the requests to the driver for the next-lower device in the device stack.Creates a WDFREQUEST object that represents the arriving request and passes it to the KMDF driver.

9 KMDF Driver Processing of I/O Requests
How a driver processes an arriving WDFREQUESTProcessing a Request InternallyThe work required to satisfy a WDFREQUEST might involve processing that takes place entirely within the driver that receives the requestProcessing a Request by Sending It to Another DriverProcessing before sending the requestInitializing the next I/O stack location in the requestCreating and sending new requestsSending requests synchronously or asynchronouslyEstablishing an I/O completion routine callbackRequests Marked Pending During ProcessingMark pending(“pended”) for later processingA KMDF driver might be able to process a request to its completion internally, without sending the request to any other drivers in the system for processing

10 I/O Completion Path from Driver to Application
Driver Completion of a RequestI/O Completion Path from Framework to I/O ManagerI/O Manager Completion of a RequestThe lowest driver in the stack (USBPORT) does whatever is necessary to satisfy the request and calls IoCompleteRequest to signal that the request has been completed. The I/O Manager calls the I/O completion routine of the next-higher driver in the stack (USBHUB).The next-higher driver (USBHUB) performs any completion processing on the request and returns from its I/O completion routine without reclaiming the IRP that represents the I/O request being completed. The next-higher driver in the stack is a KMDF driver (UsbDev.sys). Instead of calling the KMDF driver's completion routine directly, the I/O Manager calls the framework (the KMDF Library, Wdfdynam.sys). The framework reclaims the IRP, matches it to the WDFREQUEST that was used to describe this I/O request, and calls the KMDF driver's I/O completion routine callback. The KMDF driver performs any completion processing on the request and calls WdfRequestComplete to signal that it is finished.The framework calls IoCompleteRequest, which returns control of the request to the I/O Manager.The I/O Manager retrieves I/O status from the request, translates the status to a Windows error code, returns completion information and, if necessary, copies data back to the requesting application's data buffer. It then returns control to the system service dispatcher.The system service dispatcher returns control to the requesting application.Driver Completion of a Request, and 3 data items are returned to the thread: I/O status, completion information, and requested data. KMDF drivers specify status and completion information values when they complete a WDFREQUEST by calling a function such as WdfRequestCompleteWithInformation.I/O Completion Path from Framework to I/O Manager: The framework uses the I/O status and completion information in the request to fill in the corresponding fields in the IRP. Next, the framework destroys the WDFREQUEST itself, returning any context storage associated with the WDFREQUEST.I/O Manager Completion of a Request in 2 stages:Stage 1: Completion processing that might take place in any process and thread context (sometimes called an 'arbitrary' process and thread context)Completion processing in Windows drivers . Factors: (1) I/O completion routines are optional. (2) A driver can reclaim ownership of a request in its I/O completion routine.Completion processing in the framework and KMDF drivers - The framework in turn always reclaims ownership of the request from the I/O Manager, and calls the I/O completion routine callback registered by the KMDF driver for the request.After all completion routines are finished by drivers - The only work remaining for the I/O Manager is that which must be done in the context of the requesting thread: (1) If the I/O Manager is already running in the context of the requesting thread it proceeds directly to I/O completion processing in the requestor's context (2) If the I/O Manager is in a context other than that of the requesting thread, the I/O Manager queues a special kernel APC, referred to as “the special kernel APC for I/O completion.” The effect of this APC is to return the I/O Manager to executing in the context of the requesting thread and to start I/O completion processing in the requestor's context.Stage 2: Completion processing that must take place in the context of the thread that issued the I/O request.At this point, the only work remaining for the I/O Manager is to return the data items discussed previously (I/O status, completion information, and possibly request data) to the requesting thread, and to wake the thread if the thread is waiting as a result of requesting synchronous processing of an I/O request that was pended: (1) the I/O Manager retrieves the I/O status from the request being completed, and typically translates that status from a native kernel mode NTSTATUS value to a Windows error code. (2) the I/O Manager returns the completion information. (3) If the driver chose intermediate buffering of data for the completing request, the I/O Manager copies data to satisfy the request back to the requestor’s data buffer . (4) After returning the data, the I/O Manager frees any data structures it used to manage this I/O request, including the IRP. (5) At this point, if the thread had been waiting as a result of requesting synchronous processing of an I/O request that had pended, the I/O Manager wakes the thread. (6) control is returned from the I/O Manager to the application running in user mode, via the system service dispatcher.

11 Flow of an I/O Request within a KMDF Driver
Factors that influence the path of an I/O request within a KMDF driverThe type of device being supportedThe driver’s WDFQUEUE configurationThe driver’s synchronization scope configurationThe overall state of the WDFDEVICE and WDFQUEUE

12 Framework Receives a Request and Inserts It on a WDF QUEUE - WDFQUEUE Insertion Logic
1. If the device has been defined as a filter device objectIf WDFQUEUE conf DOESN’T specify the I/O event processing callback for the arriving I/O function, or if no WDFQUEUE been created for the devicethe framework forwards the request to the device’s local I/O target. Complete.Else step 22. Determine to place the arriving WDFREQUEST into the correct WDFQUEUEIf the driver has specifically configured forwarding for this I/O request , the framework selects the indicated queue.If the driver has not configured forwarding, or if the request type does not match any of the permitted forwarding request types, the framework selects the default WDFQUEUE for the target device.

13 Framework Receives a Request and Inserts It on a WDF QUEUE - WDFQUEUE Insertion Logic (cont’d)
3. Checks the dispatch type for the chosen WDFQUEUEIf the dispatch type for the chosen WDFQUEUE is WdfIoQueueDispatchManual, the selected queue is chosen.If the dispatch type for the chosen WDFQUEUE is other than WdfIoQueueDispatchManual, check if an I/O event processing callback that matches the I/O function of the arriving request been provided for the selected queueIf true, that callback is selectedIf false, determine if the default I/O event processing callback has been specified for the selected queueIf true, callback is selectedIf false, completes the WDFREQUEST with STATUS_INVALID_DEVICE_REQUEST. Complete.

14 Framework Receives a Request and Inserts It on a WDF QUEUE - WDFQUEUE Insertion Logic (cont’d)
4. Both a WDFQUEUE and an I/O event processing callback have been chosen. Checks whether the queue is currently accepting requestsIf false, complete the arriving WDFREQUEST with STATUS_INVALID_DEVICE_STATE. Processing for the request is complete. A queue can stop accepting requests.If true, the WDFREQUEST is inserted at the end of the WDFQUEUE

15 Framework Receives a Request and Inserts It on a WDF QUEUE - Driver Queue Implementation
Example 1: WDFDIO driver queue implementationCreates a single (default) Q for its deviceOnly one I/O event processing callback is specified for the Q to handle device control requestsNot configure any other Qs or provide any additional I/O event processing callbacksThe dispatch type of the queue is set to WdfIoQueueDispatchSequential on the call to WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUEQueue structure:WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&ioCallbacks, WdfIoQueueDispatchSequential);ioCallbacks.EvtIoDeviceControl = DioEvtDeviceControl;status = WdfIoQueueCreate(device, &ioCallbacks, WDF_NO_OBJECT_ATTRIBUTES, NULL); // optional pointer for queue handleAs a result of this configuration, the framework’s I/O package will insert only device control requests on the driver's queue, and will complete read, write and internal device control requests with no processing required by the driver.

16 Framework Receives a Request and Inserts It on a WDF QUEUE - Driver Queue Implementation (cont’d)
OSRUSBFX2 driver queue implementationCreate 2 QsA default queue to handling incoming device control requestsAn additional queue to handle read requests.Also creates a 3rd Q to handle write requests

17 Framework Invokes the Driver’s I/O Event Processing Callback
Dispatch Type of the QueueDispatch TypesWdfIoQueueDispatchParallelWdfIoQueueDispatchSequentialWdfIoQueueDispatchManualImpact of Dispatch Type on Driver DesignSynchronization Scope for WDFDEVICEs and WDFQUEUEsSpecifying Synchronization ScopeAs an object attribute of the WDFDEVICE objectThe most useful is WdfSynchronizationScopeDeviceHow Synchronization Scope WorksDetermines whether to invoke the I/O event processing callback depends on the dispatch type of the Q, the Q’s synchronization scope, the number of requests currently in progress, and the state of the Q.A queue’s dispatch type is defined when the queue is created, in the call to the WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE macro. The dispatch type indicates whether the framework will attempt to invoke the driver’s I/O event processing callback when a new request is placed on the queue. The dispatch type also defines whether multiple requests can be outstanding from the same queue simultaneously.WdfIoQueueDispatchParallel. When a new request is inserted into a WDFQUEUE configured for parallel dispatching, the framework invokes the I/O event processing callback identified for that request through the processWdfIoQueueDispatchSequential. When a new request is added to a queue configured for sequential dispatching, the framework invokes the I/O event processing callback that has been identified for that request only if no requests from the queue are already in progress.WdfIoQueueDispatchManual. Inserting a request into a WDFQUEUE configured for manual dispatching never results in the framework calling a type-specific or default I/O event processing callback. However, WDFQUEUEs configured for manual dispatching can optionally have an associated I/O event processing callback for a queue state change. This callback will be invoked whenever a WDFREQUEST is added to otherwise empty queue configured for manual dispatching.Impact of Dispatch Type on Driver Design. The number of queues configured by the driver and the dispatch type of each has a major impact on the driver’s overall design, including its flow of control.Specifying WdfSynchronizationScopeDevice causes the framework to allow only one thread to execute code within the driver’s I/O event processing callbacks and (by default) DPCs at a time for a given device, thus serializing the execution of these routines. This effect is achieved by guarding these routines with a spin lock that the framework acquires prior to the routines being invoked.How Synchronization Scope WorksTo understand how synchronization scope works and how it differs from the serialization that can result from serial dispatching, consider a driver for a modern, high-speed disk interface such as an intelligent SCSI adapter. Such a device might have many hundreds of requests active simultaneously. Therefore, a KMDF driver that supports this device should configure its queues to allow multiple requests to be in progress from the queue simultaneously.

18 Framework Invokes the Driver’s I/O Event Processing Callback (cont’d)
Queue StateManaged by KMDF driver and using the following flags (state: bitmasks)WdfIoQueueAcceptRequestsWdfIoQueueDispatchRequestsWdfIoQueueNoRequestsWdfioQueueDriverNoRequestsWdfIoQueuePnPHeldIs the Callback Called?1. If the queue’s dispatch type is WdfIoQueueDispatchManual and a queue state change callback has been registered for the queueIf true, and if the number of requests on the queue after inserting the arriving request is 1, the queue state change I/O event processing callback is invoked. Complete.If false, no callback is invoked. Complete.When a queue is accepting requests, WDFREQUESTs that arrive for that queue are inserted into the queue. When a queue is not accepting requests, WDFREQUESTs that arrive for the queue are completed by the framework with STATUS_INVALID_DEVICE_STATE. When a queue is dispatching requests, the associated I/O event processing callback is invoked when a WDFREQUEST is inserted on the queue.If a queue is power managed, its state is managed by the framework according to the Plug and Play and power state of the queue’s WDFDEVICE.

19 4. Examines the number of requests in progress from the queue
2. If the queue’s dispatch type is either WdfIoQueueDispatchParallel or WdfIoQueueDispatchSequential, the framework checks the state of the queue if allowing it to accept requestsIf false, the arriving request is completed with STATUS_INVALID_DEVICE_STATE. Complete.If true, continue with step 33. If the queue’s serialization scope is not WdfSynchronizationScopeNone, a lock is identifiedThe process continues with Step 44. Examines the number of requests in progress from the queueIf no requests are presently in progress from the queue, the callback is invoked. Complete.If the queue’s dispatch type is parallel, the callback is invoked. Complete.

20 Driver’s I/O Event Processing Callback Executes
Validating the Arriving RequestProcessing the Arriving RequestSatisfying the Request within the I/O Event Processing CallbackInitiating a Request on the DeviceSending a Request to Another Driver for ProcessingSynchronouslyAsynchronously, Specifying a Completion RoutineAsynchronously, Without Specifying a Completion RoutineValidating the Arriving Request. Although both the I/O Manager and the framework have already examined the arriving request for validity, the driver still must evaluate the correctness of the request in terms of its device and the function being requested.Satisfying the Request within the I/O Event Processing Callback. If the driver can completely satisfy the request within its I/O event processing callback (without first having to send the request to another driver for processing) it does so and completes the request, returning the request data, I/O status and completion information.Initiating a Request on the Device. If the driver (such as a driver for a PCI bus device) directly controls its hardware through a set of ports, registers, or shared memory locations, the driver might need to initiate a request on the device and then wait for the device to indicate that the request is complete.

21 I/O Request Completion Examples
WDFDIO Synchronous Request CompletionThe function called, the driver executes a specific block of code based upon the control code indicated in the device control request.The local variable “status” is initialized to STATUS_SUCCESS and the local variable “len” is initialized to zero. To hold the I/O status and completion information data, respectively, that are returned to the requestor on completion of the arriving WDFREQUEST.After the driver switches based on the control code, the driver validates the length (24 or 16 bits) of the input buffer supplied by the requestor.If the supplied buffer length is not valid, the driver sets the local variable “status” to an appropriate status code and breaks out of the switch statement, dropping to the bottom of the function where the request is completed.If the buffer length is valid, the driver gets a pointer to data supplied in the requestor’s input buffer from the framework, and writes two or three data bytes to the DIO device, one byte at a time, keeping track of the number of bytes written as it goes.Control next falls to the bottom of the function, where the request is completedCompletion Information is filled into the request by calling WdfRequestSetInformationThe request is completed with a specified I/O status by calling WdfRequestComplete.

22 I/O Request Completion Examples (cont’d)
WDFDIO Initiating a Request and Awaiting an InterruptWhen this device control request is received, the driver must have already received and processed a request to enable interrupts when the state of bit 0 in the device’s PortA changes.Only one IOCTL_WDFDIO_READ_PORTA_AFTER_INT type request can be in progress at a time in the driver. When the driver validates the request, it validates the size of the supplied buffer, the state of the device, and the state of the driver

23 I/O Request Completion Examples (cont’d)
OSRUSBFX2 Sending a Request and Awaiting CompletionThe validation comprises checking to ensure that the length of the requested transfer is not greater than that allowed by the device.The driver does not check to see if the buffer length is zero, since the framework completes them with STATUS_SUCCESS without passing them to the driver.The driver formats a USB request for its bulk read pipe, using the data buffer specified in the read WDFREQUEST.The driver then registers an I/O completion routine callback with the request and sends the IRP to the USBHUB driver. Because the third parameter to WdfRequestSend (RequestOptions) is specified as NULL, the default mode of operation of this function is used, which sends the request asynchronously to the driver for the target device.Assuming the call to WdfRequestSend succeeds, the driver returns to the framework to await the callback to its I/O completion routine, which indicates that the request it sent is complete.

24 I/O Request Completion Examples (cont’d)
OSRUSBFX2 Sending an Alternate Request SynchronouslyFirst, retrieve the output buffer pointer from the arriving request using the KMDF function WdfRequestRetrieveOutputBuffer.In addition to returning a pointer to a buffer in kernel virtual address space into which the driver should return the data for the requestor, it also validates the buffer length.With the buffer length validated, and a pointer to the buffer into which to return the data retrieved, the driver then calls the driver-defined function GetSwitchState.The GetSwitchState function is passed the buffer pointer and a pointer to the WDFDEVICE context, and returns a status that is used to complete the request. The data is placed in the indicated buffer.

25 Driver’s I/O Completion Routine Executes
When a request is sent to another driver asynchronously, the driver sending the request has the option of registering an I/O completion routine callback prior to sending the request.When a KMDF driver’s I/O completion routine executes, the driver regains ownership of the WDFREQUEST.I/O Completion Routine ExampleWhen this callback is invoked, the driver regains ownership of the WDFREQUEST. To cause the request to be completed back to the application program that issued it. This causes the framework to complete the WDFREQUEST and to call IoCompleteRequest on the IRP associated with the WDFREQUEST.If the driver did not complete the request, the request’s I/O status and completion information would not be returned to the requestor.

26 Driver’s Interrupt Event Callback Executes
Running at device IRQL has several consequencesOther system processes are blocked when the interrupt event callback executes, due to its high IRQL. Therefore, the amount of processing performed in this routine should be kept to a minimumVery few KMDF or system functions can be called from the driver’s interrupt event callback, again due to its high IRQLBasic actions in its interrupt event callbackEnsures that its device is interrupting.Saves the reason for the interrupt and/or data from the interruptAcknowledges the interruptIf additional work is required, requests a callback to its DpcForIsrInterrupt Event Callback ExampleFor KMDF drivers, the ISR call passes through a thin layer in the framework, which in turn calls the driver’s interrupt event callback. This callback executes at the device hardware IRQL.

Kb2685811 Download Windows 7 X64

27 Driver’s DpcForlsr Callback Executes
Typically used to continue or complete the I/O processing that was started within the device’s interrupt event callback.complete the requests that are newly satisfied as a result of the device’s interruptcontinue the processing of any requests that are partially but not yet fully complete as a result of the device’s interruptcompleting a request can influence the flow of control in a driver, especially if the driver has configured the queue with a WdfIoQueueDispatchSequential dispatch type

Kernel Mode Driver Framework 111 Download Free

28 SummaryAn I/O request from user mode takes as it is processed by Windows.The overall flow of an I/O request through the system It also shows where the kernel-mode driver framework (KMDF) fits within the process, and the type of work that the framework performs.A KMDF driver takes to process a WDFREQUEST. These steps are defined by the device type, driver design, WDFQUEUE and dispatching configuration and the device’s synchronization scope.Due to the various processing and synchronization options, a well-designed KMDF driver will typically require few, if any, manually acquired locks to properly serialize access to its shared data structures.