Frontiers of Systems Programming

formal verification of systems code

Testing can show that code works on the cases you tried, but it can never show that no bad case exists - there are too many inputs to try them all. Formal verification of systems code takes a different route: instead of running the code on examples, you write a precise mathematical specification of what the code should do, and then construct a proof - checked by a machine - that the code meets that specification for every possible input. It is the difference between 'I tested it a lot' and 'I proved no input can break this property.'

Concretely, you state the specification in a formal logic, model the program's behavior precisely, and use a proof assistant or solver to verify that the implementation satisfies the spec. The proof is machine-checked: a small, trusted checking program confirms every logical step, so you are not trusting a human's claim that the argument is airtight. This is enormously laborious - the seL4 microkernel famously required person-years of proof effort for a few thousand lines of C - but the payoff is a guarantee no amount of testing can give: for the stated properties, there are no bugs of that kind, full stop. Where it is applied, it tends to be the most critical, smallest, most reused code: a microkernel, a hypervisor core, a cryptographic routine, a compiler.

It matters because for a handful of foundational components, 'proven correct' is a real and rare achievement. But be scrupulously honest about what it does and does not guarantee. The proof only covers the properties you specified - verify functional correctness and you have said nothing about timing or power side-channels unless you also specify those. The proof assumes a model of the hardware and the assumptions baked into it (the compiler, the hardware behaving to spec, no faults the model ignores); if reality violates an assumption, the guarantee does not hold. And a flawed or incomplete specification can be proven satisfied while the system still does the wrong thing - 'proven correct' means 'proven to match this spec under these assumptions,' never 'guaranteed to be free of all problems.'

spec: for all inputs, the kernel never writes outside a thread's permitted memory proof: a machine-checked derivation that the C implementation satisfies that spec => tested code shows 'works on cases I tried'; verified code shows 'no input violates this property' (but only THIS property, and only if the hardware/compiler assumptions hold)

Verification proves an implementation meets a precise spec for all inputs - but only for the stated properties, and only under the model's assumptions.

'Proven correct' is narrower than it sounds: the proof covers only the specified properties under explicit assumptions (a correct compiler, hardware obeying its model, no faults outside the model). A wrong or incomplete spec can be 'satisfied' by a system that still misbehaves, and properties you did not specify - like timing side-channels - are simply not covered.

Also called
machine-checked proofproven correct形式化驗證機器檢驗證明