scalable contract checking for systems software using smt solvers

41
Scalable Contract Checking for Systems Software using SMT solvers Shaz Qadeer RiSE, Microsoft Research Joint work with Jeremy Condit and Shuvendu Lahiri http://research.microsoft.com/en-us/ projects/havoc/

Upload: alaqua

Post on 05-Jan-2016

34 views

Category:

Documents


0 download

DESCRIPTION

Scalable Contract Checking for Systems Software using SMT solvers. Shaz Qadeer RiSE , Microsoft Research Joint work with Jeremy Condit and Shuvendu Lahiri. http://research.microsoft.com/en-us/projects/havoc/. Context: Scalable module verification. Harness. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Scalable Contract Checking for Systems Software  using SMT solvers

Scalable Contract Checking for Systems Software

using SMT solvers

Shaz QadeerRiSE, Microsoft Research

Joint work with Jeremy Condit and Shuvendu Lahiri

http://research.microsoft.com/en-us/projects/havoc/

Page 2: Scalable Contract Checking for Systems Software  using SMT solvers

Context: Scalable module verification

Target: OS components (kernel, drivers, file-systems)– ~100KLOC of lines of codes with

>1000 of procedures

Module– A set of public/entry procedures – A set of private/internal

procedures

Specs– Interface specification

• Specs for public methods• Specs for external modules

– Property assertion

Initialize(..);

while(*) {choice= nondet();If (choice == 1){

[assume pre_1] call Public_1(…);

} else if (choice == 2){[assume pre_2]call Public_2(…);

} …}Cleanup(…);

Harness

Page 3: Scalable Contract Checking for Systems Software  using SMT solvers

Desirable goals

• Find bugs – Violations of property assertions– Low false alarms

• Use contracts – Modular checking for scalability– Readable contracts are formal documentation

• Reduce testing cost by providing high assurance in the verifier– Formal documentation of assumptions– Simple meta-theory for proofs

Page 4: Scalable Contract Checking for Systems Software  using SMT solvers

Existing methods on these examples

Large difference between theory and practice

Imprecise– Modeling of lists/arrays

Unsound– Modeling of lists/arrays– Aliasing, pointer arithmetic– Restricted harness

Complex “proof” calculus– Combination of analyses

Initialize(..);

while(*) {choice= nondet();If (choice == 1){

[assume pre_1] call Public_1(…);

} else if (choice == 2){[assume pre_2]call Public_2(…);

} …}Cleanup(…);

Harness

Page 5: Scalable Contract Checking for Systems Software  using SMT solvers

Full functional correctness is not a goal

Neither is minimizing the trusted computing base

Page 6: Scalable Contract Checking for Systems Software  using SMT solvers

Proof method: Floyd-Hoare Triple

• Floyd-Hoare triple {P} S {Q}

P, Q : predicates/propertyS : a program

• From a state satisfying P, if S executes, – No assertion in S fails, and – Terminating executions end in a state satisfying Q

Page 7: Scalable Contract Checking for Systems Software  using SMT solvers

Select(f1,b) = 5 f2 = Store(f1,a,5) Select(f2,a) + Select(f2,b) = 10is valid

{ b.f = 5 } a.f = 5 { a.f + b.f = 10 }is valid

theory of equality: =theory of arithmetic: 5, 10, +theory of arrays: Select, Store

iff

Program verification Formula

• [Nelson & Oppen ’79]

Page 8: Scalable Contract Checking for Systems Software  using SMT solvers

Satisfiability-Modulo-Theory (SMT)

• Boolean satisfiability solving + theory reasoning• Ground theories

– Equality, arithmetic, Select/Store• NP-complete logics• Powerful methods to combine decision

procedures for theories– [Nelson & Oppen ’79]

• Phenomenal progress in the past few years– Yices, Z3, Mathsat, ….

Page 9: Scalable Contract Checking for Systems Software  using SMT solvers

Simple type-state property

• Allocation type-state of DEV_OBJ– Device Objects (DEV_OBJ)

allocated and freed

• Property to check for a module– IoDeleteDevice() only called

