How to find lots of bugs by checking program belief systems - PowerPoint PPT Presentation

About This Presentation
Title:

How to find lots of bugs by checking program belief systems

Description:

How to find lots of bugs by checking program belief systems Dawson Engler David Chen, Seth Hallem, Ben Chelf, Andy Chou Stanford University ... – PowerPoint PPT presentation

Number of Views:92
Avg rating:3.0/5.0
Slides: 24
Provided by: publicpc7
Learn more at: http://web.stanford.edu
Category:

less

Transcript and Presenter's Notes

Title: How to find lots of bugs by checking program belief systems


1
How to find lots of bugs by checking program
belief systems
This talk I s about how to find lots of error s
in real coe. The way we are going to do this is
a bit unusual. Rather than undertand what rules
the systemmust follow or swhat state it is in,
both of which are hard. Instead we are going to
do omething much easier we will infer what rules
it believes it must obey and what state it
cbelieve it is in and cross check thee believes
for contradictions. The great thing this buys us
is that now we can find lots of errors in coe we
do no t unederstand.
  • Dawson Engler
  • David Chen, Seth Hallem, Ben Chelf, Andy Chou
  • Stanford University

2
Context finding OS bugs w/ compilers
Reduced to using grep on millions of line of
code, or documentation, hoping you can find all
cases
  • Systems have many ad hoc correctness rules
  • acquire lock l before modifying x, cli() must
    be paired with sti(), dont block with
    interrupts disabled
  • One error crashed machine
  • If we know rules, can check with extended
    compiler
  • Rules map to simple source constructs
  • Use compiler extensions to express them
  • Nice scales, precise, statically find 1000s of
    errors

3
Goal find as many serious bugs as possible
Reduced to using grep on millions of line of
code, or documentation, hoping you can find all
cases
  • Problem what are the rules?!?!
  • 100-1000s of rules in 100-1000s of subsystems.
  • To check, must answer Must a() follow b()? Can
    foo() fail? Does bar(p) free p? Does lock l
    protect x?
  • Manually finding rules is hard. So dont.
    Instead infer what code believes, cross check for
    contradiction
  • Intuition how to find errors without knowing
    truth?
  • Contradiction. To find lies cross-examine. Any
    contradiction is an error.
  • Deviance. To infer correct behavior if 1 person
    does X, might be right or a coincidence. If
    1000s do X and 1 does Y, probably an error.
  • Crucial we know contradiction is an error
    without knowing the correct belief!

4
Cross-checking program belief systems
Specification checkable redundancy. Can cross
check code against itself for same effect.
Others that x was not already equal to value.
  • MUST beliefs
  • Inferred from acts that imply beliefs code must
    have.
  • Check using internal consistency infer beliefs
    at different locations, then cross-check for
    contradiction
  • MAY beliefs could be coincidental
  • Inferred from acts that imply beliefs code may
    have
  • Check as MUST beliefs rank errors by belief
    confidence.


x p / z // MUST belief p not null
// MUST z ! 0 unlock(l) // MUST l
acquired x // MUST x not protected by
l
// MAY A() and B() // must be paired
5
Trivial consistency NULL pointers
Show because it is one of the simplest possible
checkers, and because it finds hundreds of errors.
  • p implies MUST belief
  • p is not null
  • A check (p NULL) implies two MUST beliefs
  • POST p is null on true path, not null on false
    path
  • PRE p was unknown before check
  • Cross-check these for three different error
    types.
  • Check-then-use (79 errors, 26 false pos)

/ 2.4.1 drivers/isdn/svmb1/capidrv.c
/ if(!card) printk(KERN_ERR, capidrv-d ,
card-gtcontrnr)
6
Null pointer fun
Can look for redundancy in general deadcode elim
is an error finder. Can look for writes never
read, lock acquired that protects nothing,
  • Use-then-check 102 bugs, 4 false
  • Contradiction/redundant checks (24 bugs, 10 false)

