1/28
Type safety from the ground up.
Chris Hawblitzel(joint work with Jean Yang, Juan
Chen, and Gregory Malecha)
3/28
Answer #1: Type Safety!
source code(e.g. C#)
assembly language
Type checker
Compiler
(but compilers have bugs)
• Catches many common bugs (at compile time or run time):• buffer overflows• double frees• ...
Web scripting: Java, Javascript, .NET, ...Operating systems: SPIN, Singularity, ...
4/28
Example compiler bug (in Bartok)
void F(int[] arr, int i) { if (i <= arr.Length) { // i ≤ arr.Length int j = i - 1; // j < i ≤ arr.Length if (j >= 0) { // 0 ≤ j < i ≤ arr.Length // no bounds check required! arr[j]++; } }}
counterexample: i = -231
j = 231 - 1 j > i
vulnerability: address = &(arr[0]) + 4*j = &(arr[0]) + 4*(231 - 1) = &(arr[0]) - 4
5/28
Answer #2: Typed Assembly Language!(Morrisett et al, POPL 1998)
source code(e.g. C#)
typedassembly language
Type checker
Compiler
• catches type errors in assembly language program
• types for objects, stacks, code pointers, etc.
6/28
Answer #2: Typed Assembly Language!
source code(e.g. C#)
typedassembly language
Type checker
Compiler
(but run-time systems and operating systems have bugs)
run-time system (GC, ...)
OSservices
Linker / loader
7/28
From: Apple Product SecurityDate: Fri, 11 Jul 2008...Available for: iPhone v1.0 through v1.1.4,iPod touch v1.1 through v1.1.4Description: 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.
Example GC vulnerabilities
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...
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...
8/28
Answer #3: Verification!(via automated theorem proving)
source code(e.g. C#)
typedassembly language
Type checker
Compiler
run-time system (GC, ...)
low-level OSservices
Linker / loader
Verifier
9/28
Verve: a verifiably safe OS
Verified Garbage Collector
Verified Threads
Verified InterruptHandlers
Verified DeviceInterface
VerifiedStartup
Verifysafetywith TALchecker
Verifysafety &correctnesswithBoogie/Z3
Boot Loader
x86 Hardware
Small Operating System (C#)
Typed Assembly Language
Bartok
“every assembly language instruction checked for safety”
Kern
elN
ucle
us
10/28
Kern
elN
ucle
us
Small Operating System (C#)
Typed Assembly Language
Bartok
ThreadsGetStackStateResetStackYieldTo
GC HeapAllocObjectAllocVectorGarbageCollectThrow(readField)(writeField)(readStack)(writeStack)
InterruptsFaultHandlerErrorHandlerInterruptHandlerFatalHandler
Device IOVgaTextWriteTryReadKeyboardStartTimerSendEoiPciConfigRead32PciMemSetupPciMemRead32PciMemWrite32DmaBufferDmaPhysicalAddrRdtsc
• Class types, interface types• Array types• Method invocations• Stack frames• Casts, array store checks• ...
Verve: a verifiably safe OS
BUILD!
11/28
Related work
• (Mostly) type-based– House (Hallgren et al)– TALK (Maeda et al)– Typed GC interface (Vanderwaart et al)
• (Mostly) interactive theorem proving– FLINT / certified code (Shao et al)– seL4 (Klein et al)
13/28
Z3: Automated theorem prover
DECIDABLE THEORIESboolean expressions e ::= true | false | !e | e && e | e ==> e | ...linear integer arithmetic e ::= ... | -2 | -1 | 0 | 1 | 2 | e + e | e – e | e <= e | ...bit vector arithmetic e ::= ... | e & e | e << e | ...arrays e ::= ... | e[e] | e[e := e]
UNDECIDABLEquantifiers e ::= ... | forall x.e | exists x.e
14/28
Practical, verified copying collector code
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); call ebp := Mov(eax);... call edi := Mov(0); call edx := Mov(0); 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;
loopEnd: call eax := Lea(esi + 4); call GcWrite(ecx + 4, eax);...
mov edi, 0 mov edx, 0 CopyAndForward$loop:
cmp edx, ebp jae CopyAndForward$loopEnd
automatictranslation
15/28
Memory management
Code,Static fields,GC info
Interrupttable
IO-MMUpagetables
DMAarea
General-purposememory
Nucleusprivatestack
PCItables
Threadcontexts
C#/TALstacks
GCheap
Trusted specification
Untrusted definitions
16/28
Memory management
Code,Static fields,GC info
Interrupttable
IO-MMUpagetables
DMAarea
General-purposememory
Nucleusprivatestack
PCItables
Threadcontexts
C#/TALstacks
GCheap
Defined by (trusted) specification
Untrusted definitions
from-space
to-space
... && (forall i:int::{T(i)} T(i) && Fi <= i && i < Fk && r1[i] != NO_ABS && (IsFwdPtr(gcMem[i + 4]) ==> Pointer(r2, gcMem[i + 4] - 4, r1[i]) && AlignedHeapAddr(i + 4) && word(gcMem[i + 4]))...
17/28
Memory management
Code,Static fields,GC info
Interrupttable
IO-MMUpagetables
DMAarea
General-purposememory
Nucleusprivatestack
PCItables
Threadcontexts
C#/TALstacks
GCheap
Trusted specification
Untrusted definitions
18/28
DMAarea
Memory management
Code,Static fields,GC info
Interrupttable
IO-MMUpagetables
General-purposememory
Nucleusprivatestack
PCItables Thread
contextsC#/TALstacks
GCheap
Trusted specification
Untrusted definitions
IO pagetable
IO-MMU IO pagetable
IO pagetable
... and(ptr, 4095) == 0&&(forall i:int::{T(i)} T(i) && 0 <= i && i < 512 ==> IoPageTableEntry(IomMem[ptr + 8 * i], IomMem[ptr + 8 * i + 4])...
ptr
19/28
Threads and interrupts
Stacks
Interrupt table
Interrupt/error handling
procedure InterruptHandler(stackState:[int]StackState, …); requires StackState[S] == StackRunning; ensures NucleusInv(... StackState[S := StackInterrupted(eax, ebx, …)] [Stack0 := StackRunning] …);
TALcode
0
void KernelMain() { … // Schedule thread, wait for exception or // interrupt ScheduleNextThread();
// CurrentThread received exception, // interrupt, or exited voluntarily uint cid = CurrentThread; Thread t = threadTable[cid]; …}
20/28
Micro-benchmarks
Verve functionality
Cycles
Round-trip yield
98
Round-tripwait + signal
216
Comparisons Cycles
L4 (IPC) 224
SeL4 (IPC) 448
Singularity (yield) 2156
Linux (yield) 2390
Windows (yield) 3554
21/28
Size of code, specification
Copying Mark-sweepSpecification Boogie lines 1517Verified Boogie lines 5189 5734
x86 instructions 1747 1859
Boogie verification• ~1 person-year work• Boogie/Z3 runs in ~10 minutes
3x code
C# code (100% safe) 35,000
CODE!
22/28
Building VerveVerifie
dKernel.cs
Nucleus.bpl (x86) Kernel.obj (x86)
Compiler
Specification
Boot loader
TAL checkerBoogie/Z3
Verve.iso
Translator /Assembler
Linker /ISO generator
DEMO!
23/28
Bug Whose fault?
InitializeGC: clobber ebp
AllocObject: off-by-4
debugger stub
linking GC tables
String GC descriptor
Bugs in the trusted computing base
Specification
Boot loader
TAL checkerBoogie/Z3
Translator /Assembler
Linker /ISO generator
Specification
Specification
Debugger stub
Windows/Bartok
TAL checker
Specification TAL checker
TAL checkerLinker / ISO gen
Specification
procedure InitializeGc(); requires SMemRequireRA(...); requires MemInv(...); ... modifies Eip, eax, ..., ebp, esp; ensures WellFormed(toAbs); ensures ebp == old(ebp);
procedure AllocObject(...); requires isStack(S); requires NucleusInv(...); ... ensures eax == 0 || Pointer(toAbs, eax - 4, abs); ensures ebp == old(ebp);
Debugger stub
Code,Static fields,GC info
public sealed class String : ...{ private int m_arrayLength; private int m_stringLength; internal char[] m_chars; ...
24/28
Towards foundational Verve(Gregory Malecha)
Nucleusspecification TAL checker
Well-typed registersWell-typed objects
Well-typed stack frames...
Specification for valuesSpecification for objects
Specification for stack frames...
Goal: mechanizedconnection
25/28
Unified invariant
Nucleus invariant+ TAL well-typedness
... && (forall i:int::{T(i)} T(i) && Fi <= i && i < Fk && r1[i] != NO_ABS && (IsFwdPtr(gcMem[i + 4]) ==> Pointer(r2, gcMem[i + 4] - 4, r1[i]) && AlignedHeapAddr(i + 4) && word(gcMem[i + 4]))...
Inductive WellTypedIns : CodeType -> Instr -> CodeType -> Prop :=| Tmov : forall st st' from to ty, opdType st from ty -> regTyUpd st to ty = st' -> WellTypedIns st (Imov to from) st‘| ...
26/28
Unified invariant MOV edx, esi
CALL ...Nucleus...
MOV edx, esi
CALL ...Nucleus...
MOV esi, eax
Nucleus invariant+ TAL well-typedness
TAL instruction = 1 stepNucleus call = 1 stepEach step maintains unified invariant
27/28
Progress on “foundational Verve”• Approach so far (roughly)– Mechanically translate Boogie Spec into Coq– Specify “step” relation in Coq– Boogie/Z3 proofs become Coq axioms– (Try to!) prove invariant holds after each step
• We’re not done yet, but we’ve found spec bugs
procedure YieldTo(s:int, ...); requires ecx == s; requires (StackState[s] == StackRunning && ...) || (StackState[s] == StackYielded(...) && ...) || (StackState[s] == StackInterrupted(...) && ...) || (StackState[s] == StackEmpty && ...) || (!isStack(s));
implementation YieldTo(s:int, ...){ if (ecx >= ?NumStacks) { ... call debugBreak(); } ...}