automated tools for software reliability
Download
Skip this Video
Download Presentation
Automated Tools for Software Reliability

Loading in 2 Seconds...

play fullscreen
1 / 72

Automated Tools for Software Reliability - PowerPoint PPT Presentation


  • 89 Views
  • Uploaded on

Automated Tools for Software Reliability. Suhabe Bugrara [email protected] Stanford University. Problem. 80% of development cost on identifying and correcting defects Software errors cost US economy $60 billion annually (0.6% of GDP). Manual Testing.

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about ' Automated Tools for Software Reliability' - triage


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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
problem
Problem
  • 80% of development cost on identifying and correcting defects
  • Software errors cost US economy $60 billion annually (0.6% of GDP)
manual testing
Manual Testing
  • Traditional approach to quality assurance
  • Expensive
  • Time consuming
  • Not systematic
  • Difficult to quantify effectiveness of test suite
  • Cannot make any guarantees about reliability
  • Insufficient for safety critical systems
automated tools
Automated Tools
  • Programs to find defects in programs
  • Automated
  • Systematic
  • Easy to quantify effectiveness
  • Provide guarantees about reliability
  • Sometimes expensive (for now…)
  • Sometimes time consuming (for now…)
program analyzers
Program Analyzers

Complete

Incomplete

Undecidable

Decidable

Sound

  • Reports all errors
  • Reports no false alarms
  • Reports all errors
  • May report false alarms

Decidable

Decidable

Unsound

  • May not report all errors
  • Reports no false alarms
  • May not report all errors
  • May report false alarms
static driver verifier
Static Driver Verifier
  • Program analyzer for API usage rules
  • Developed by Microsoft Research
  • Applied to device drivers in Windows
  • Sound: reports all possible errors
  • Incomplete: may report false alarms
sdv overview
SDV: Overview
  • Write API usage rule specification
  • Instrument program with usage checks
  • Abstract program
  • Check abstraction for errors
  • If error found, see if error is false alarm
  • If false alarm, refine abstraction
  • If not false alarm, report error as bug
api usage rules
API Usage Rules
  • Ex. locks are alternatingly acquired and released
api usage rules1
API Usage Rules
  • Ex. locks are alternatingly acquired and released
  • Expressed as finite state machine
    • States = {locked, unlocked,error}
    • Transitions = {acquire(), release()}
api usage rules2
API Usage Rules
  • Ex. locks are alternatingly acquired and released
  • Expressed as finite state machine
    • States = {locked, unlocked,error}
    • Transitions = {acquire(), release()}

acquire();

unlocked

locked

release();

release();

acquire();

error

slide13

state {

enum { Unlocked=0; Locked=1} state = Unlocked;

}

KeAcquireSpinLock.return {

if (state == Locked)

error();

else

state = Locked;

}

KeReleaseSpinLock.return {

if (!(state == Locked))

error();

else

state = Unlocked;

}

slide14

enum {Unlocked=0, Locked=1} state = Unlocked

voidKeAcquireSpinLock_return() {

if (state == Locked)

error();

else

state = Locked;

}

voidKeReleaseSpinLock_return() {

if (!(state == Locked))

error();

else

state = Unlocked;

}

slide16

1: voidexample() {

2: do {

3: KeAcquireSpinLock();

4:

5: nPacketsOld = nPackets;

6: req = devExt->WLHV

7: if (req && req->status) {

8: devExt->WLHV = req->Next

9: KeReleaseSpinLock();

10:

11: irp = req->irp;

12: if (req->status > 0) {

13: irp->IoS.Status = SUCCCESS;

14: irp->IoS.Info = req->Status;

15: } else {

16: irp->IoS.Status = FAIL;

17: irp->IoS.Info = req->Status;

18: }

19: SmartDevFreeBlock(req);

20: IoCompleteRequest(irp);

21: nPackets++;

22: }

23: } while (nPackets!=nPacketsOld);

24: KeReleaseSpinLock();

25:

26: }

slide18

enum {Unlocked=0, Locked=1} state = Unlocked

voidKeAcquireSpinLock_return() {

if (state == Locked)

error();

else

state = Locked;

}

voidKeReleaseSpinLock_return() {

if (!(state == Locked))

error();

else

state = Unlocked;

}

slide19