/ 2.4.7 drivers/char/mxser.c / struct
mxser_struct info tty-gtdriver_data unsigned
flags if(!tty !info-gtxmit_buf) return 0
/ 2.4.7/drivers/video/tdfxfb.c /
fb_info.regbase_virt ioremap_nocache(...)
if(!fb_info.regbase_virt) return -ENXIO
fb_info.bufbase_virt ioremap_nocache(...) /
META meant fb_info.bufbase_virt! /
if(!fb_info.regbase_virt)
iounmap(fb_info.regbase_virt)
7
Redundancy checking
Can look for redundancy in general deadcode elim
is an error finder. Can look for writes never
read, lock acquired that protects nothing.
Redundant transition means were missing
something with analysis.
  • Assume code supposed to be useful
  • Useless actions conceptual confusion. Like
    type systems, high level bugs map to low-level
    redundancies
  • Identity operations x x, 1 y, x x,
    x x
  • Assignments that are never read

/ 2.4.5-ac8/net/appletalk/aarp.c / da.s_node
sa.s_node da.s_net da.s_net
for(entrypriv-gtlec_arp_tablesientry ! NULL
entrynext) next entry-gtnext if ()
lec_arp_remove(priv-gtlec_arp_tables, entry)
lec_arp_unlock(priv) return 0
Critical sections that have no shared state,
contradictory booleans in general look at
deadcode elim and CSE as error signalers
8
Internal Consistency finding security holes
First pass mark all pointers treated as user
pointers. Second pass make sure they are never
dereferenced.
  • Applications are bad
  • Rule do not dereference user pointer ltpgt
  • One violation security hole
  • Detect with static analysis if we knew which were
    bad
  • Big Problem which are the user pointers???
  • Soln forall pointers, cross-check two OS
    beliefs
  • p implies safe kernel pointer
  • copyin(p)/copyout(p) implies dangerous user
    pointer
  • Error pointer p has both beliefs.
  • Implemented as a two pass global checker
  • Result 24 security bugs in Linux, 18 in OpenBSD
  • (about 1 bug to 1 false positive)

9
An example
Marked as tainted because passed as the first
argument to copy_to_user, which is used to access
potentientially bad user pointers. Does global
analysis to detect that the pointer will be
dereferenced by ippd_
  • Still alive in linux 2.4.4
  • Tainting marks rt as a tainted pointer,
    checking warns that rt is passed to a routine
    that dereferences it
  • 2 other examples in same routine

/ drivers/net/appletalk/ipddp.cipddp_ioctl
/ case SIOCADDIPDDPRT return
ipddp_create(rt)case SIOCDELIPDDPRT
return ipddp_delete(rt) case SIOFCINDIPDDPRT if
(copy_to_user(rt, ipddp_find_route(rt),
sizeof(struct ipddp_route))) return
EFAULT
10
Cross checking beliefs related abstractly
  • Parameter features Can a param be null? What
    are legal values of integer parameter Return
    code What are allowable error code to return
    when?
  • Execution context Are interrupts off or on when
    code runs? When it exits? Does it run
    concurrently?
  • Common multiple implementations of same
    interface.
  • Beliefs of one implementation can be checked
    against those of the others!
  • User pointer (3 errors)
  • If one implementation taints its argument, all
    others must
  • How to tell? Routines assigned to same function
    pointer
  • More general infer execution context, arg
    preconditions
  • Interesting q what spec properties can be
    inferred?

bar_write(void p, void arg,) p (int
)arg do something disable()
return 0
foo_write(void p, void arg,)
copy_from_user(p, arg, 4) disable() do
something enable() return 0
If one does it right, we can cross check all if
one dev gets it right we are in great shape.
11
Handling MAY beliefs
  • MUST beliefs only need a single contradiction
  • MAY beliefs need many examples to separate fact
    from coincidence
  • Conceptually
  • Assume MAY beliefs are MUST beliefs
  • Record every successful check with a check
    message
  • Every unsuccessful check with an error message
  • Use the test statistic to rank errors based on
    ratio of checks (n) to errors (err)
  • Intuition the most likely errors are those where
    n is large, and err is small.

