1 / 60

Type Qualifiers

Type Qualifiers. Lecture 14 CS 6340 (adapted from a talk by Jeffrey Foster). Even after large, extensive testing efforts, commercial software is shipped riddled with errors ("bugs"). -- PITAC Report to the President, February 24, 1999.

meir
Télécharger la présentation

Type Qualifiers

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. Type Qualifiers Lecture 14CS 6340 (adapted from a talk by Jeffrey Foster)

  2. Even after large, extensive testing efforts, commercial software is shipped riddled with errors ("bugs"). -- PITAC Report to the President, February 24, 1999 Trustworthy Computing is computing that is available, reliable, and secure as electricity, water services and telephony....No Trustworthy Computing platform exists today. -- Bill Gates, January 15, 2002 (highest priority for Microsoft) Software Quality Today

  3. Conclusion? Software is buggy

  4. So What? • Software has always been buggy • But now... • More people use software • Computers keep getting faster • Speed/quality tradeoff changing • Cost of fixing bugs is high

  5. Common Techniques for Software Quality • Testing • Code auditing • Drawbacks: Expensive, difficult, error-prone, limited assurances • What more can we do? • Tools that analyze source code • Techniques for avoiding programming mistakes

  6. Tools Need Specifications • put_tty_queue_nolock(c, tty); • spin_lock_irqsave(&tty->read_lock, flags); • spin_unlock_irqrestore(&tty->read_lock, flags); • Goal: Add specifications to programs • In a way that... • Programmers will accept • Lightweight • Scales to large programs • Solves many different problems

  7. const ANSI C tainted Security vulnerabilities File operations open Type Qualifiers • Extend standard type systems (C, Java, ML) • Programmers already use types • Programmers understand types • Get programmers to write down a little more... int ptr( char) int  ptr( FILE)

  8. Application: Format String Vulnerabilities • I/O functions in C use format strings printf("Hello!"); Hello! printf("Hello, %s!", name); Hello,name! • Instead of printf("%s", name); Why not printf(name); ?

  9. Format String Attacks • Adversary-controlled format specifier name := <data-from-network> printf(name); /* Oops */ • Attacker sets name = “%s%s%s” to crash program • Attacker sets name = “...%n...” to write to memory • Lots of these bugs in the wild • New ones weekly on bugtraq mailing list • Too restrictive to forbid variable format strings

  10. Using Tainted and Untainted • Add qualifier annotations int printf(untainted char *fmt, ...) taintedchar *getenv(const char *) tainted = may be controlled by adversary untainted = must not be controlled by adversary

  11. tainteduntainted / Subtyping void f(tainted int); untainted int a; f(a); void g(untainted int); tainted int b; f(b); OK f accepts tainted or untainted data Error g accepts only untainted data untainted tainted untainted tainted

  12. Framework • Pick some qualifiers • and relation (partial order) among qualifiers • Add a few explicit qualifiers to program • Infer remaining qualifiers • and check consistency

  13. Type Qualifier Inference • Two kinds of qualifiers • Explicit qualifiers: tainted, untainted, ... • Unknown qualifiers: a0,a1, ... • Program yields constraints on qualifiers tainteda0a0untainted • Solve constraints for unknown qualifiers • Error if no solution

  14. int  ptr( FILE) open a0  a1 int a2 ptr ptr( char) tainted open FILE a ptr tainted char Adding Qualifiers to Types

  15. f y z a6a1 a0  a2a4 a1 int a2 ptr a4 ptr a6 int a3=a5 a3 int a5 int Constraint Generation ptr(int) f(x : int) = { ... } y := f(z)

  16. untainted a0 a7 a2a4 a1 a2 a4 a6 a3=a5 a9 • • • a3 a5 tainted a8 Constraints as Graphs Key idea: programs  constraints  graphs a6a1

  17. a0 a2a4 a1 a2 a4 a6 a3 a5 Satisfiability via Graph Reachability Is there an inconsistent path through the graph? untainted a6a1 a7 a3=a5 a9 • • • tainted a8

  18. a0 a2a4 a1 a2 a4 a6 a3 a5 Satisfiability via Graph Reachability Is there an inconsistent path through the graph? untainted a6a1 a7 a3=a5 a9 • • • tainted a8

  19. a0 a2a4 a1 a2 a4 a6 a3 a5 Satisfiability via Graph Reachability tainteda6a1a3a5a7untainted untainted a6a1 a7 a3=a5 a9 • • • tainted a8

  20. Satisfiability in Linear Time • Initial program of size n • Fixed set of qualifiers tainted, untainted, ... • Constraint generation yields O(n) constraints • Recursive abstract syntax tree walk • Graph reachability takes O(n) time • Works for semi-lattices, discrete p.o., products

  21. The Story So Far... • Type qualifiers as subtyping system • Qualifiers live on the standard types • Programs  constraints  graphs • Useful for a number of real-world problems • Up next: State change and type qualifiers • A glimpse of a more complex system • Followed by: Applications, experiments

  22. Application: Locking Lock x; lock(x); ...critical section... unlock(x); • x : locked Lock • x : unlocked Lock

  23. Flow-Sensitive Type Qualifiers • Standard type systems are flow-insensitive • Types don't change during execution /* x : int */ x := ...; /* x : int */ • We need flow-sensitivity • Qualifiers may change during execution /* y : locked Lock */ y := ...; /* y : unlocked Lock */

  24. Some Challenges • How do we deal with aliasing? p = &x; *p = ...; • How do we make the analysis scale? • Too expensive to model full state at each point • What happens when too much is aliased? • How does the programmer control aliasing?

  25. Modeling State with Abstract Stores • Track each variable's type at each point • Abstract stores map variables to types • ...and types contain qualifiers • { x : t, y : r, z : s, ... } • x := ...; • { x : t', y : r, z : s, ... } • y := ...; • { x : t', y : r', z : s, ... }

  26. What About Aliasing? • Suppose p points to x: { x : q int, p : ptr(q int), ... } *p := ...; { x : q int, p : ptr(q' int), ... } • Variable names alone are insufficient • Solution: Add a level of indirection • Stores map locations to types • Pointer types point to locations

  27. r *p : ptrr(int)*x : ptrs(int) ... /* require r = s */ Unification-Based Alias Analysis • Initial flow-insensitive pass computes aliasing • Before flow-sensitive analysis • Simultaneous with standard type inference • Types are not flow-sensitive, only qualifiers • Associate a location r with each pointer • Unify locations that may alias p = &x;

  28. { r : q int, h : ptr(r), ... } Using Locations in Stores • Suppose p points to x: *p : ptrr(int) x : ptrr(int) { x : q int, p : ptr(q int), ... } • *p := ...; • { r : q' int, h : ptr(r), ... }

  29. What About Scalability? • Stores are too big { r : t, h : r, n : s, ... } • A program of size n may have • n locations • n program points • n2 space to represent stores • We need a more compact representation • Idea: represent differences between stores

  30. Constructing Stores • Three kinds of stores S S ::= e Unknown store | Alloc(S, r : t) Like store S, but r allocated with type t | Assign(S, r : t) Like store S, but update type of r with t • Store constraints Se • Control flow from S to e • Solution maps e to { r : t, h : r, n : s, ... } • Key: only write down necessary portion of soln.

  31. Example Lock x; while (...) { lock(x); y := ... unlock(x); }

  32. Alloc(e0, r : unlocked) e1 Alloc(e0, r : unlocked) e1 Alloc(e0, r : unlocked) e1 Assn(Assn(Assn(e1, r : locked), h : q t), r : unlocked) e1 Assn(Assn(Assn(e1, r : locked), h : q t), r : unlocked) e1 Assn(Assn(Assn(e1, r : locked), h : q t), r : unlocked)e1 Assn(Assn(Assn(e1, r : locked), h : q t), r : unlocked) e1 e1 e2 e0 Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock Example Lock xr; while (...) { lock(xr); yh := ... unlock(xr); }

  33. Alloc(e0, r : unlocked) e1 Assn(Assn(Assn(e1, r : locked), h : q t), r : unlocked) e1 e1 e2 Example e0 Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  34. Lazy Constraint Resolution • We don't care about most locations • only those that may be lockedorunlocked • In this case, we will only do work for r • Key to efficiency: When solving for store variables, only represent the minimum necessary

  35. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  36. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  37. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  38. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  39. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  40. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  41. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  42. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  43. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  44. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  45. Constraint Resolution Example e0 green = { r : unlocked Lock } red = { r : locked Lock } Alloc r : unlocked Lock e1 e2 Assign r : locked Lock check e1(r) : unlocked Lock Assign h : q t  check (r) : locked Lock Assign r : unlocked Lock

  46. Strong Updates • In e2, location r has qualifier q' • We've replaced r's qualifier • This is called a strong update • Location r is linear e0 Alloc r : q int e1 Assign r : q' int e2

  47. Weak Updates • What if r allocated twice? • Only one is actually updated e0 Alloc r : q int Alloc r : q int • In e2, location r has qualifier q q' • We've merged r's new and old qualifiers • This is called a weak update • Location r is non-linear e1 Assign r : q' int e2

  48. Recovering Linearity • What do we do when aliasing too imprecise? • Can't strongly update non-linear locations • New construct restrict • Programmer adds restrict to help the alias analysis • restrict x = e1 in e2 • Roughly: within e2, accesses to *e1 must use x

  49. Restrict Example Lock locks[n]; lock(&locks[i]); ... unlock(&locks[i]);

  50. Restrict Example • Within scope of restrict, only mylock used • Can perform strong updates • After restrict ends, weak update from mylock to locks[] Lock locks[n]; restrict mylock = &locks[i] in lock(mylock); ... unlock(mylock);

More Related