1: voidexample() {

2: do {

3: KeAcquireSpinLock();

4: KeAcquireSpinLock_return();

5: nPacketsOld = nPackets;

6: req = devExt->WLHV

7: if (req && req->status) {

8: devExt->WLHV = req->Next

9: KeReleaseSpinLock();

10: KeReleaseSpinLock_return();

11: irp = req->irp;

12: if (req->status > 0) {

13: irp->IoS.Status = SUCCCESS;

14: irp->IoS.Info = req->Status;

15: } else {

16: irp->IoS.Status = FAIL;

17: irp->IoS.Info = req->Status;

18: }

19: SmartDevFreeBlock(req);

20: IoCompleteRequest(irp);

21: nPackets++;

22: }

23: } while (nPackets!=nPacketsOld);

24: KeReleaseSpinLock();

25: KeReleaseSpinLock_return();

26: }

Program A

sdv abstraction
SDV: Abstraction
  • Construct abstractionB of original program A
    • Over-approximates reachability
      • If error() is reachable in A,

then it is also reachable in B

        • This characteristic makes SDV sound
      • If error() is reachable in B,

then it may not be reachable in A

        • This characteristic makes SDV incomplete
  • Check abstraction B for any errors
reachable states
Reachable States

Abstraction B

real bug!

error

Original A

Sound: If A has error, then B has error

reachable states1
Reachable States

false alarm!

Abstraction B

error

Original A

Incomplete: If B has error, then A may not have error

slide24

bool b1;

b1 = false; Abstract state == Locked withb1

voidKeAcquireSpinLock_return() {

if (b1)

error();

else

b1 = true;

}

voidKeReleaseSpinLock_return() {

if (!(b1))

error();

else

b1 = false;

}

slide25

1: voidexample() {

2: do {

3: ;

4: KeAcquireSpinLock_return();

5: ;

6: ;

7: if (SdvMakeChoice()) {

8: ;

9: ;

10: KeReleaseSpinLock_return();

11: ;

12: if (SdvMakeChoice()) {

13: ;

14: ;

15: } else {

16: ;

17: ;

18: }

19: ;

20: ;

21: ;

22: }

23: } while (SdvMakeChoice());

24: ;

25: KeReleaseSpinLock_return();

26: }

Program B

slide27

1: voidexample() {

2: do {

3: ;

4: KeAcquireSpinLock_return();

5: ;

6: ;

7: if (SdvMakeChoice()) {

8: ;

9: ;

10: KeReleaseSpinLock_return();

11: ;

12: if (SdvMakeChoice()) {

13: ;

14: ;

15: } else {

16: ;

17: ;

18: }

19: ;

20: ;

21: ;

22: }

23: } while (SdvMakeChoice());

24: ;

25: KeReleaseSpinLock_return();

26: }

Error trace

found!

slide28

1: voidexample() {

2: do {

3: KeAcquireSpinLock();

4: KeAcquireSpinLock_return();

5: nPacketsOld = nPackets;

6: req = devExt->WLHV

7: if (req && req->status) {

8: devExt->WLHV = req->Next

9: KeReleaseSpinLock();

10: KeReleaseSpinLock_return();

11: irp = req->irp;

12: if (req->status > 0) {

13: irp->IoS.Status = SUCCCESS;

14: irp->IoS.Info = req->Status;

15: } else {

16: irp->IoS.Status = FAIL;

17: irp->IoS.Info = req->Status;

18: }

19: SmartDevFreeBlock(req);

20: IoCompleteRequest(irp);

21: nPackets++;

22: }

23: } while (nPackets!=nPacketsOld);

24: KeReleaseSpinLock();

25: KeReleaseSpinLock_return();

26: }

But, no bug in original program!

slide30

1: voidexample() {

2: do {

3: ;

4: KeAcquireSpinLock_return();

5: b2 = false;

6: ;

7: if (SdvMakeChoice()) {

8: ;

9: ;

10: KeReleaseSpinLock_return();

11: ;

12: if (SdvMakeChoice()) {

13: ;

14: ;

15: } else {

16: ;

17: ;

18: }

19: ;

20: ;

21: b2 = !b2 ? true : SdvMakeChoice();

22: }

23: } while (b2);

24: ;

25: KeReleaseSpinLock_return();

26: }

ProgramC

reachable states2
Reachable States

Abstraction B

error

Refined C

Original A

false alarm no longer reported!

sdv summary
SDV: Summary
  • Write API usage rule specification
  • Instrument program with usage checks
  • Abstract program
  • Check abstraction for errors
  • If error found, see if error is false alarm
  • If false alarm, refine abstraction
  • If not false alarm, report error as bug
soundness
Soundness
  • Assume memory safety
    • No buffer/integer overflows
    • Safe memory management
    • No null pointer dereferences
  • Oversimplified harness
    • Use stubs to model calls into OS procedures
    • Stubs may not represent all behavior
research challenges in verification
Research Challenges in Verification
  • Eliminate assumption of memory safety
  • Eliminate false alarms
  • Scale to the entire operating system
  • Verify more complicated properties
    • prove consistency of file system data structures