z(n, err) ((n-err)/n-p0)/sqrt(p0(1-p0)/n)
12
Statistical Deriving deallocation routines
Can cross-correlate free is on error path, has
dealloc in name, etc, bump up ranking. Foo has 3
errors, and 3 checks. Bar, 3 checks, one error.
Essentially every passed check implies belief
held, every error not held
  • Use-after free errors are horrible.
  • Problem lots of undocumented sub-system free
    functions
  • Soln derive behaviorally pointer p not used
    after call foo(p) implies MAY belief that foo
    is a free function
  • Conceptually Assume all functions free all
    arguments
  • (in reality filter functions that have
    suggestive names)
  • Emit a check message at every call site.
  • Emit an error message at every use
  • Rank errors using z test statistic z(checks,
    errors)
  • E.g., foo.z(3, 3) lt bar.z(3, 1) so rank bars
    error first
  • Results 23 free errors, 11 false positives

bar(p) p x
bar(p) p 0
foo(p) p x
foo(p) p x
foo(p) p x
bar(p) p 0
13
A bad free error
/ drivers/block/cciss.ccciss_ioctl / if
(iocommand.Direction XFER_WRITE) if
(copy_to_user(...)) cmd_free(NULL, c)
if (buff ! NULL) kfree(buff)
return( -EFAULT) if (iocommand.Directio
n XFER_READ) if (copy_to_user(...))
cmd_free(NULL, c)
kfree(buff) cmd_free(NULL, c) if
(buff ! NULL) kfree(buff)

14
Statistical deriving routines that can fail
Can also use consistency if a routine calls a
routine that fails, then it to can fail.
Similarly, if a routine checks foo for failure,
but calls bar, which does not, is a type error.
(In a sense can use witnesses take good code and
see what it does, reapply to unknown code)
  • Traditional
  • Use global analysis to track which routines
    return NULL
  • Problem false positives when pre-conditions
    hold, difficult to tell statically (return
    p-gtnext?)
  • Instead see how often programmer checks.
  • Rank errors based on number of checks to
    non-checks.
  • Algorithm Assume all functions can return NULL
  • If pointer checked before use, emit check
    message
  • If pointer used before check, emit error
  • Sort errors based on ratio of checks to errors
  • Result 152 bugs, 16 false.

p bar() If(!p) return p x
p bar() If(!p) return p x
p bar() If(!p) return p x
p bar() p x
P foo() p x
15
The worst bug
  • Starts with weird way of checking failure
  • So why are we looking for seg_alloc?

