1 / 38

Dealing with Memory Errors and Data Races

Dealing with Memory Errors and Data Races. Presented by Thadpong Pongthawornkamol CS598yyz, FA05. CCured in the Real World*. By J. Condit et al . University of California, Berkeley In ACM PLDI’03. *Some slides are borrowed from the authors’ presentation. Outline. Motivation CCured

Télécharger la présentation

Dealing with Memory Errors and Data Races

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. Dealing with Memory Errors and Data Races Presented by Thadpong Pongthawornkamol CS598yyz, FA05

  2. CCured in the Real World* By J. Condit et al. University of California, Berkeley In ACM PLDI’03 *Some slides are borrowed from the authors’ presentation

  3. Outline • Motivation • CCured • Pointer Type System • Type Inference • The Real World • Upcast & Physical Subtyping • Downcast & Run-time Type Info • Compatibility with Libraries • Experimental Results • Conclusion

  4. Memory problems are major causes of system and security failures 50% of software and securities errors Most system softwares are developed with C Flexible, Efficient Also unsafe Motivation

  5. Halt: Memory Safety Violation Instrumented C Program CCured Translator Compile & Execute C Program Success CCured • What is CCured? • An extension of C language to provide type safety • Separate memory object into two disjoint parts • Static & Dynamic • Different kinds of pointers need different levels of checking

  6. Data in C can be divided into two categories Static : object has only one type Dynamic : object does not have to be type-specific Each pointer can be either static or dynamic, depending on how it is used in the code int **a; int i; int acc; int **p; int *e; acc = 0; for (i=0; i<100; i++) { p = a + i; e = *p; while ((int) e % 2 == 0) { e = * (int **) e; } acc += ((int)e >> 1); } Pointer Type System Bound check NULL check Type Check

  7. Properties The best kind of pointers Can’t do pointer arithmetic Can’t be cast to other types assignment, passing arguments and returning are implicit casts Can’t be set to integers except 0 but can be cast to an integer What to check when dereferenced Not NULL Static value Every object pointed by a SAFE pointer of type tmust have type talso Every alias of a SAFE pointer of type tmust be a pointer of type talso SAFE pointers t *ptr; *ptr = …; ptr t

  8. Properties Can do pointer arithmetic Can be set to any integers Can’t be dereferenced anymore Can’t be cast to other types What to check when dereferenced Not NULL Not an integer No bound violation Static value Every object pointed by a SEQ pointer of type tmust have type talso Every alias of a SEQ pointer of type tmust be a pointer of type talso SEQ pointers t ptr[3]; *(ptr+i) = …; base ptr end t t t

  9. Properties Can be cast to any type Can do arithmetic operations What to check Null check when dereferenced Bound check when dereferenced Tag check/update when memory is read/written WILD pointer can point to scalar type or another WILD pointer only Separate dynamic region from static region Tag bit is 1 if the corresponding memory stores the home field of a WILD pointer, and 0 otherwise Prevent non-pointer object to be read as a home field WILD pointers int **ptr; ptr = (char *)…; indicate if each slot points to a home home ptr tags len DYN DYN int 1 1 0

  10. Type Inference • Automatically classify pointer variables in the code into SAFE, SEQ, or WILD • Constraint Collection • Scan each expression and assign basic constraints to it • E.g. result of pointer arithmetic cannot be a SAFE pointer, bad casts must produce WILD pointers • Constraint Normalization • Translate constraints into simpler forms • E.g. { ((q = WILD) -> (q’ = WILD)) Λ (q = WILD)} -> { (q’ = WILD)} • Constraint Solving • Propagate WILD type to related pointers • Propagate SEQ type to related pointers • All remaining variables are considered SAFE

  11. Examples* struct seq_int { int * __SEQ _p ; struct meta_seq_int { void *_b ; void *_e ; } _ms ; }; typedef struct seq_int seq_int; int * arith_sq(seq_int p, int delta); int * arith(int * x, int delta) { return x + delta; } struct meta_wildp_int { void *_b ; } ; struct wildp_int { int * __WILD _p ; struct meta_wildp_int _ms ; } ; typedef struct wildp_int wildp_int; int foo_w(wildp_int __WILD a); int foo(int * a) { int * * g = (int * *)a; // Bad cast return 0; } *CCURED Documentation. http://manju.cs.berkeley.edu/ccured/

  12. Handling the rest of C* • Ignore explicit deallocation • Use garbage-collector instead • Separate stack pointers • Disallow stack pointers to be written to the heap or globals • Pointers to functions are treated similarly • Casts between different signature produce WILD pointers • Union structure unsafe • Likely to be WILD • Etc. *Necula et al. CCured: Type-safe retrotting of legacy code. ACM POPL’02

  13. The Real World • Too many WILD pointers in real programs • WILD property is contagious • High runtime-overhead • Most “bad” casts are not really bad • Upcasts & downcasts between class hierarchy, which all classes have common structures • Accepting such casts does not violate the integrity of the program • Compatibility problem with external precompiled library • Inconsistency between original data structure and Ccured-modified data structure • Manual conversion between two types requires tedious works

  14. Circle Figure double (*) (struct Figure *) int Coping with Casts • Parent-child pair types have the same structure prefix • Type conversion among parent-child pair types is common in C • 93% of bad casts are upcasts • 6% of bad casts are downcasts struct Figure { double (*area)(struct Figure * obj); }; struct Circle { double (*area)(struct Figure * obj); int radius; } *c; double Circle area(Figure *obj) { Circle *cir = (Circle*)obj; // downcast return PI * cir->radius * cir->radius; } c->area((struct Figure *)c); // upcast

  15. Upcast • Add Rules and modify inference algorithm to allow upcast • Consider “void *” type as a parent of all pointer types • It is safe to cast any pointers to void * The upcast of SAFE pointer is still a SAFE pointer The upcast of SEQ pointer is still a SEQ pointer if well-aligned

  16. Runtime-Type Info (RTTI) pointer type Store original pointer with type information rttiOf() maps type to object isSubtype() checks if an object’s type is the subtype of another object’s type Downcast only allowed when the object’s type is the subtype of the type which the object is going to cast into Downcast struct Figure { double (*area)(struct Figure * obj); }; struct Circle { double (*area)(struct Figure * obj); int radius; } *c; Struct Figure *ptr = malloc(…); ptr type Figure Figure Circle

  17. CCured transparently modify pointer formats Include metadata in each pointers The pointers cannot be passed to or received from external precompiled library Solutions Manual wrappers Separating metadata from data More overhead for SAFE pointers Modifying data requires Modifying metadata also Compatibility Issue

  18. Tested with several network applications Proved compatibility Much Faster if compared with Valgrind 0.99 ~ 1.87 slowdown factor Benefits from code No relationship between #WILD pointers and performance Execution path matters Experimental Results

  19. Conclusion • CCured • A tool to provide type safety to C language • Separate static contents and dynamic contents • Three kinds of pointers with different check policies • SAFE, SEQ, and WILD • Automatic inference module • Generate CCured-version code from original code • The extension of CCured • Coping with upcasts & downcasts • Reduce WILD pointers • Resolve compatability issues • Separate metadata from original data • Can be used to test real-world system software • Still, some compatibility issues remain

  20. RaceTrack: Efficient Detection of Data Race Conditions via Adaptive Tracking* By Y. Yu et al. Microsoft Research & UC Berkeley In ACM SOSP’05 *Some slides are borrowed from the authors’ presentation

  21. Outline • Motivation • RaceTrack • Algorithm • Adaptive Mechanisms • Managing Data Structure • Improving Warning Analysis • Experimental Results • Conclusion

  22. Motivation • U.S. blackout August 2003* • “the worst outage in North American history” “the bug was unmasked as a particularly subtle incarnation of a common programming error called a "race condition," ” "There was a couple of processes that were in contention for a common data structure, and through a software coding error in one of the application processes, they were both able to get write access to a data structure at the same time," says [GE Energy manager Mike] Unum… "We test exhaustively, we test with third parties, and we had in excess of three million online operational hours in which nothing had ever exercised that bug," says Unum. "I'm not sure that more testing would have revealed that. Unfortunately, that's kind of the nature of software... you may never find the problem.” … *http://www.theregister.co.uk/2004/04/08/blackout_bug_report/

  23. RaceTrack Approach • Run with RaceTrack-modified runtime • No program annotation is needed • No preprocessing is needed • Monitors all the managed code executed (including all managed libraries) • RaceTrack warns about potential races • Actual races need not occur • Analyze warnings for false alarms • Object and field of the offending memory access • Stack trace of the offending thread

  24. Basic Lockset Algorithm • Locking discipline: Accesses to a shared variable are protected by some common lock • Ideas • Each shared variable should be protected with at least one lock • Any violations can be a potential data race

  25. Basic Lockset Algorithm Idea: Infer the locks protecting X MX: locks protecting location X LT: locks being held by thread T When X is accessed by T, MX = MX ∩ LT If MX is empty, then issue a warning

  26. Computing Lockset T1 T2 Lock m1 x = 3; Unlock m1 LT1 = {m1} MX = {m1} LT1 = { } Lock m2 x = 5; Unlock m2 LT2 = {m2} MX = { } and warn Simple, but too many false alarms (e.g. shared reads)

  27. RaceTrack General Idea MX: locks protecting X LT: locks being held by thread T SX: threads concurrently accessing X When X is accessed by T, MX = MX∩ LT SX = … If MX = { } and |SX| > 1, then warn

  28. RaceTrack Algorithm • Each thread T maintains a virtual clock CT • Initially set to 1 when T is created • Each thread T maintains a set of segments {T1, CT1, …, Tn, CTn} • Initially set to { } when T is created • We call this set BT • Intuitively, Ti, CTi is “ordered before” T, CT • Each variable maintains a set of segments {T1, CT1, …, Tn, CTn} • We call this set SX • Intuitively, the threads in SX are concurrently accessing X

  29. RaceTrack Algorithm T1 CT1=1 BT1={} When T1 forks T2: • CT2 = 1 • BT2 = BT1 U { T1, CT1 } • CT1 = CT1 + 1 fork T2 CT2=1 CT1=2 BT2={T1,1} BT1={} T3 fork CT1=2

  30. RaceTrack Algorithm T1 When T1 joins T2: • R = {x ∈ BT2 : x.t ≠ T1} • BT1 = BT1U R U{ T2, CT2 } CT1=1 BT1={} fork T2 CT2=1 CT1=2 BT2={T1,1} BT1={ } join CT1=2 BT1={T2,1}

  31. RaceTrack Algorithm T1 When T accesses X: • W = RemoveBefore(SX, BT) • SX = W U {T,CT} • MX = if W = { } then LTelseMX∩ LT • Issue warning if MX = { } ∧ |SX| > 1 CT1=1 BT1={} fork T2 CT2=1 CT1=2 T1,1 BT2={T1,1} BT1={ } T2,1 join T1,2 X CT1=2 BT1={T2,1} SX={T1,1, T2,1, T1,2} MX={ } SX={T1,1, T2,1} MX={ } SX={T1,1} MX={ } SX={ } MX={ }

  32. Adaptive Threadset Track for what only needed Adaptive Granularity First monitor at object level Change to field-level mode when a potential race is detected Adaptive Mechanisms

  33. Managing Data Structure Threadset table (unmanaged) {T1, T2} {T1, T7} j2: i1 j1 i2 j2 obj Lockset table (unmanaged) MT f1 f2 state { } {L1, L5} i2:

  34. Reducing Overhead Head-Middle-Tail • Monitor only first/middle/last N elements • RaceTrack uses M = 128 • Constant time/space overhead regardless of array size • Monitor at most 3*M elements • Could miss races obj array overhead

  35. Improving Warning Analysis • Multiple stack traces • Continue tracking subsequent accesses once a potential race is detected and reported • Report any further accesses to the same location • Likely to repeat • Ranking • Field-level warnings > object-level warnings • Warnings at Shared-Modify2 > at Shrared-Modify1 • Multiple stack traces > single stack traces

  36. Experimental Results • Used with CLR regression test suite • 1200 (48 distinct) warnings • 50% fault alarms & benign races • Used with real-world large programs • 1.04 ~ 4.10 slowdown factors

  37. Conclusion • RaceTrack • Tool for data race detection • Hybrid approach (lockset & threadset) • Adaptive threadset & granularity • Acceptable(?) overhead • Limitations • Can miss races • Unrepeated races • Blind points in array • Can produce false alarms • Unconventional synchronizations • Benign races

  38. Discussion • Which way to go? • Code-based approach (CCured) • Low runtime overhead (compared to runtime approach) • Recompilation needed • Language-dependent • Dynamic approach with VM (RaceTrack) • Blackbox approach (no code needed) • Runtime overhead • Architecture-dependent • Different strategies for different problems & scenarios? • What about other kinds of bugs (e.g. sematic, protocol) ?

More Related