280 likes | 471 Views
Modular Verification of Assembly Code with Stack-Based Control Abstractions. Xinyu Feng Yale University Joint work with Zhong Shao, Alexander Vaynberg, Sen Xiang and Zhaozhong Ni. C# (Spec #). Java (JML). …. Cyclone. CCured. TAL. Motivation.
E N D
Modular Verification of Assembly Code with Stack-Based Control Abstractions Xinyu Feng Yale University Joint work with Zhong Shao, Alexander Vaynberg, Sen Xiang and Zhaozhong Ni
C# (Spec #) Java (JML) … Cyclone CCured TAL Motivation How to verify the safety & correctness properties of low-level system software? System Software Vanilla C & C++ & Assembly? Hardware
Verifying C & Assembly? Many challenges … This talk:how to specify/verify low-level stack-based control flows? • How to formulate the stack invariants? • How to design a compositional program logic? Previous work does not apply! • Hoare-Logic done at high-level: no explicit stacks! • TAL & Proof-Carrying Code: • Mostly use continuations & CPS-based reasoning • Too general to distinguish different stack abstractions
f: ... sw $ra, -4($fp) h: jal h ;; $ra contains ct ct: lw $ra, -4($fp) jr $ra ... jr $ra Problems – call/return void f(){ void h(){ h(); return; return; } } Stacks are hidden! pc pc pc Does f use the right return addr.?
env cannot outlive the stack frame of rev ! f0 f1 f2 f0 … f2 … f1 Problems – setjmp/longjmp jmp_buf env = …; void cmp0(int x,jmp_buf env){ cmp1(x, env); } int rev(int x){ if (setjmp(env) == 0){ cmp0(x, env); return 0; }else{ return 1; } } pc pc void cmp1(int x,jmp_buf env){ if (x == 0) longjmp(env, 1); else return; } pc env sp …
Our Contributions A simple program logic (SCAP) for modular verification of (1) compiled C code & (2) manually-written assembly code All systems are lemma libraries built on a single CAP0 framework! No ’s!
Outline of This Talk • Motivations and contributions • SCAP logic for verifying function call/return • Basic framework • Specifications • Stack-invariant • Instruction rules (to enforce the invariant) • Generalizations for complicated controls • Implementation & applications
The Machine (data heap) H f1: I1 addu … lw … sw … … j f pc 0 1 2 … f2: I2 r1 r2 r3 … rn f3: I3 (register file) R … (code heap) C (state) S ::=(H,R) (instr. seq.) I ::={fI}* (program) P ::=(C,S,pc)
c1 c2 c3 cn … S0 S1 S2 Sn Invariant-Based Verification Initial condition:Inv(S0) Progress: if Inv(S), then S’. S c S’. Preservation: if Inv(S) and S cS’, then Inv(S’).
a1 a2 a3 Program Specifications (spec) ::={fa}* (data heap) H f1: I1 addu … lw … sw … … j f pc 0 1 2 … f2: I2 r1 r2 r3 … rn f3: I3 (register file) R … (code heap) C (state) S ::=(H,R) (instr. seq.) I ::={fI}* (program) P ::=(C,S,pc)
The SCAP Program Logic • the form of specification “a” • the invariant (based on the spec. ) • the proof obligations • Instruction rules for call, ret, tail call, …
Outline of This Talk • Motivations and contributions • SCAP logic for verifying function call/return • Basic framework • Specifications • Stack-invariant • Instruction rules (to enforce the invariant) • Generalizations for complicated controls • Implementation & applications
{$ra = n …} g0 g1 {$ra = n …} Specifications • Challenges • f uses the “right” return addr.? • Hoare triple {p} f {q}? • In different basic blocks! f: ... sw $ra, -4($fp) jal h ct: lw $ra, -4($fp) ... jr $ra {(p0, g0)} • SCAP specifications: (p, g) • p: State Prop • g: State State Prop {(p1, g1)} g0 S S’ S’.$ra = S.$ra …
Program Spec. and Code Pointers • Program Specification ::= {f1(p1,g1), …,fn(pn,gn)} • “safe” to return (jr $ra): • $radom() ($ra)=(p,g) • p holds at the time of return p0 p1 jal f p2 jal h g2 g0 g1 p3 jr$ra g3 p4 jr $ra … g4 jr $ra
SCAP : Stack Invariant Always safe to return? p0 S0 g0 p1 jr $ra g0 S0S1 S1.$ra (S1.$ra))=(p1, g1) p1S1 S1 g1 p2 S2 g0 S0S1 g1 S1S2 S2.$ra (S2.$ra)=(p2, g2) p2S2 g2 p3 S3 g0 S0S1 g1 S1S2 g2 S2S3 S3.$ra (S3.$ra)=(p3, g3) p3S3 g3 Logical control stack
SCAP : Stack Invariant WFST(n, g0 S0, ) S1. g0 S0 S1 p1,g1. (S1.$ra)=(p1, g1) p1 S1 WFST(n-1, g1 S1, ) WFST(0, g0 S0, ) S1. g0 S0 S1 Invariant: p S n.WFST(n, g S, ) p0 S0 g0 p1 jr $ra S1 g1 p2 S2 g2 p3 S3 g3 Logical control stack
c S p S n.WFST(n,g S,) p’ S’ n.WFST(n,g’S’,) SCAP : Invariant Preservation • Inv(S): p S n.WFST(n, g S, ) S’
SCAP: call p S WFST(n, g S, ) p0 S0 WFST(n+1, g0 S0, ) p p0 p0 S S0 g0 g0 p1 n+1 p1 g jr $ra jr $ra g1 g1 S1 jal f S1 n n S2 S2 … … p S p0 S0 g0 S0 S1 S0.$ra = S1.$ra p S g0 S0 S1 p1 S1 p S g0 S0 S1 g1 S1 S2 g S S2
SCAP: ret p S WFST(n, g S, ) p1 S1 WFST(n-1, g1 S1, ) p n p1 p1 S g S1 g1 g1 jr $ra n-1 n-1 … … p S g S S1
SCAP: tail call p S WFST(n, g S, ) p0 S0 WFST(n, g0 S0, ) p p0 p0 S S0 g0 g0 g jr $ra jr $ra j f n n S1 S1 … … p S p0 S0 p S g0 S0 S1 g S S1
Outline of This Talk • Motivations and contributions • SCAP logic for verifying function call/return • Basic framework • Specifications • Stack-invariant • Instruction rules (to enforce the invariant) • Generalizations for complicated controls • Implementation & applications
SCAP: call p S WFST(n, g S, ) p0 S0 WFST(n+1, g0 S0, ) p p0 p0 S S0 g0 g0 p1 n+1 p1 g jr $ra jr $ra g1 g1 S1 jal f S1 n n S2 S2 … … p S p0 S0 g0 S0 S1 S0.$ra = S1.$ra p S g0 S0 S1 p1 S1 p S g0 S0 S1 g1 S1 S2 g S S2
Multi-ret p1 p1 p p g1 g1 jr ra jr ra g g + Tail-call p1 p g1 g jr ra Generalization: Stack unwinding/cutting
Example: setjmp/longjmp jmp_buf env = …; void cmp0(int x,jmp_buf env){ cmp1(x, env); } int rev(int x){ if (setjmp(env) == 0){ cmp0(x, env); return 0; }else{ return 1; } } void cmp1(int x,jmp_buf env){ if (x == 0) longjmp(env, 1); else return; }
Further extensions call switch switch switch switch switch ret switch switch switch coroutines coroutines w. functions calls
Implementation & Applications • Coq implementation • Encoding of machine (370 lines) • Syntax & Operational semantics • Encoding of CAP0 framework/SCAP systems (1800L) • Inference rules & Soundness proof • Certified programs w. proofs (10,000+ L) • malloc/free • …… • garbage collectors [McCreight et al 06]
Summary • SCAP-family logics as lemmas • CAP0: the generic framework • Inference rules are lemmas in CAP0