/ 2.3.99 ipc/shm.c1745map_zero_setup /if
(IS_ERR(shp seg_alloc(...))) return
PTR_ERR(shp)static inline long IS_ERR(const
void ptr) return (unsigned long)ptr gt
(unsigned long)-1000L
/ ipc/shm.c750newseg /if (!(shp
seg_alloc(...)) return -ENOMEMid
shm_addid(shp)
int ipc_addid( new) ... new-gtcuid
new-gtuid new-gtgid new-gtcgid
ids-gtentriesid.p new
16
Deriving A() must be followed by B()
  • a() b() implies MAY belief that a() follows
    b()
  • Programmer may believe a-b paired, or might be a
    coincidence.
  • Algorithm
  • Assume every a-b is a valid pair (reality
    prefilter functions that seem to be plausibly
    paired)
  • Emit check for each path that has a() then b()
  • Emit error for each path that has a() and no
    b()
  • Rank errors for each pair using the test
    statistic
  • z(foo.check, foo.error) z(2, 1)
  • Results 23 errors, 11 false positives.

17
Checking derived lock functions
/ 2.4.1 drivers/sound/trident.c
trident_release lock_kernel() card
state-gtcard dmabuf state-gtdmabuf
VALIDATE_STATE(state)
  • Evilest
  • And the award for best effort

/ 2.4.0drivers/sound/cmpci.ccm_midi_release
/ lock_kernel() if (file-gtf_mode
FMODE_WRITE) add_wait_queue(s-gtmidi.owai
t, wait) ... if
(file-gtf_flags O_NONBLOCK)
remove_wait_queue(s-gtmidi.owait, wait)
set_current_state(TASK_RUNNING)
return EBUSY unlock_kernel()

18
Summary Belief Analysis
  • Key ideas
  • Check code beliefs find errors without knowing
    truth.
  • Beliefs code MUST have Contradictions errors
  • Beliefs code MAY have check as MUST beliefs and
    rank errors by belief confidence
  • Secondary ideas
  • Check for errors by flagging redundancy.
  • Analyze client code to infer abstract features
    rather than just implementation.
  • Spec checkable redundancy. Can use code for
    same.

19
Example free checker
Simple. Have had freshman write these and post
bugs to linux groups. Three parts start state.
Pattern raw c coede or wildcards., match does a
transition, callouts. Scales with
sophistication of analysis. System will kill
variable, track when assigned to others.
sm free_checker state decl any_pointer v
decl any_pointer x start kfree(v) ?
v.freed v.freed v x v !
x ? / suppress fp / v ?
err(Use after free!)
start
kfree(v)
v.freed
use(v)
error
20
Example inferring free checker
Simple. Have had freshman write these and post
bugs to linux groups. Three parts start state.
Pattern, match does a transition, callouts.
Scales with sophistication of analysis.
sm free_checker state decl any_pointer v
decl any_pointer x decl any_fn_call call decl
any_args args start call(v) ?
char n mc_identifier(call) if(strstr(n,
free) strstr(n, dealloc) )
mc_v_set_state(v, freed)
mc_v_set_data(v, n) note(NOTE s,
n) v.freed v x v ! x
? / suppress fp / v ? err(Use
after free s!, mc_v_get_data(v))
21
Context finding OS bugs w/ static analysis
Follow paths in code to see that they satisfy a
partial order, or do not overcommit resources, or
obey temporal orderings key abstract rules map
pretty clearly to source code.
  • Systems software has many ad-hoc restrictions
  • reenable disabled interrupts, hold lock l
    before using x
  • Lots of rules one bug crashed system
  • Our approach system-specific extensions check
    rules
  • Scalable handles millions of lines of code
  • Precise says exactly what error was
  • Static does not require running code
  • Effective 1500 errors in Linux source code

22
Goal find as many serious bugs as possible.
Reduced to using grep on millions of line of
code, or documentation, hoping you can find all
cases
  • THE problem what are the rules?!?!
  • 100-1000s of rules in 100-1000s of subsystems.
  • To check, must answer Must a() follow b()? Can
    foo() fail? Does bar(p) free p? Does lock l
    protect x?
  • Manually finding rules is hard. So dont.
    Instead infer what code believes, cross check for
    contradiction
  • Intuition how to find errors without knowing
    truth?
  • Contradiction. To find lies cross-examine. Any
    contradiction is an error.
  • Deviance. To infer correct behavior if 1 person
    does X, might be right or a coincidence. If
    1000s do X and 1 does Y, probably an error.
  • Crucial we know contradiction is an error
    without knowing the correct belief!

23
Related work
  • Tool-based checking
  • PREfix/PREfast
  • Slam
  • ESP, ASTlog
  • Higher level languages
  • TypeState, Vault
  • Foster et als type qualifier work.
  • Derivation
  • Houdini to infer ESC specs
  • Daikon for dynamic invariants
  • Larus et al dynamic temporal inference
  • Spec extraction
  • Bandera
  • Slam
Write a Comment
User Comments (0)
About PowerShow.com