on elements in MyDevObj

~MyDevObj

MyDevObj

IoCreateDevice() IoDeleteDevice()

Page 10: Scalable Contract Checking for Systems Software  using SMT solvers

Simple property simple invariants

typedef struct _DEV_OBJ{DEV_EXT *DevExt;

…} DEV_OBJ;

typedef struct _DEV_EXT{DEV_OBJ *Self;

…} DEV_EXT;

requires (do MyDevObj)NT_STATUS PnP(DEV_OBJ do, IRP *pirp){

PDEV_EXT data = do->DevExt; ….

switch(pirp->MajorFn){case IRP_MN_REMOVE_DEVICE: IoDeleteDevice(data->Self);

…}

}

DevExt

Self

do

DEV_OBJ

DEV_EXT

x MyDevObj. x->DevExt->Self = x

Page 11: Scalable Contract Checking for Systems Software  using SMT solvers

Simple property simple invariants

NT_STATUS Unload(…){ ….

iter = hd->First; while(iter != null) {

RemoveEntryList(iter);iter = iter->Next;IoDeleteDevice(iter->Self);

}….

}

First

Next

Self

DevExt

hd

x Btwn(Next, hd->First,NULL). x DevExt

x DevExt. x->Self->DevExt = x

DEV_OBJ

DEV_EXT

x DevExt. x->Self MyDevObj

DEV_OBJ

Next

Self

DevExt

DEV_EXT

Page 12: Scalable Contract Checking for Systems Software  using SMT solvers

Limitations of SMT solvers

• No support for precise reasoning with reachability predicate– Incompleteness in Floyd-Hoare proofs for straight line

code• Brittle support for quantifiers

– Complexity: NP-complete (ground) undecidable– Leads to unpredictable behavior of verifiers

• Proof times, proof success rate

Page 13: Scalable Contract Checking for Systems Software  using SMT solvers

Limitations of SMT solvers

• Answer the query {P} S {Q} for loop-free and call-free programs

• To handle loops and procedures, contracts are needed– Loop invariants– Pre/post-conditions

• Infeasible to manually supply internal contracts for large modules

Page 14: Scalable Contract Checking for Systems Software  using SMT solvers

Contributions

• Efficient decision procedure for verifying list-based programs

• Verifying and exploiting C type annotations

• Annotation inference for large modules

Page 15: Scalable Contract Checking for Systems Software  using SMT solvers

next

f

g

next

f

g

next

f

g

yx

Btwn(next,x,y)

Reachability predicate: Btwnf

Page 16: Scalable Contract Checking for Systems Software  using SMT solvers

• Express properties of collectionsx Btwn(next, next(hd), hd). state(x) = LOCKED //cyclic

• Arithmetic reasoning on data (e.g. sortedness)x Btwn(next, hd, null) \ {null}. y Btwn(next, x, null) \ {null}. d(x) d(y)

Expressive logic

Page 17: Scalable Contract Checking for Systems Software  using SMT solvers

Efficient decision procedure

• Decides the validity of {P} S {Q} – Worst-case exponential time but works well in

practice• Decision problem is NP-complete

– Cannot expect any better with propositional logic– Retains the complexity of current SMT logics

• Implemented in the Z3 SMT solver– Leverages powerful ground-theory reasoning

(arithmetic, arrays, uninterpreted functions…)

Page 18: Scalable Contract Checking for Systems Software  using SMT solvers

Contributions

• Efficient decision procedure for verifying list-based programs

• Verifying and exploiting C type annotations

• Annotation inference for large modules

Page 19: Scalable Contract Checking for Systems Software  using SMT solvers

C languageC types

– Scalars (int, long, char, short)– Pointers (int*, struct T*, ..)– Nested structs and unions – Array (struct T a[10];) – Function pointers– Void *

Difficult to establish type safety in presence of pointer arithmetic, casts– Type Safety (spatial) memory safety– Important default property to check

Lack of types hurts property checking– Difficult to disambiguate heap pointers– Difficult to write concise type invariants

Page 20: Scalable Contract Checking for Systems Software  using SMT solvers

