470 likes | 821 Views
Static Analysis And Verification Of Drivers. Outline. Static Tools What they are The benefits of using them PRE f ast Static Driver Verifier. What Is Static Analysis?. Analyze what the program will do without actually executing it
E N D
Outline • Static Tools • What they are • The benefits of using them • PREfast • Static Driver Verifier
What Is Static Analysis? • Analyze what the program will do without actually executing it • Flags violations of rules and conventions needed for correct program execution • Flow analysis tool builds an abstract model, simulates execution • The abstraction allows otherwise very difficult analysis, e.g. “rough idea” of the value of a variable • The abstraction is approximate, but complete (all paths are treated equally) • An abstraction: more compact and easier to manipulate than the program itself
Why Static Analysis? • Static Analysis can reduce defects by up to a factor of six! • (Capers Jones, Software Productivity Group) • Rule of thumb: A defect that costs $1 to fix on the programmer’s desktop costs $100 to fix once it is incorporated into a complete program and many thousands of dollars if it is identified only after the software has been deployed in the field • (Building a Better Bug Trap – The Economist June 2003)
Static Analysis Can… • The business case • Reduce time to market by cutting testing time due to earlier detection of bugs • Significantly reduce review effort by automating a major portion of the process • Better chance of finding deep bugs by removing more obvious bugs • Improve code quality by directly supporting adherence to programming practices
Static Analysis Can… • The development case • Find / prevent bugs earlier (before they’re hard to fix) • Find / prevent bugs more directly / obviously • Find / prevent bugs while developing • Find / prevent “hard to test” bugs • Make you more efficient
Limitations • Any simulation / analysis is imperfect • Some false positives (noise) • Some false negatives (didn’t find what it should have) • Just because the tools say a driver is good, don’t believe it • The tools are simply saying they couldn’t find anything more • The biggest risk with using static tools is overconfidence • The second biggest risk is not using them at all
Microsoft’s Static Tools For Drivers • PREfast for Drivers (PFD) • Lightweight / fast • Easy to use early in development • Limited to function scope • Works on anything, C and C++ • Static Driver Verifier (SDV) • Extremely deep analysis • More useful in the later stages of development • Requires complete driver • Works over the whole driver • Limited to some kinds of drivers, and to C • If you have access to others, use them, but use PFD and SDV, too
Driver Tools Relationship Ease Of Use Hard Easy Reproducibility Hard A problem has been detected and Windows has been shut down to prevent Damage to your computer. DRIVER_IRQL_NOT_LESS_OR_EQUAL If this is the first time you've seen this Stop error screen, restart your computer. If this screen appears again, follow these steps: Check to make sure any new hardware or software is properly installed. If this is a new installation, ask your hardware or software Manufacturer for any Windows updates you might need. If problems continue, disable or remove any newly installed hardware or software. Disable BIOS memory options such as caching or shadowing. If you need to use Safe Mode to remove or disable components, restart your computer, press F8 to select Advanced Startup Options, and then select Safe Mode Technical information: *** STOP: 0x00000001 (0x0000000,00000002,0x00000000,0x00000000) Driver Verifier PREfast For Drivers Static Driver Verifier Depth Complex By cook
PREfast For Drivers (PFD) • Fast (2-5x compile time, usually) • Finds a lot of “stupid” errors and some “hard” ones • Works on code that compiles; doesn’t need to run • User or Kernel mode drivers, C or C++, any size • Some things it can find • Null pointer, uninitialized variable (along an unusual path) • Local leaks (memory, resource) • Mismatched parameters • Forgot to check result • Format / list mismatch • Misuse of IRQLs (some) • Various special cases that are easily missed (Cancel IRQL, e.g.) • Proper use of callback / function pointers (esp. in recent versions)
Sample: Driver Specific Resource Leak void LeakSample(BOOLEAN Option1) { NTSTATUS Status; KIRQL OldIrql; BufInfo *pBufInfo; KeAcquireSpinLock(MyLock,&OldIrql); //... if (Option1) { pBufInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(BufInfo), 'fuB_'); if (NULL==pBufInfo) { return STATUS_NO_MEMORY; } //... KeReleaseSpinLock(MyLock, OldIrql); return STATUS_SUCCESS; } //... #include <wdm.h> PKSPIN_LOCK MyLock; typedef struct { char buff[100]; } BufInfo;
Sample: Driver Specific Resource Leak void LeakSample(BOOLEAN Option1) { NTSTATUS Status; KIRQL OldIrql; BufInfo *pBufInfo; KeAcquireSpinLock(MyLock,&OldIrql); //... if (Option1) { pBufInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(BufInfo), 'fuB_'); if (NULL==pBufInfo) { return STATUS_NO_MEMORY; } //... KeReleaseSpinLock(MyLock, OldIrql); return STATUS_SUCCESS; } //... #include <wdm.h> PKSPIN_LOCK MyLock; typedef struct { char buff[100]; } BufInfo; warning 8103: Leaking the resource stored in 'SpinLock:MyLock'.
Sample: Driver Specific Resource Leak void LeakSample(BOOLEAN Option1) { NTSTATUS Status; KIRQL OldIrql; BufInfo *pBufInfo; KeAcquireSpinLock(MyLock,&OldIrql); //... if (Option1) { pBufInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(BufInfo), 'fuB_'); if (NULL==pBufInfo) { KeReleaseSpinLock(MyLock, OldIrql); return STATUS_NO_MEMORY; } //... KeReleaseSpinLock(MyLock, OldIrql); return STATUS_SUCCESS; } //... #include <wdm.h> PKSPIN_LOCK MyLock; typedef struct { char buff[100]; } BufInfo;
Filter Presets • PFD comes with a number of filters to reduce the set of things you look at. (See the “Filters” button in the viewer.) • WSPMIN: the “you really, really should fix these” set • Drivers_only: high-likelihood of being driver problems • Drivers_all: the combination of the two above • But: take a few minutes to look at all the bugs (in your sources and headers) and see if there’s anything else that scares you • If you don’t agree with the presets (either way) let us know so we can get better
PFD Limitations • The usual static tool limitations • Executable is currently 32-bit only • Designed to work on 32 bit applications, but compile 64-bit applications as 32-bit and get most of the benefit • Function-scope analysis
Hints • Watch out for “continuable asserts” • You thought the assert made it impossible, but if it’s like many drivers, there’s a way to continue from the debugger. PFD doesn’t know that. Use __declspec(noreturn) and #if _PREFAST_ • Twice around a loop • If it looks “impossible” check the order of the line numbers listed: you might be going around a loop more than once to get to the error • Read the documents for other hints. It’s really hard to explain some things in a sentence or two
Using PREfast For Drivers • There are three versions of PREfast • (New) Drivers version (2.1.xxxx) (PFD): in the WDK (the only “PREfast” there) • Older (in DDK) • (Old) Drivers version (1.5.2402): Default in the newest Server 2003 SP1 DDK. (See DDK online documents if you have older DDKs) • (Run ‘prefast version’ and look for 1.5.2402) • Non-drivers version (1.5.2400): Default in older versions of 2003 SP1 DDK. (Avoid using: not as useful to you.) • Read the “PREfast Step-by-Step” paper
Static Driver Verifier • Introduction • Example • Concepts • Rules • OS Model • Verification Engine • Summary
Introduction • Static Driver Verifier • Is a compile time static analysis tool • Operates on driver source code • Completely Automatic • What Static Driver Verifier does • Finds bugs in drivers • Verifies that the driver adheres to the WDM interface requirements
IntroductionSupported Drivers • WDM drivers • Functions drivers • Filter drivers • Bus drivers • Only pure C drivers • Up to 50 K lines of code • Support for KMDF planned post Longhorn
X IoCompleteRequest Example I/O System Irp Driver Dispatch function Irp ; Irp Device Driver Interface
X One defect found Example
First Completion Double Completion
Server 2003 SP1 DDK ü Rule Passes Example
IntroductionQuality • Comprehensive Path Coverage • Driver is exercised in a hostile environment • Verifies all possible paths in the drivers • Verifies cross function calls • Verifies driver together with supporting libraries • But there are places where SDV is imprecise • Only one driver (not the entire driver stack) • OS Model imperfect • The verification engine is not precise
IntroductionExperience • Defects • SDV finds a few serious, hard to repro defects • The defects are inherently complex • Performance • SDV may run in a few minutes • But may also need to run overnight
library.c ü more_code.c driver.c X Concepts SDV Rules Verification Engine OS Model
library.c ü more_code.c driver.c X Concepts SDV Rules Verification Engine OS Model
library.c ü more_code.c driver.c X Rules SDV Rules Verification Engine OS Model
Rules • Each rule captures an aspect of the WDM interface requirements • Rules are written in a language called SLIC • Each rule defines • State declarations in form of C style variables • Events that are associated with DDI functions • SDV comes with 64 rules • IRP Rules • IRQL Rules • PnP Rules • Synchronization Rules • Other Miscellaneous rules • Ideas to new rules are welcome!
I/O System Driver Entry Point Device Driver Interface KeRelease SpinLock KeAcquire SpinLock SpinLock Rule
I/O System Driver returns Driver called Unlocked Driver Entry Point Release Abort Acquire Release Acquire called Driver returns Locked Device Driver Interface KeRelease SpinLock KeAcquire SpinLock SpinLock Rule state { enum {unlocked, locked} s = unlocked; }
I/O System Driver Entry Point Device Driver Interface KeRelease SpinLock KeAcquire SpinLock SpinLock Rule state { enum {unlocked, locked} s = unlocked; } RunDispatchFunction.exit { if (s != unlocked) abort; } KeAcquireSpinLock.entry { if (s != unlocked) abort; else s = locked; } KeReleaseSpinLock.entry { if (s != locked) abort; else s = unlocked; }
PnpSurpriseRemove DoubleCompletion ForwardedAtBadIrql IrpProcessingComplete MarkingInterlockedQueuedIrps MarkingQueuedIrps PendedCompletedRequest NullDeviceObjectForwarded TargetRelationNeedsRef PnpIrpCompletion RequestedPowerIrp StartIoCancel StartIoRecursion LowerDriverReturn WmiComplete WmiForward MarkIrpPending IRP Rules
IrqlKeReleaseSpinLock ForwardedAtBadIrql IrqlApcLte IrqlDispatch IrqlDispatchLt IrqlExAllocatePool IrqlExPassive IrqlIoPassive1 IrqlIoPassive2 IrqlIoPassive3 IrqlIoPassive4 IrqlIoPassive5 IrqlKeDispatchLte IrqlIoBuildDeviceIoControlRequest IrqlKePassive IrqlKeRaiseLower IrqlKeSetEvent IrqlKeWaitForMutexObject IrqlKeWaitForSingleObject IrqlMmPassive IrqlObPassive IrqlProbePassive IrqlPsPassive IrqlReturn IrqlRtlPassive IrqlZwPassive PagedCode IrqlKeInsertQueueDpc IRQL Rules
IrqlKeReleaseSpinLock ForwardedAtBadIrql IrqlApcLte IrqlDispatch IrqlDispatchLt IrqlExAllocatePool IrqlExPassive IrqlIoPassive1 IrqlIoPassive2 IrqlIoPassive3 IrqlIoPassive4 IrqlIoPassive5 IrqlKeDispatchLte IrqlIoBuildDeviceIoControlRequest IrqlKePassive IrqlKeRaiseLower IrqlKeSetEvent IrqlKeWaitForMutexObject IrqlKeWaitForSingleObject IrqlMmPassive IrqlObPassive IrqlProbePassive IrqlPsPassive IrqlReturn IrqlRtlPassive IrqlZwPassive PagedCode IrqlKeInsertQueueDpc IRQL Rules IrqlKeReleaseSpinLock.slic: KeReleaseSpinLock.entry { if (irql != DISPATCH_LEVEL) abort; elseif ($2 != previous_irql) abort; }
library.c ü more_code.c driver.c X Operating System Model SDV Rules Verification Engine OS Model
Operating System ModelIntroduction I/O System • Exercises the driver • Calls DriverEntry • Calls Dispatch functions • Calls ISRs • Models certain aspects of the OS state • Like the current Interrupt Request Level • Models Device Driver Interface functions • Like the IoCreateDevice function Driver Device Driver Interface
Operating System ModelDevice Driver Interface Functions I/O System IoCreateDevice( … , OUT *DeviceObject ) { … switch (choice) { case 0: (*DeviceObject) = pValidDevice; return STATUS_SUCCESS; case 1: (*DeviceObject) = NULL; return STATUS_INSUFFICIENT_RESOURCES; case 2: (*DeviceObject) = NULL; return STATUS_OBJECT_NAME_EXISTS; default: (*DeviceObject) = NULL; return STATUS_OBJECT_NAME_COLLISION; } } Driver Device Driver Interface IoCreateDevice
library.c ü more_code.c driver.c X Verification Engine SDV Rules Verification Engine OS Model
Verification Engine • Executes • Your driver in the context of the OS Model • While keeping track of the rule state • While looking for rule violations • Checks each and every path of the driver • Implements worst case behavior • Symbolic model checker • Strategy: Throw away many irrelevant details through aggressive, but correct, abstraction
Practical Experience • It reports serious bugs indeed present in a driver • 1+ bug in average for sample drivers in Server 2003 DDK (3677) • Reasonable Noise level • 33% false positives on 30 DDK samples • SDV does not report tons of suspicious issues • Less than 1 false bug reported per driver, in average • Experiments show • High quality drivers are often clean • One driver with 15 bugs reported of which 14 were true
Static Driver VerifierSummary • SDV is a compile-time tool that finds bugs in device drivers • Finds corner cases that are hard to reproduce with Driver Verifier • Finds bugs that are deeper than PREfast for Drivers • SDV is composed of three parts • Rules • OS Model • Verification Engine • SDV can help improve the quality of your driver
Additional Resources • Email • Pfdfdbk @ microsoft.com (PREfast for Drivers) • Sdvfdbk @ microsoft.com (Static Driver Verifier) • Web Resources • Whitepapers • PREfast with Driver specific Rules on http://www.microsoft.com/whdc/devtools/tools/PREfast-drv.mspx • PREfast Step-by-Step • http://www.microsoft.com/whdc/DevTools/tools/PREfast_steps.mspx • Static Driver Verifier: Finding Bugs in Device Drivers at Compile-Time on http://www.microsoft.com/whdc/devtools/tools/SDV.mspx
© 2005 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. Microsoft makes no warranties, express or implied, in this summary.