Automated Verification of Practical Garbage Collectors Chris Hawblitzel (Microsoft Research) Erez Petrank (Technion) 1/17

Download Report

Transcript Automated Verification of Practical Garbage Collectors Chris Hawblitzel (Microsoft Research) Erez Petrank (Technion) 1/17

Automated Verification of
Practical Garbage Collectors
Chris Hawblitzel (Microsoft Research)
Erez Petrank (Technion)
1/17
Downloading safe code
JIT compiler
Java bytecode / .NET bytecode /
JavaScript / ActionScript
Web browser
run-time system
x86
exception
handling
threads
garbage
collector
2/17
GC vulnerabilities
MS07-057: Cumulative security update for Internet Explorer
Date: October 2007
...Internet Explorer 6 may exit with an access violation when the JavaScript
garbage collector runs and you have dynamically removed a TBODY, THEAD,
or TFOOT HTML tag from a table in Windows XP...
Mozilla Firefox Bug in JavaScript Garbage Collector Lets Remote Users Deny Service
Advisory: Mozilla Foundation Security Advisory
Date: Apr 16 2008
A remote user can create specially crafted HTML that, when loaded by the target
user, will trigger a flaw in the JavaScript garbage collector code and cause the target
user's browser to crash. ... The vendor indicates that similar crashes have been
exploitable in the past, so arbitrary code execution may be possible...
From: Apple Product Security
Date: Fri, 11 Jul 2008
...
Available for: iPhone v1.0 through v1.1.4,iPod touch v1.1 through v1.1.4
Description: A memory corruption issue exists in JavaScriptCore's handling
of runtime garbage collection. Visiting a maliciously crafted website may
lead to an unexpected application termination or arbitrary code execution.
This update addresses the issue through improved garbage collection.
3/17
GC verification
Earlier work
New work: realistic GCs
 Small GCs
 Runs real Bartok-compiled C#
• real memory layouts
 Interactive
proofs
 Automated verification