IRP IRP

Flink

Blink

ListEntry

Flink

Blink

ListEntry

Example: Type Checking

p

q = CONTAINING_RECORD(p, IRP, ListEntry) = (IRP*)((char*)p - &((IRP*)0->ListEntry))

Type Checker: Does variable q have type IRP*?

q

Page 21: Scalable Contract Checking for Systems Software  using SMT solvers

Property Checker: Is r->Data1 unchanged?

...q->Data2 = 42;

IRP IRP

Flink

Blink

ListEntry

Example: Property Checkingq

Data2

Data1

Flink

Blink

ListEntry

Data2

Data1

r

Page 22: Scalable Contract Checking for Systems Software  using SMT solvers

Example: Property Checking

Flink

Blink

ListEntry

Data2

Data1

Flink

Blink

ListEntry

Data2

Data2 / Data1

For all we know,Data1 and Data2could be aliased!

q

r

Page 23: Scalable Contract Checking for Systems Software  using SMT solvers

Our Approach

• Implement a type checker in HAVOC– Provide formal semantics for C and its types

• Use types to improve the property checker– Provide Java-style field disambiguation

• Fully automated using Z3 SMT solver

Page 24: Scalable Contract Checking for Systems Software  using SMT solvers

Formalizing Type Safety

A C program is type safe if the run-time value of every variable and heap location

corresponds to its compile-time type.

Mem : addr -> value Type : addr -> type HasType : value x type -> bool

for all a in addr, HasType(Mem(a), Type(a))

Page 25: Scalable Contract Checking for Systems Software  using SMT solvers

Example

requires( HasType(ENCL(p), record*) && ENCL(p) != NULL)void init_record(list *p) { record *r = CONTAINING_RECORD(p, record, node); r->data2 = 42;}requires( forall(q, Btwn(next, p, NULL), q != NULL ==>

HasType(ENCL(q), record*) && ENCL(q) != NULL))void init_all_records(list *p) { while (p != NULL) { init_record(p); p = p->next; }}

#define ENCL(x) CONTAINING_RECORD(x, record, node)

Page 26: Scalable Contract Checking for Systems Software  using SMT solvers

Decision Procedure

• Translation results in verification conditions that refer to Mem, Type, and HasType

• Can be encoded into an NP-complete logic– No worse than SAT solving– Provide decision procedure using an SMT solver

Page 27: Scalable Contract Checking for Systems Software  using SMT solvers

Experiments

• Implementation supports full C language– Supports polymorphism– Supports user-defined, dependent types

• Fancier type invariants => slower checking– Pay only for what you use!

• Annotated and checked four Windows drivers– Sample drivers provided with Windows DDK– About 2.3 KLOC total, with 225 annotations– Checking time: ~1 minute each

Page 28: Scalable Contract Checking for Systems Software  using SMT solvers

Contributions

• Efficient decision procedure for verifying list-based programs

• Verifying and exploiting C type annotations

• Annotation inference for large modules

Page 29: Scalable Contract Checking for Systems Software  using SMT solvers

Simple property simple invariantsNT_STATUS Unload(…){ ….

iter = hd->First; while(iter != null) {

RemoveEntryList(iter);iter = iter->Next;IoDeleteDevice(iter->Self);

}….

}

First

Next

Self

DevExt

hd

x Btwn(Next,hd->First,NULL). x DevExt

x DevExt. x->Self->DevExt = x

DEV_OBJ

DEV_EXT

x DevExt. x->Self MyDevObj

DEV_OBJ

Next

Self

DevExt

DEV_EXT

Page 30: Scalable Contract Checking for Systems Software  using SMT solvers

Need to simplify the problem

Module– A set of public/entry

procedures – A set of private/internal

procedures

Specs– Interface specification– Property assertion

Require the user to provide a module invariant

Initialize(..);[loop_inv moduleInv]while(*) {

choice= nondet();If (choice == 1){

[assume pre_1] call Public_1(…);

} else if (choice == 2){[assume pre_2]call Public_2(…);

} …}Cleanup(…);

Harness

