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.
Download
Report
Transcript 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.
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
Motivation
How to verify the safety & correctness
properties of low-level system software?
System
Software
Java (JML)
Cyclone
…
CCured
C# (Spec #)
TAL
Vanilla C & C++ & Assembly?
Hardware
Verifying C & Assembly?
Many challenges …
This talk: how to specify/verify low-level stackbased 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
Problems – call/return
void f(){
void h(){
h();
return;
Stacks are hidden!
return;
}
}
f:
pc
...
sw
$ra, -4($fp)
h:
jal h
pc
ct: lw
$ra, -4($fp)
;; $ra contains ct
pc
jr $ra
...
jr
$ra
Does f use the right return addr.?
Problems – setjmp/longjmp
jmp_buf env = …;
int rev(int x){
void cmp0(int x,jmp_buf env){
f0
pc
f2
if (setjmp(env) == 0){
pc
cmp0(x, env);
return 0;
cmp1(x, env);
}
void cmp1(int x,jmp_buf env){
env cannot outlive the stack frame of rev !
f1
}else{
if (x == 0)
pc
env
return 1;
longjmp(env, 1);
f0
else
}
…
}
f2
…
sp
f1
…
return;
}
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
No ’s!
single CAP0 framework!
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
f1:
(data heap) H
I1
f2:
I2
f3:
I3
…
(code heap) C
::={f I}*
0
1
2
…
pc
r1 r2 r3 … rn
(register file) R
(state) S::=(H,R)
(program) P::=(C,S,pc)
addu …
lw …
sw …
…
j f
(instr. seq.) I
Invariant-Based Verification
S0
c1
S1
c2
S2
c3
…
cn
Initial condition: Inv(S0)
Progress:
if Inv(S), then S’. S c S’.
Preservation:
if Inv(S) and S c S’, then Inv(S’).
Sn
Program Specifications
(spec) ::= {f a}*
a1
f1:
a2
f2:
a3
f3:
(data heap) H
I1
I2
I3
…
(code heap) C
::={f I}*
0
1
2
…
pc
r1 r2 r3 … rn
(register file) R
(state) S::=(H,R)
(program) P::=(C,S,pc)
addu …
lw …
sw …
…
j f
(instr. seq.) I
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
Specifications
Challenges
f uses the “right” return addr.?
f: {(p
{$ra
g0)}
n …}
0, =
Hoare triple {p} f {q}?
...
In different basic blocks!
sw
jal h
SCAP specifications: (p, g) g
p: State Prop
g: State State Prop
0
ct: {(p1, g1)}
g1
g0 S S’ S’.$ra = S.$ra …
$ra, -4($fp)
lw
$ra, -4($fp)
...
jr
$ra
{$ra = n …}
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
g0
g1 p
3
p4
jr $ra
…
jr $ra
g4
p2
jal h
jr $ra
g3
g2
SCAP : Stack Invariant
Always safe to return?
S0
S1.$ra (S1.$ra))=(p1, g1) p1 S1
g1
p2
S1
S2
g0 S0 S1 g1 S1 S2
g0 S0 S1 g1 S1 S2 g2 S2 S3
g0
p1 jr $ra
g0 S0 S1
S2.$ra (S2.$ra)=(p2, g2) p2 S2
p0
g2
p3
S3
g3
S3.$ra (S3.$ra)=(p3, g3) p3 S3
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
S0
p0
g0
p1 jr $ra
g1
p2
S1
S2
g2
p3
S3
Invariant:
g3
p S n.WFST(n, g S, )
Logical control stack
SCAP : Invariant Preservation
Inv(S):
p S n.WFST(n, g S, )
c
S
p S
n.WFST(n,g S,)
S’
p’ S’
n.WFST(n,g’S’,)
SCAP: call
p S WFST(n, g S, )
p
S
g
p0
p1 jr $ra
g1
n
p0 S0 WFST(n+1, g0 S0, )
p0
S0
g0
S1
n+1
jal f
p S g0 S0 S1 p1 S1
g1
n
S2
p S p0 S0
p1 jr $ra
g0
S1
S2
g0 S0 S1 S0.$ra = S1.$ra
p S g0 S0 S1 g1 S1 S2 g S S2
SCAP: ret
p S WFST(n, g S, )
n
p1
S
g1
n-1
p1 S1 WFST(n-1, g1 S1, )
p
g
S1
jr $ra
p S g S S1
p1
g1
n-1
SCAP: tail call
p S WFST(n, g S, )
p
S
p0
S0
p0
g0
g0
g
n
p0 S0 WFST(n, g0 S0, )
jf
jr $ra
n
jr $ra
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, )
p
S
g
p0
p1 jr $ra
g1
n
p0 S0 WFST(n+1, g0 S0, )
p0
S0
g0
S1
n+1
jal f
p S g0 S0 S1 p1 S1
g1
n
S2
p S p0 S0
p1 jr $ra
g0
S1
S2
g0 S0 S1 S0.$ra = S1.$ra
p S g0 S0 S1 g1 S1 S2 g S S2
Generalization: Stack unwinding/cutting
Multi-ret
p1
p
g
g1
jr ra
+
Tail-call
p1
p
g1
g
jr ra
p1
p
g
jr ra
g1
Example: setjmp/longjmp
jmp_buf env = …;
void cmp0(int x,jmp_buf env){
int rev(int x){
if (setjmp(env) == 0){
cmp0(x, env);
return 0;
cmp1(x, env);
}
void cmp1(int x,jmp_buf env){
if (x == 0)
}else{
longjmp(env, 1);
return 1;
else
}
return;
}
}
Further extensions
switch
call
switch
switch
switch
coroutines
ret
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
Function call;
tail-call optimization
SCAP
Exceptions: Stack-unwinding
SCAP-I, EUCAP
Exceptions: Stack-cutting
SCAP-II, ECAP
Weak-continuation
setjmp/longjmp
SCAP-II
Coroutines (w. function call)
CAP-CR (SCAP-CR)
Threads
FCCAP
CAP0: the generic framework
Inference rules are lemmas in CAP0