1 / 57

Static Analysis and Verification of Drivers

Static Analysis and Verification of Drivers. Adam Shapiro Program Manager. Donn Terry Software Development Engineer PFD. Jakob Lichtenberg Software Development Engineer SDV . Session Outline. Static analysis tools: What they are Benefits PRE f ast for Drivers (PFD)

thadine
Download Presentation

Static Analysis and Verification of Drivers

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Static Analysis and Verification of Drivers Adam ShapiroProgram Manager Donn TerrySoftware Development Engineer PFD Jakob LichtenbergSoftware Development Engineer SDV

  2. Session Outline • Static analysis tools: • What they are • Benefits • PREfast for Drivers (PFD) • Static Driver Verifier (SDV) • Summary

  3. What Is Static Analysis? • Compile-time analysis of the source program: • Like code inspection, but performed by a tool. • Compile-time type-checking a simple example. • Looks for violations of well-defined constraints: • Procedure contracts or API contracts . • Examples of bugs found by Static Analysis: • p = NULL;…f(p); • f() requires pto be non-NULL • Completing the same IRP twice: IoCompleteRequest (IRP); ... IoCompleteRequest (IRP);

  4. Why Static Analysis? Cheap bugs! Rule of thumb • “A defect that costs $1 to fix on the programmer’s desktop costs $100 tofix once it is incorporated into a complete program and many thousands of dollarsif it is identified only after the softwarehas been deployed in the field.” “Building a Better Bug Trap” – The Economist, June 2003

  5. Tools That Make You More Effective • Push-button technology. • 100% path coverage: • At little cost (let a computer do it) • Quickly (minutes or hours versus weeks) • Defects are discovered early: • Even before device hardware is available • Before designing test cases • Often while still coding • Defect reports are easy to use: • A direct reference to the defective path (or point)in the source code reduces cost of debugging

  6. Static Analysis – How Does It Work? • The tool builds an abstract model of a driver and exhaustively inspects execution along all paths: • The abstract model is simpler: it’s reduced... • It’s so much simpler that it’s possible to have it inspected (“simulated”) exhaustively. • Over-approximation of the driver: • The control part remains the same . • All paths are preserved and treated equally . • The data state is over-approximated. • if argument x is not constrained, assume any value . • if (x>0) guards the point of interest, keep track of Boolean (x>0),but not integer value of x: Boolean is simpler than integer. • if (x > 0) { IoCompleteRequest (Irp); }

  7. Static Analysis – Not a Silver Bullet • Does not replace functional testing. • Targets violations of a given set of well-defined constraints. • Principal limitations: • It doesn’t know about every possible error. • Algorithms are based on source code abstraction and heuristics, which results in both false positives and false negatives. • It is a useful tool.

  8. Our Static Tools for Drivers • PREfast For Drivers (PFD): • Lightweight and fast (runs in minutes). • Easy to use early in development – start early: • Use on any code that compiles. • Limited to procedure scope. • Works on any code, C and C++. • Finds many local violations. • Static Driver Verifier (SDV): • Extremely deep analysis (runs in hours). • More useful in the later stages of development: • Requires complete driver. • Works over the whole driver (inter-procedural). • Limited to WDM and KMDF and to C (more planned). • Think: Compile –Time Driver Verifier. • Finds deep bugs.

  9. 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

  10. PFD: PREfast For Drivers • Fast (2 to 5 times compile time, usually). • Finds many “inadvertent” errors and some “hard” ones. • Works on code that compiles; doesn’t need to run. • Some things it can find: • Null pointer and uninitialized variable (along an unusual path) • Local leaks (memory and resource) • Mismatched parameters • Forgot to check result • Format/list mismatch • Misuse of IRQLs (some) • Various special cases that are easily missed (such as Cancel IRQL) • Proper use of callback/function pointers

  11. PFD: 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; } //...

  12. PFD: 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; } //... warning 28103: Leaking the resource stored in 'SpinLock:MyLock'.

  13. PFD: 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; } //…

  14. Precisely describe the “part” you’re building and the contract that represents. Enable automatic checking. Tells tools things they can’t infer. Effective (and checked) documentation: Programmers don’t have to guess/experiment. Code and documentation don’t drift apart. Comments are nice, but… Why Annotate?Good Engineering Practice

  15. Record and express the contract: Developers know what the contract is. Is the contract a good one? Automatic checking: that is, “cheap” bugs: The sooner a bug is found, the less expensive it is to fix. Annotated code finds many more bugs (with less noise) than un-annotated code. Code that enters test with fewer “easy” bugs makes testing far more efficient – less wasted time for finding and fixing easy bugs. Annotation Benefits

  16. PFD: Annotations – Example wchar_t * wmemset( __out_ecount(s) wchar_t *p, __in wchar_t v, __in size_ts); __in: the parameter is input to the function __out: the parameter is output from the function __out_ecount(s): the parameter is a buffer with s elements If the parameter p doesn’t contain at least s elements, PFD will yield a warning.

  17. PFD - Callback Annotations wdm.h typedef VOID DRIVER_CANCEL ( __in struct _DEVICE_OBJECT *DeviceObject, __in struct _IRP *Irp ); typedef DRIVER_CANCEL *PDRIVER_CANCEL; Driver.h DRIVER_CANCELMyCancel; Driver.c VOID MyCancel ( struct _DEVICE_OBJECT *DeviceObject, struct _IRP *Irp ) { … }

  18. If your driver uses floating point, you must be very careful to protect the hardware. It’s easy to forget that you used it. It’s very hard to find in test, typically not repeatable, and blue-screen is the preferable symptom. It can span multiple functions. Problem: Floating Point

  19. Example: Floating Point long intSqrt(long i) { return (long) sqrt((double)i); }

  20. Example: Floating Point long intSqrt(long i) { return (long) sqrt((double)i); } … if (KeSaveFloatingPointState(b)) { … intSqrt(…) … KeRestoreFloatingPointState(b); } else // deal with error … intSqrt(…) … …

  21. Example: Floating Point __drv_floatUsed long intSqrt(long i) { return (long) sqrt((double)i); } … if (KeSaveFloatingPointState(b)) { … intSqrt(…) … KeRestoreFloatingPointState(b); } else // deal with error … intSqrt(…) … …

  22. Static Driver Verifier Jakob Lichtenberg Software Development Engineer Microsoft Corporation

  23. X X Static Analysis Tools for Drivers • Two complementary technologies provided in the WDK: • PREfast for Drivers: Look inside every procedure for possible violations. • Static Driver Verifier: Look along paths, cross inter-procedural boundaries. ReadFoo ( PIRP Irp ) { PIRP p = NULL; ... if (status) { IoCompleteRequest(p); } } ReadFoo ( PIRP Irp ) { ... status = Bar (Irp); if (status) { IoCompleteRequest(Irp); } } Bar ( PIRP Irp ) { ... IoCompleteRequest(Irp); return STATUS_SUCCESS; }

  24. Static Analysis Tools for Drivers PREfast for Drivers (PFD): • Lightweight and fast (runs in minutes). • Easy to use early in development – start early. • Use on any code that compiles. • Limited to a procedure scope; each procedure analyzed independently. • Annotations improve precision. • Works on any code, C and C++. • Finds many local violations. Static Driver Verifier (SDV): • Extremely deep analysis (runs in hours). • More useful in the later stages of development. • Requires complete driver. • Works over the whole driver, along every path, crossing inter-procedural boundaries. • Annotations not necessary. • Limited to WDM or KMDF and to C. • Finds a few deep bugs.

  25. Static Driver Verifier • What Static Driver Verifier does: • Global analysis of entire driver. • Looks for violations of DDI constraints. • SDV for WDM: • 68 rules covering aspects such as IRPs, IRQL, Plug and Play, and synchronization rules. • New: SDV for KMDF: • 52 rules covering aspects such as DDI ordering, device initialization, request completion, and request cancellation. • Availability: from Windows Longhorn Server WDK. • Limitations: • Only pure C drivers. • Up to 50 K lines of code.

  26. Example I/O System Irp Driver Dispatch Routine Irp Irp IoCompleteRequest Device Driver Interface

  27. X Example I/O System Irp Driver Dispatch Routine Irp Irp IoCompleteRequest Device Driver Interface

  28. Example • Parport driver sample in Win XP SP1 DDK

  29. X • One defect found Example

  30. First Completion Double Completion

  31. Server 2003 SP1 DDK ü • Rule Passes Example

  32. X Example IO Mngr P4CompleteRequest ( Irp ) PptDispatchClose ( Irp ) IoCompleteRequest( Irp ); PptFdoClose( Irp ) P4CompleteRequestReleaseRemLoc ( Irp )

  33. library.c ü more_code.c driver.c X Concepts SDV

  34. library.c ü more_code.c driver.c X Concepts SDV Rules Verification Engine OS Model

  35. library.c ü more_code.c driver.c X Rules SDV Rules Verification Engine OS Model

  36. Rule 1 A DDI Constraint Is…A Rule

  37. Rule 2 …One More Rule…

  38. Rule 3 …And Yet Another Rule

  39. Rules • SDV comes with: • 68 WDM rules • 52 KMDF rules • Each rule captures an aspect of an interface requirements. • Rules are written in a C-like language and define: • State declarations in form of C-style variables. • Events that are associated with DDI functions.

  40. I/O System Driver Entry Point Device Driver Interface KeRelease SpinLock KeAcquire SpinLock SpinLock Rule

  41. I/O System Driver returns Driver called Unlocked Driver Entry Point Release Abort Acquire Release Locked Acquire Driver returns Device Driver Interface KeRelease SpinLock KeAcquire SpinLock SpinLock Rule state { enum {unlocked, locked} s = unlocked; }

  42. 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; }

  43. library.c ü more_code.c driver.c X Operating System Model SDV Rules Verification Engine OS Model

  44. Operating System Model I/O System • Exercises the driver: • Calls DriverEntry • Calls Dispatch functions • Calls ISRs • Models certain aspects of the operating system state: • Like the current interrupt request level (IRQL) • Models device driver interface functions: • Like the IoCallDriver DDI Driver Device Driver Interface

  45. Operating System Model I/O System void main() { int choice, status; … status = DriverEntry(…); … status = AddDevice(…); … … switch (choice) { case 0: status = DriverRead(…); break; case 1: status = DriverWrite(…); break; … case 28: status = DriverCreate(…); break; default: status = DriverClose(…); break; } } … Driver Read Write Create Close DriverEntry AddDevice … Device Driver Interface

  46. Operating System Model I/O System NTSTATUS IoCallDriver( …, PIRP Irp ) { int choice; … switch (choice) { case 0: … Irp->PendingReturned = 0; return STATUS_SUCCESS; case 1: … Irp->PendingReturned = 0; return STATUS_UNSUCCESSFUL; default: … Irp->PendingReturned = 1; return STATUS_PENDING;; } } Driver UNSUCCESSFUL SUCCESS PENDING … Device Driver Interface IoCallDriver

  47. library.c ü more_code.c driver.c X Verification Engine SDV Rules Verification Engine OS Model

  48. Verification Engine: Example I/O System • Executes: • Your driver in the context of the operating system 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. … Driver Read Write Create Close DriverEntry AddDevice UNSUCCESSFUL SUCCESS PENDING … Device Driver Interface IoCallDriver

More Related