Page 31: Scalable Contract Checking for Systems Software  using SMT solvers

Module invariants

• Module invariants– Invariant about all objects of a given type– Invariants on global variables

• Preserved by the public functions • Low overhead

– On “steady state” and therefore succinct– Only needed to be written at module level

Page 32: Scalable Contract Checking for Systems Software  using SMT solvers

Intra-module inference

• Given module M, interface specs, property and module invariants

• Infer annotations on internal procedures and loops

• Use annotations to verify property and module invariant

• Challenges– Module invariants are temporarily broken– Inference has to be scalable

Page 33: Scalable Contract Checking for Systems Software  using SMT solvers

Module invariant brokenrequires (TypeInvDO)ensures (TypeInvDO)

void publicFoo () { PDEV_OBJ do = NewDEV_OBJ(); privateBar(do);}

requires (TypeInvDOExcept(do))requires (TypeInvDO)ensures (TypeInvDO)

void privateBar (PDEV_OBJ do) { do->DevExt->Self = do;}

DevExt

Self

x

DEV_OBJ

DEV_EXT

#define TypeInvDO \ x MyDevObj. x->DevExt->Self = x \

Page 34: Scalable Contract Checking for Systems Software  using SMT solvers

Houdini algorithm (Flanagan-Leino 01)

• Problem statement – Given a set of procedures P1, …, Pn– A set of C of candidate annotations for each procedure– Returns a subset of the candidate annotations such that each

procedure satisfy its annotations– Also known as “monomial predicate abstraction”

• Algorithm– Performs a greatest-fixed point starting from all annotations

• Remove annotations that are violated– Requires a quadratic (n * |C|) number of theorem prover calls– Uses a modular checker

Page 35: Scalable Contract Checking for Systems Software  using SMT solvers

Candidate assertions

• Candidate assertions– Type-states in module invariants

• Over parameters, globals, locals and their fields

– Module invariant exceptions (next slide)– Conditional annotations

• Disjunction of above annotations

Page 36: Scalable Contract Checking for Systems Software  using SMT solvers

Module invariant exceptionsTypeInvDOExcept({do,de->Self},requires))TypeInvDOExcept({do,de->Self},ensures))void privateBar (PDEV_OBJ do, PDEV_EXT de) { … do->DevExt->Self = do;}

#define TypeInvDO \ x MyDevObj. x->DevExt->Self = x \

#define TypeInvDOExcept({a,b},ANNOT) \

ANNOT(x MyDevObj. x = a x = b x->DevExt->Self = x)\ANNOT(a->DevExt->Self = a) \ANNOT(b->DevExt->Sefl = b) \

Exceptions come from parameters,

return, globals, fields

Page 37: Scalable Contract Checking for Systems Software  using SMT solvers

Observations

• Able to synthesize most intermediate invariants– “close” to the module invariant (simple)– readable

• Invariants contain quantifiers, Boolean structure– Checking all Boolean combinations expensive (from

NP-Complete PSPACE-complete [CADE’09])• Retains scalability of the Houdini inference

Page 38: Scalable Contract Checking for Systems Software  using SMT solvers

Experiments• Benchmarks

– 4 device drivers (~7KLOC each), contains lists, arrays• #Internal methods: ~30• #loops: ~20

• Properties– double-free, lock-usage

• User provides module invariant– Tool infers intermediate invariants and modifies

clauses

Page 39: Scalable Contract Checking for Systems Software  using SMT solvers

Results

• Verified the properties with 0 false alarms• Module invariant overhead

– Number of module invariants ~5-10– Reused across multiple drivers

• Most internal annotations inferred– Approx 1500 inferred annotation per driver– Less than 5 manual annotation per driver

• Mostly conditional annotations (e.g. predicated on return value)

– Inference time < 5X of the checking time

Page 40: Scalable Contract Checking for Systems Software  using SMT solvers

Contributions

• Efficient decision procedure for verifying list-based programs

• Verifying and exploiting C type annotations

• Annotation inference for large modules

Page 41: Scalable Contract Checking for Systems Software  using SMT solvers

Questions?