program analyzers1
Program Analyzers

Complete

Incomplete

Undecidable

Decidable

Sound

  • Reports all errors
  • Reports no false alarms
  • Reports all errors
  • May report false alarms

Decidable

Decidable

Unsound

  • May not report all errors
  • Reports no false alarms
  • May not report all errors
  • May report false alarms
slide36
EXE
  • Automatically generate test cases that explore important program paths
  • Developed by Dawson Engler’s group
  • Bug finding tool
  • Unsound: may not report all errors
  • Complete: never reports false alarms
slide37

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

slide38

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

slide39

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

(x >= INT_MIN) && (x <= INT_MAX) && (x < 0) && (ret = -x)

find a solution using an automatic constraint solver…

x = -1

slide40

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

(x >= INT_MIN) && (x <= INT_MAX) && (x >= 0) && (x = 12345678) && (ret = -x)

find a solution using an automatic constraint solver…

x = 12345678

slide41

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

(x >= INT_MIN) && (x <= INT_MAX) && (x >= 0) && (x != 12345678)

&& (ret = x)

find a solution using an automatic constraint solver…

x = 4

slide42

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

EXE automatically generated test cases for each path…

x = -1

x = 12345678

x = 4

slide43

intbad_abs (int x) {

if (x < 0)

return –x;

if (x == 12345678)

return –x;

return x;

}

slide44

1: intsymbolic_bad_abs (int x) {

2: add_constraints(x >= INT_MIN, x <= INT_MAX);

3: ret = new symbol;

4:

5: if (fork() == child) {

6: add_constraints(x < 0, ret = -x);

7: return ret;

8://(x >= INT_MIN) && (x <= INT_MAX) && (x < 0) && (ret = -x)

9: } else

10: add_constraints(x >= 0);

11:

12: if (fork() == child) {

13: add_constraints(x = 12345678, ret = -x);

14: return ret;

15: //(x >= INT_MIN) && (x <= INT_MAX) && (x >= 0) && (x = 12345678)

16:// && (ret = -x)

17: } else

18: add_constraints(x != 12345678);

19:

20: add_constraints(ret = x);

21: return ret;

22: //(x >= INT_MIN) && (x <= INT_MAX) && (x >= 0) && (x != 12345678)

23:&& (ret = x)

24:}

slide45

1: intmain (void) {

2: unsigned i, t, a[4] = { 1, 3, 5, 2};

3: make_symbolic(&i);

4:

5: if (i >= 4)

6: exit(0);

7:

8: char *p = (char *) a + i * 4;

9: *p = *p – 1;

10:

11: t = a[*p];

12:

13: t = t / a[i];

14:

15: if (t == 2)

16: assert(i == 1);

17: else

18: assert(i == 3);

19: }

review
Review
  • Why does SDV produce false alarms and EXE doesn’t?
  • Why use SDV, then?
saturn
Saturn
  • Large-scale program verification
  • Developed by Alex Aiken’s group
  • Sound: reports all errors
  • Incomplete: may report false alarms
  • Gives guarantees of reliability on systems as large as the Linux kernel with over 6.2 million lines of code
program analyzers2
Program Analyzers

Complete

Incomplete

Undecidable

Decidable

Sound

  • Reports all errors
  • Reports no false alarms
  • Reports all errors
  • May report false alarms

Decidable

Decidable

Unsound

  • May not report all errors
  • Reports no false alarms
  • May not report all errors
  • May report false alarms
unchecked user pointer dereferences
Unchecked User Pointer Dereferences
  • Security property of operating systems
  • Two types of pointers in operating systems
    • kernel pointer: pointer created by the operating system
    • user pointer: pointer created by a user application and passed to the operating system via an entry point such as a system call
  • Must check that a user pointer points into userspace before dereferencing it
unchecked user pointer dereferences1
Unchecked User PointerDereferences

1: static ssize_t read_port(…, char * __user buf, …) {

2: unsigned long i = *ppos;

3: char * __user tmp = buf;

4:

5: if (!access_ok(..,buf,...)) //check

6: return -EFAULT;

7:

8: while (count-- > 0 && i < 65536) {

9: if (__put_user(inb(i),tmp) < 0) //deref

10: return -EFAULT;

11: i++;

12: tmp++;

13: }

14:

15: *ppos = i;

16: return tmp-buf;

17: }

security vulnerability
Security Vulnerability
  • Malicious user could
    • Take control of the operating system
    • Overwrite kernel data structures
    • Read sensitive data out of kernel memory
    • Crash machine by corrupting data