• annotated GCs in BoogiePL
• assemble BoogiePL to x86
• specifications in BoogiePL
• Z3 automated SMT prover
4/17
Challenges to automated verification
1. Reasoning about graphs
2. Undecidable logic
3. Large formulas
5/17
Outline
• Background
• Simple verified GC
– miniature mark-sweep collector
– quantifiers
• Practical verified GCs
6/17
Mark-sweep and copying collectors
abstract
A
graph
(root)
mark-sweep
copying from
A
C
C
B
copying to
A
A
B
B
C
B
7/17
Garbage collector properties
A
(root)
B
C
• Verified:
– isomorphism
(McCreight, Shao et al 2007)
– effectiveness
– after gc, unreached objects reclaimed
• Not verified:
– Termination
– Efficiency
A
C
B
8/17
Verifying Mark
procedure Mark(ptr:int)
requires GcInv(Color, $toAbs, $AbsMem, Mem);
requires memAddr(ptr) && T(ptr);
requires $toAbs[ptr] != NO_ABS;
modifies Color;
ensures GcInv(Color, $toAbs, $AbsMem, Mem);
ensures (forall i:int::{T(i)} T(i) && !Black(Color[i]) ==> Color[i] == old(Color)[i]);
ensures !White(Color[ptr]);
{
if (White(Color[ptr])) {
Color[ptr] := 2; // make gray
call Mark(Mem[ptr,0]);
call Mark(Mem[ptr,1]);
Color[ptr] := 3; // make black
}
}
9/17
Verifying Mark: abstract <--> concrete
procedure Mark(ptr:int)
requires GcInv(Color, $toAbs, $AbsMem, Mem);
requires memAddr(ptr) && T(ptr);
requires $toAbs[ptr] != NO_ABS;
modifies Color;
ensures GcInv(Color, $toAbs, $AbsMem, Mem);
ensures (forall i:int::{T(i)} T(i) && !Black(Color[i]) ==> Color[i] == old(Color)[i]);
ensures !White(Color[ptr]);
{
$AbsMem
if (White(Color[ptr])) {
A
B
Color[ptr] := 2; // make gray
call Mark(Mem[ptr,0]);
call Mark(Mem[ptr,1]);
$toAbs
$toAbs
Color[ptr] := 3; // make black
Mem
}
forall i:int ::{T(i)} T(i) && memAddr(i) ==> A
B
}
$toAbs[Mem[i, field]]
== $AbsMem[$toAbs[i], field]
10/17
Verifying Mark: no black-->white
procedure Mark(ptr:int)
requires GcInv(Color, $toAbs, $AbsMem, Mem);
requires memAddr(ptr) && T(ptr);
requires $toAbs[ptr] != NO_ABS;
modifies Color;
ensures GcInv(Color, $toAbs, $AbsMem, Mem);
ensures (forall i:int::{T(i)} T(i) && !Black(Color[i]) ==> Color[i] == old(Color)[i]);
ensures !White(Color[ptr]);
{
if (White(Color[ptr])) {
Color[ptr] := 2; // make gray
call Mark(Mem[ptr,0]);
call Mark(Mem[ptr,1]);
Color[ptr] := 3; // make black
}
forall i:int::{T(i)} T(i) && memAddr(i) ==>
}
Black(Color[i]) ==> !White(Color[Mem[i,field]])
11/17
Quantifiers and triggers
procedure Mark(ptr:int)
requires GcInv(Color, $toAbs, $AbsMem, Mem);
requires memAddr(ptr) && T(ptr);
explicit introductions of T(...)
requires $toAbs[ptr] != NO_ABS;
to provoke quantifier instantiations
modifies Color;
ensures GcInv(Color, $toAbs, $AbsMem, Mem);
ensures (forall i:int::{T(i)} T(i) && !Black(Color[i]) ==> Color[i] == old(Color)[i]);
ensures !White(Color[ptr]);
“trigger” quantifier instantiation
{
i =e when T(e) seen
if (White(Color[ptr])) {
Color[ptr] := 2; // make gray (equivalent
“Color := function:
Color[ptr := 2];”
T is to
a dummy
call Mark(Mem[ptr,0]);
T(e) <==> true
call Mark(Mem[ptr,1]);
Color[ptr] := 3; // make black
}
forall i:int::{$toAbs[i]}{$toAbs’[i]}
}
also trigger on old, new $toAbs
...
$toAbs[i] != NO_ABS
(and split $toAbs into “regions”)
==> $toAbs[i] == $toAbs’[i] ...
12/17
Outline
• Background
• Simple verified GC
• Practical verified GCs
– Object layouts, GC tags, static data, stacks, interior pointers, ...
– Mark-sweep collector
• Free list + cache
• Mark stack
• Table of color bits (2 bits per color)
– Copying collector
• Simple (non-generational) 2-space Cheney queue algorithm
– Mutator-GC interface:
• Initialize
• read, write
• AllocateObject, AllocateString, AllocateVector, AllocateArray
13/17
procedure CopyAndForward($ptr:int, $_tj:int)
requires ecx == $ptr;
requires CopyGcInv(...);
requires Pointer($r1, $ptr, $r1[$ptr]);
...
{
call edx := GcRead(ecx + 4);
esp := esp - 4; call GetSize($ptr, edx, $r1, $r1);
ebp := eax;
...
edi := 0;
automatic
edx := 0;
translation
loop:
assert 4 * edi == edx;
assert CopyGcInv(...);
...
if (edx >= ebp) { goto loopEnd; }
call copyWord($ptr, $_tj, esi, edi, ebp);
call edi := Add(edi, 1);
call edx := Add(edx, 4);
goto loop;
Practical, verified
copying collector code
mov edi, 0
mov edx, 0
CopyAndForward$loop:
cmp edx, ebp
jae CopyAndForward$loopEnd
loopEnd:
call eax := Lea(esi + 4);
call GcWrite(ecx + 4, eax);
...
14/17
Performance (2 of 10 benchmarks)
execution time
(seconds)
1.8
VC
1.6
Asmlc
VMS
execution time
(seconds)
GEN
250
MS
VC
Bartok
VMS
GEN
MS
200
1.4
1.2
150
1
0.8
100
0.6
0.4
50
0.2
0
0
0
50
100
150
200
available memory (MB)
0
500
1000
1500
2000
available memory(MB)
caveat: Bartok collectors support more features (e.g. threads, pinning) than verified collectors
15/17
Code size, verification time
BoogiePL
lines of code
x86
instructions
Time to
verify
(seconds)
Trusted defs
546
Shared code
779
177
12
Copying
2398
802
115
Mark-sweep
3038
865
70
lines of proof script: 0
16/17
Conclusions
http://www.codeplex.com/singularity
Source Code: base/Imported/Bartok/runtime/verified/GCs
• Verified run-time status: two practical GCs
1. Reasoning about graphs ==> isomorphism
2. Undecidable logic ==> triggers
3. Large formulas ==> modern automated prover (Z3)
• Original mutator-GC interface specification had
two bugs, so:
– Copying collector:
• crashed 1st time (spec bug: Initialize not asked to save ebp)
• crashed 2nd time (spec bug: preheader vs. header confusion)
• worked 3rd time
– Mark-sweep (with corrected spec): worked 1st time
17/17