SAFE KERNEL EXTENSIONS WITHOUT RUN-TIME CHECKING George C. Necula Peter Lee Carnegie Mellon U Overview • Paper presents a technique allowing kernels to check extension safety – Code receiver defines a set of safety rules that guarantee safe behavior of programs, – Code producer creates a formal safety proof that its code adheres to the safety rules – Code receiver uses a simple and fast proof validator to check that the code is safe Starting Idea Code Producer Untrusted code Code Consumer Verifies safety of code • Good idea but … Starting Idea Code Producer Untrusted code Code Consumer Verifies safety of code • Formally proving the safety of untrusted code requires a large amount of effort Shift the burden to the producer Code Producer Untrusted code + Safety Proof Proves safety of its code • Works better Code Receiver Validates proof Proof-carrying code • Code producer must establish and prove the safety of the code – Attaches proof to code • Code consumer only has to validate the proof – Much simpler task Advantages • Code producer does most of the validation work • Code consumer does not care how the proofs are constructed • PCC programs are tamperproof – Changing the code voids the proof • No cryptography • No trusted third parties • Errors are detected before code is run Difficulties • How to encode the formal proof? • How to check the proof? – Not an easy task • How to relate the proof with the program? Implementation • Basic elements: – Formal specification language used to express the safety policy – Formal semantics of the language used by the untrusted code – Language used to express the proofs – Algorithm for validating the proofs – Method for generating the safety proofs Formal Specification Language • Expresses the safety policy of the receiver • Uses first-order predicate logic extended with predicates for type safety and memory safety Formal semantics of language • Describes the language used by the untrusted code – A logic relating programs to specifications • Untrusted code is DEC Alpha machine code – Was at that time the fastest microprocessor Proof language • Variant of Edinburgh Logical Framework (LF) – Essentially a typed lambda calculus – Can easily encode a wide variety of logics, including higher-order logics Proof validation • Simple LF type checker • Basic tenet of LF is that proofs are represented as expressions and predicates as types – In order to check the validity of a proof we only need to typecheck its representation Generating safety proofs • Uses a theorem prover – First, the code is scanned by the same verification generator that the consumer uses – Then the predicate is submitted to a theorem prover that attempts to prove that predicate – In case of success, prover emits an LF representation of the proof Application • Machine code implementation of network packet filters • Safety policy was focused on finegrained memory safety • Safety proofs were smaller than 800 bytes • Required no more than 3ms on a DEC Alpha to be validated. More details Observe that all four filters are very small Run time • Average per packet runtime of the four PCC packet filters • Compared with – BSD Packet Filter Interpreter (will be slow!) – Using software fault isolation – Using a safe subset of Modula 3 plus the VIEW extension for safe pointer casting BFI is worst! Conclusion • PCC allows server or kernel to interact safely with untrusted code • PCC has no runtime overhead for receiver • Safety policies are defined by receiver – Much more flexible Too bad that safety proofs are so hard to construct!
© Copyright 2026 Paperzz