verifying the security property
Verifying the Security Property
  • Eliminate the need for annotations
  • Eliminate false positives
  • Provide guarantee that no security vulnerabilities of this kind are present
security verifier
Security Verifier
  • Design a sound and incomplete verifier to prove statically that no unchecked user pointer dereferences exist
security verifier1
Security Verifier
  • Compute set of facts at each program point
  • States = { user, checked, error}
  • Facts are pairs of locations and states
    • (*v,user) signifies that v is a user pointer
  • Verify that program never in error state
security verifier2
Security Verifier
  • Pointer is in user state if created by user application
  • Pointer is in checked state if access_ok applied
  • Pointer is in error state if dereferenced when
    • Pointer is in user state, AND
    • Pointer is NOT in checked state
example
Example

1: int sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: …

one possible approach
One Possible Approach

1: int sys_call (int *u, int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: …

(*u,user)

(*u,user)

(*u,user)

(*u,user)

(*u,checked)

(*u,user) lost precision!

(*u,user)

(*u,error) emit warning!

…, but, procedure does not contain any vulnerabilities!

path sensitivity
Path Sensitivity
  • Ability to reason about branch correlations
  • Important for reducing false positive rate
  • Programs use substantial amount of branch correlation in practice
example1
Example

1: int sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: …

path sensitivity1
Path Sensitivity

1: int sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: …

Valid Path

path sensitivity2
Path Sensitivity

1: int sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: …

Valid Path

path sensitivity3
Path Sensitivity

1: int sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: …

Valid Path

path sensitivity4
Path Sensitivity

1: int sys_call (int *u, int cmd) { //u is user pointer

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) { //check u

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u; //dereference u

12: …

Invalid Path!

path sensitive analysis
Path Sensitive Analysis

1: int sys_call (int *u, int cmd) {

2: int x;

3:

4: if (cmd == 1) {

5: if (!access_ok(u)) {

6: return –ERR;

7: }

8: }

9: …

10: if (cmd == 1)

11: x = *u;

12: …

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,user)  true

(*u,checked)  cmd == 1

(*u,error)  cmd == 1 && !(cmd == 1) && true

 false

design of saturn security verifier
Design of Saturn Security Verifier
  • Generate summary of behavior for each procedure with respect to calling context
  • Apply summary of callee at call site in caller
  • Repeatedly generate and apply summaries until a fixed point is reached
experimental setup
Experimental Setup
  • Implemented verifier for unchecked user pointer dereferences
  • Applied verifier to Linux 2.6.17.1 built for x86 architecture
  • 6.4 million lines of code
  • Analyzed in 6 hours over 50 node cluster
results
Results
  • 91,543 procedures
  • 154 (.17%) of procedures time out
  • 627 system call parameters
  • 867,544 dereferences
  • 15,452 (1.8%) of dereferences time out
results1
Results
  • Verified automatically
    • 620 out of 627 system call arguments (99%)
    • 851,914 out of 852,092 dereferences (99.96%)
  • Warnings
    • 7 warnings on system call arguments
    • 278 warnings on dereferences
    • 20 annotations required to verify
saturn other analyses
Saturn: Other Analyses
  • Null pointer dereferences bug finder
    • Found hundreds of bugs in systems code
    • Isil Dillig, Thomas Dillig, and Alex Aiken. Static Error Detection Using Semantic Inconsistency Inference, PLDI 2007
  • Buffer overflow
  • Safe casting
  • Integer overflow
  • Locking
  • Safe memory management
other tools
Other Tools
  • BLAST
  • CQual
  • Metal
  • Daikon
  • Vault
  • ESP
  • ESPX
  • MOPS
  • DART
  • CSSV
  • Alloy
  • eXplode
  • Chord
  • TVLA
  • CCured
  • Clouseau
  • STeP
  • Prefix
  • Prefast
  • Failure Oblivious Computing
references
References
  • A. Aiken et al. An Overview of the Saturn Project. PASTE 2007
  • T. Ball et al. Thorough Static Analysis of Device Drivers. EuroSys 2006
  • C. Cadar et al. EXE: Automatically Generating Inputs of Death. CCS 2006
  • C. Cadar et al. Execution Generated Test Cases: How to Make Systems Code Crash Itself. SPIN 2006
  • B. Hackett et al. Modular Checking for Buffer Overflows in the Large. ICSE 2006.
  • J. Yang et al. Automatically generating malicious disks using symbolic execution. IEEE Security and Privacy 2006
  • Software Errors Cost U.S. Economy $59.5 Billion Annually. NIST 2002. http://www.nist.gov/public_affairs/releases/n02-10.htm
ad