Microkernels and their verification: seL4 - Timothy Bourke Systèmes et réseaux-ENS DI L3, 2017-2018 - DI ENS
←
→
Page content transcription
If your browser does not render page correctly, please read the page content below
Microkernels and their verification: seL4 Timothy Bourke Systèmes et réseaux—ENS DI L3, 2017-2018 1 / 52
Why are operating systems used? ‘Operating system’ in the narrow sense: i.e., the kernel, and not the user interface libraries, window manager, minesweeper, etcetera. For sharing • memory, • computation time and processors, and, • input/output devices (keyboards, disks, graphics). For abstraction (a base for building bigger systems): • application portability (i.e., hardware independence, device drivers); • common services (e.g., file systems, access control); • concurrency and communication— • with protection, • and access control (for untrusted users and applications). Lots of low-level details and bookkeeping! 2 / 52
Protection modes: overview A kernel is more than just a standard library of code. It works closely with hardware. It controls other processes and manages their interactions. Most processors have protection modes that They control access to the processor and core hardware—interrupt controllers, memory management units, timers. The kernel runs in privileged mode (kernel mode): • It can change the address spaces of other processes; • It can configure and respond to interrupts (i.e., preempt); • If it misbehaves, the whole system can crash. Other code runs in user mode: • under an illusion of an isolated and flat address space; • using system calls to setup interaction with hardware and other processes. • If it misbehaves, the kernel can recover. 3 / 52
Bad memory access in protected mode Address incorrectly reference instruction address IRQL used for access 0 = read, 1 = write Cause: This Stop error message usually occurs during instal- lation when there was an attempt in kernel mode to touch pageable memory at too high a process internal request level (IRQL). Typically, this error occurs when a driver uses an in- correct memory address. Other possible causes of this er- ror include an incompatible device driver, a general hardware problem, or incompatible software. http://support.microsoft.com/kb/314063 5 / 52
Protection modes: switching mode Interrupts • User-mode processes make system calls by loading arguments into registers and triggering a software interrupt. • Device interrupts (incl. timers) also trigger the kernel. Traps: Execute an illegal instruction to trigger a CPU trap. Special instructions • Modern Intel processors have sysenter and sysexit instructions. • AMD processors have syscall and sysret instructions. Alternatives • No protection: small embedded systems. • Type-safe OSes: e.g., Singularity . [?] 6 / 52
How much code should run in privileged mode? • The minimum. “But it must be fast and easy to write!” Monolithic kernels 7 / 52
How much code should run in privileged mode? • The minimum. “But it must be fast and easy to write!” Monolithic kernels • The absolute minimum. 7 / 52
How much code should run in privileged mode? • The minimum. “But it must be fast and easy to write!” Monolithic kernels • The absolute minimum. “But it can be fast and it is a better architecture for building systems!” Microkernels 7 / 52
How much code should run in privileged mode? • The minimum. “But it must be fast and easy to write!” Monolithic kernels (Windows, Linux, *BSD, MacOS) • The absolute minimum. “But it can be fast and it is a better architecture for building systems!” Microkernels (Minix, EROS, L4, seL4) 7 / 52
Monolithic kernels: Windows Windows NT 4 architecture (1996) 8 / 52
Monolithic kernels: Linux 9 / 52
Hardware Hardware Microkernels • Kernel provides no services, only mechanisms • Strongly dependent on fast IPC and exception handling COMP9242 S2/2013 5 ©2012 Gernot Heiser, UNSW/NICTA. Distributed under Creative Commons Attribution License 10 / 52
Pr" U"DBWDB_Dx%&##%2D"# / ª¥²N² ¡g¢ ¯¶¥¡ 2D1Pr)2$2)B&"2PUD)of 81"uÙN81F:N8D2 ¦ ¡g¢ ³¥¨¥¡ ²N´rµ$¬«.N,4 ¡g¢ £r©¥¡ "#)B lí "#)7C"PhDB_Dx"2E#S%UC82S%LT&BdS/ ¦ ¡g¢ §g¯¶® ±¥· ¡g¢ §r£¥¤ •black=i-cache L2 (a#8 D4/ ¦ ¡Y¢ ¡r³¥® •^white=other causes D1Pr"#3&D &"#S%88D:"f&>DC"Ph>e$+Yf7) ^:And that 81"U!there 2))"Dis no 82Dfundamental reason :))"#)E#CDwhy >!D"Ta microkernel, if • >T S3ÕB&Dx: )| / T&5dproperly 12))S3B&DÖdesigned, 8#8DS%~DS%&4cannot 3(D .+88Dbe L2fast. % M&81Cte$+gf#7)(TN8))BWoD;"P6!"81S%&o:N8 %#+y878D U7I%|7d:LT&5
Key microbenchmark: round-trip IPC time in cycles Name Year Processor MHz Cycles µs Original 1993 i486 50 250 5.00 Original 1997 Pentium 160 121 0.75 L4/MIPS 1997 R4700 100 86 0.86 L4/Alpha 1997 21064 433 45 0.10 Hazelnut 2002 Pentium 4 1,400 2,000 1.38 Pistachio 2005 Itanium 2 1,500 36 0.02 OKL4 2007 XScale 255 400 151 0.64 NOVA 2010 Core i7 (Bloomf eld) 32-bit 2,660 288 0.11 seL4 2013 Core i7 4770 (Haswell) 32-bit 3,400 301 0.09 seL4 2013 ARM11 532 188 0.35 seL4 2013 Cortex A9 1,000 316 0.32 Table 1: One-way IPC cost of var ious L4 kernels. The context-switch friendliness of the hardware is an important factor. [?] 12 / 52
200 mechanisms Microkernels: – L4 performance V2 API: 7 system calls plus L4 with cache flush a few kernel protocols 100 L4 – reduced IPC complexity – 15 kLOC(?) x86 assembler raw copy 0 0 2000 4000 6000 Message Length [B] COMP9242 S2/2013 22 ©2012 Gernot Heiser, UNSW/NICTA. Distributed under Creative Commons Attribution License 13 / 52
L4 family of microkernels On µ-Kernel Construction—Liedtke, SOSP 1995 Feature inclusion based on essential functionality and not performance • Address spaces (page-based virtual memory) • Threads • IPC: Inter-Process Communication (i.e., transferring messages between address-spaces via the kernel; also for communicating interrupts) Implement (minimal) mechanisms, not policy Outside the kernel: memory managers, pagers, device drivers. (See also: From L3 to seL4: What Have We Learnt in 20 Years of L4 Microkernels?—Elphinstone and Heiser, SOSP 2013) 14 / 52
The seL4 microkernel What is seL4? • seL4 is a 3rd-generation microkernel in the L4 tradition. • It comprises about 10,000 lines of C and 600 lines of assembler. • It was developed at NICTA in Sydney. • It is a capability-based system. It has undergone extensive formal analysis. Why? 1 A kernel is essential to a Trusted Computing Base (TCB). 2 A high-performance microkernel is hard to program correctly. 3 Microkernels are small—there are less lines of code to verify. 15 / 52
seL4: what does it do? • A critical ‘brick’ for building secure and trustworthy systems. • Share computing resources between several subsystems. • Control communications between subsystems with different levels of criticality and trustworthiness. Typical applications • Mixed-security workstation: a single machine with simultaneous access to a secure network and the Internet. • Mobile phones: execute dedicated telecommunications code and user applications on the same processor and not on separate chips. • Isolation and protection of intellectual property. Replace physical separation by capability-based security and validated by formal proof. 16 / 52
DARPA HACMS: High-Assurance Cyber Military Systems mission computer Link to Critical ground station Virtual machine and (Linux): Secure Wifi + Crypto Camera (non-critical, not secure) flight computer CAN interface Drivers seL4 • Research prototype: quadcopter • seL4 runs on the mission computer. • It shares a single computing unit between critical components and an unsecured virtual machine. • The attacker has access to the Linux subsystem and tries to compromise the rest of the system. 17 / 52
DARPA HACMS: High-Assurance Cyber Military Systems mission computer Link to Critical ground station Virtual machine and (Linux): Secure Wifi + Crypto Camera (non-critical, not secure) flight computer CAN interface Drivers seL4 • Commercial platform: the ‘Unmanned Little Bird’ (ULB) ‘potentially autonomous’ helicopter developed by Boeing. (https://ts.data61.csiro.au/projects/TS/SMACCM/) • Execute legacy code on seL4 then successively isolate components to reduce attack surfaces and facilitate analysis of the architecture. • Same principle of secure separation for other systems. 17 / 52
What is a capability? A capability is a communicable, unforgeable token of authority. It contains: • A reference (e.g., a pointer) to an object (e.g., a memory page, a thread, a fifo), and, • access rights (e.g., read, write, grant, send, receive). They must be protected from modification. An example: the string "/etc/passwd" is not a capability. 18 / 52
What is a capability? A capability is a communicable, unforgeable token of authority. It contains: • A reference (e.g., a pointer) to an object (e.g., a memory page, a thread, a fifo), and, • access rights (e.g., read, write, grant, send, receive). They must be protected from modification. An example: the string "/etc/passwd" is not a capability. "/etc/passwd" and O_RDWR is not a capability either. 18 / 52
What is a capability? A capability is a communicable, unforgeable token of authority. It contains: • A reference (e.g., a pointer) to an object (e.g., a memory page, a thread, a fifo), and, • access rights (e.g., read, write, grant, send, receive). They must be protected from modification. An example: the string "/etc/passwd" is not a capability. "/etc/passwd" and O_RDWR is not a capability either. fd = open("/etc/passwd", O_RDWR) is (almost) a capability. 18 / 52
Capabilities in seL4 Capabilities for everything • Most notably for memory management. • Tricky: also used to allocate memory to store (more) capabilities. Key concepts • CPtr: Capability addresses (integers given to user processes). • CSpace: The ‘address space’ of process capabilities. • CNode: A Capability Table in the CSpace. • CTE: Capability Table Entry (a ‘slot’ containing a capability). 19 / 52
Capabilities in seL4 Capabilities for everything • Most notably for memory management. • Tricky: also used to allocate memory to store (more) capabilities. Key concepts • CPtr: Capability addresses (integers given to user processes). • CSpace: The ‘address space’ of process capabilities. • CNode: A Capability Table in the CSpace. • CTE: Capability Table Entry (a ‘slot’ containing a capability). Communicable • Capabilities may be sent via IPC. • Parts of CSpaces may be shared between processes (just as with virtual memory). 19 / 52
Capability lookup 14 CHAPTER 3. CAPAB • A capability address is just an integer CNode Guard 0x0 (4 bits) 0x00 Object (‘handle’/‘token’). Guard 0x000 (12 bits) Object Object 0x00 CNode • It is resolved to a capability by the CNode kernel (or not). Object Object 0xFF 4 bit guard + 8 bit radix = 12 bits CNode • Thread CSpaces are implemented as 0xFF translated 32 - 20 - 12 = 0 bits remaining guarded page tables: Guard 0x0 (3 bits) • efficient 0x0 12 bit guard + 8 bit radix* = 20 bits Object translated. 32 bit word - 20 bits = 12 • sparse bits remaining *(2^8 = 256 slots) CNode • Lots of flexibility (read: complexity) 0xF CNode • sharing and ‘lending’ subspaces; 3 bit guard + 4 bit radix = 7 bits translated 32 - 20 - 7 = 5 bits remaining • Allocated memory (‘Untyped’ Figure 3.2: An example CSpace demonstrating object referen capabilities) can be chopped up to all levels, various guard and radix sizes and internal CNode refer [?] increase a CSpace. It should be noted that Figure 3.2 demonstrates only what is possi usually practical. Although the CSpace is legal, it would be reason work with due to the small number of slots and the circular 20 reference / 52
System calls System calls are made by ‘invoking’ capabilities. • The client invokes a Send or SendWait on an object capability. Client Kernel Object Cap Object Request SendWait Syscall Result Reply Cap Endpoint Figure 2.3: A request by a client for a kernel service. The dotted lines represent the conceptual flow of control and data during the request. [?] • The type of the object and a message field determine the call made. • The kernel may send a response on a given reply capability. • The message field may contain other capabilities (e.g., copying cnodes). Client Server Service Cap Service Cap Wait Request 21 / 52
the destination slot. seL4 CNode src root CPTR to the CNode that forms the root of the source CSpace. Must be at a depth of 32. seL4 Word src index CPTR to the source slot. Resolved from the root of the source CSpace. uint8 t src depth Number of bits of src index to resolve to find the source slot. seL4 CapRights rights The rights inherited by the new capability. Possible values for this type are given in Sec- tion 3.1.3. Return value: A return value of 0 indicates success. A non-zero value indicates that an error occurred. See Section 9.1 for a description of the message register and tag contents upon error. Description: See Section 3.1.2. 22 / 52
Deleting and Revoking capabilities Delete: removes a capability from a slot • Simple. • Unless it is the last capability to an object: then the object is destroyed. • Destroying a TCB or CNode requires deleting all of the child capabilities (and so on. . . ) Revoke: removes previously granted rights • Deletes all derived capabilities. • Leaves the actual capability intact. • The bookkeeping is done by a Capability Derivation Tree (CDT) • Track all child capabilities generated by retyping and copying. • Conceptually a tree. Implemented as a doubly-linked list. 23 / 52
Object 1 derived derived derived derived derived badged badged Figure 3.1: Example capability derivation tree. level 4, both are the original capability to the respective object, both are children the untyped capability they were created from. Ordinary original capabilities can have one level of derived capabilities. Further cop of these derived capabilities will create siblings, in this case remaining on level 5. Th is an exception to this scheme for endpoint capabilities — they support an additio layer of depth with the concept of badged and unbadged endpoints. The orig endpoint capability will be unbadged. Using the mint method, a copy of the capabi with a specific badge can be created. This new, badged capability to the same ob is treated as an original capability (the “original badged endpoint capability”) supports one level of derived children like other capabilities. 3.2 Deletion, Revocation, and Recycling 24 / 52
seL4: design, development, and verification 25 / 52
26 / 52
David Cock Alexander Kroh Vernon Tang Adrian Danis Etienne Le Sueur Michael von Tessin Matthias Daum Corey Lewis David Tsai Jeremy Dawson Japheth Lim Harvey Tuch Philip Derrin Anna Lyons Adam Walker Dhammika Elkaduwe Tran Ma James Wilmot Kevin Elphinstone Daniel Matichuk Simon Winwood Kai Engelhardt Stephanie McArthur Jiawei Xie Matthew Fernandez © 2016 Data61/CSIRO. Legal notice and Disclaimer (http://www.csiro.au/About/Footer/Legal-notice) · Contact us (/contact/) · privacy (http://www.csiro.au/About/Access-to-information/Privacy) Served by Apache on Linux on seL4. 26 / 52
Online Repositories Developed in L4.verified and later (on-going) projects. • Source code (Haskell and C): https://github.com/seL4/seL4 • Proofs (Isabelle): https://github.com/seL4/l4v 27 / 52
seL4 call graph [?, Figure 1] • Good: Small code base (
Abstract specification • Non-deterministic model in a higher-order logic. • Defines the kernel’s binary interface and the effect of calls on an abstract state. Abstract specification Haskell prototype iterative development • A shared language between systems programmers and formal methods experts Haskell prototype • Iterative and rapid prototyping • Defines an implementation of the specification • It is executable: co-simulation with QEMU • Model with algebraic data types (records, lists, etc.) • Functional expressions without side-effects (maps, folds, etc.) • Manipulate global state in a monadic style • Global program variables (Model/StateData.lhs) • ARM Machine state (Model/StateData/ARM.lhs) 29 / 52
Reactive model [?, Figure 10] 30 / 52
Abstract specification iterative development Prototype Haskell 31 / 52
Abstract specification Executable translator Prototype Haskell specification 31 / 52
Abstract specification Executable translator Prototype Haskell specification manual Why rewrite the kernel in C? implementation • Haskell requires a significant run-time environment (even bigger than the kernel). C Implementation • It requires a garbage collector. • The manual translation gave opportunities for micro-optimization. 31 / 52
Abstract specification Executable translator Prototype Haskell specification manual implementation parser Model of the C implementation C Implementation (operational semantics) 31 / 52
Abstract specification refinement Executable translator Prototype Haskell specification manual c-refinement implementation parser Model of the C implementation C Implementation (operational semantics) 31 / 52
Abstract specification (Isabelle/HOL) seL4/l4v:/spec/haskell/spec/abstract/Schedule_A.thy Executable specification (Haskell) C implementation seL4/l4v:/spec/haskell/src/SEL4/Kernel/Thread.lhs seL4/seL4:/src/kernel/thread.c 32 / 52
Modelling state • (Most) Global and local variables as fields in a record. • Model the heap as a mapping from addresses to bytes. heap_mem heap_mem ... byte list ... 204 heap_update_list 204 to_bytes int 204 136 136 size_of TYPE(int) 1646954700 136 42 42 heap_list from_bytes 98 98 42 0 98 1 0 0 1 0 0 34 65 0 20 34 ... 65 20 ... Figure 3. int heap representation [?] • Actual model: model multiple ‘typed’ heaps. [?] Figure 4. In In this work we deal primarily with C’s base and pointer types but it is possible to extend this to compound types. Array indexing, • Requires reasoning about offsets, alignment, overlap, validity, etc., access, and update semantics can be expressed in terms of the cor- rewrite rules connecting the m responding pointer semantics. C’s struct types can be translated but sometimes unavoidable. this kind of aliasing when prog to Isabelle record types, however the models in this paper require ment of C. extending when fields have their address taken2 or padding is in- • Automatic generation of bitfield access routines and associated proofs In this type-safe fragment, volved. Similarly, union types can be treated as datatypes when a language would be based on tag field can be identified, and otherwise translated to type-casts. (Python script). for each language type, e.g. a Low-level heap access and update Heap dereferences in expres- this avoids the problem of inter sions, e.g. ∗p + 1 are given a semantics by first lifting the raw heap proofs, it does not allow 33 / us 52 to state with the polymorphic lift function, e.g. lift s p + 1 where s is
C: source to model kernel_all.c_pp StrictC-parser Simpl model vcg proof obligations Simpl: Sequential IMperative Programming Language [?] • General model of imperative programming in Isabelle/HOL (exceptions, local and global variables, pointers and heap, . . . ) • Big-step operational semantics Γ ` hc, si ⇒ s 0 • Small-step operational semantics • Hoare logic (i.e., axiomatic semantics; derived thus correct) • Verification Condition Generator a tactic to automate weakest precondition reasoning 34 / 52
C: source to model kernel_all.c_pp StrictC-parser Simpl model vcg proof obligations datatype (dead ’s, ’p, ’f) com = Skip | Basic "’s => ’s" | Spec "(’s * ’s) set" | Seq "(’s,’p,’f) com" "(’s,’p,’f) com" | Cond "’s bexp" "(’s,’p,’f) com" "(’s,’p,’f) com" | While "’s bexp" "(’s,’p,’f) com" | Call "’p" | DynCom "’s => (’s,’p,’f) com" | Guard "’f" "’s bexp" "(’s,’p,’f) com" | Throw | Catch "(’s,’p,’f) com" "(’s,’p,’f) com" 34 / 52
C: source to model kernel_all.c_pp StrictC-parser Simpl model vcg proof obligations StrictC: parsing into Isabelle for a subset of C • Treats a large subset of C (no goto, no side-effects in expressions, . . . ) • Allows some annotations to help the proof tools. • The command install_C_file 1 parses a C file, 2 translates it into a Simpl program, 3 discharges some minor proof obligations, 4 generates lemmas for unmodified globals. • The translation into Simpl encodes the semantics for C and gives a model. 34 / 52
Abstract specification refinement Executable translator Haskell prototype specification manual c-refinement implementation parser Model of C implementation C implementation (operational semantics) 35 / 52
Abstract specification refinement lateral refinement Executable translator fastpath Haskell prototype specification manual c-refinement c-refinement implementation parser Model of C implementation C implementation (operational semantics) 35 / 52
Abstract specification refinement lateral refinement Executable translator fastpath Haskell prototype specification manual c-refinement c-refinement implementation parser Model of C implementation C implementation (operational semantics) gcc -O1 seL4 binary 35 / 52
Translation validation of binary in HOL4 • Extremely rigours, but no longer ‘end to end’: more formal tools Comprehensive Formal Verification of an OS Microkernel 2:27 • Work on gcc -O2 continues. . . Abstract specification refinement lateral refinement Executable translator fastpath Haskell prototype specification manual c-refinement c-refinement implementation parser Fig. 12. Binary verification overview for seL4. Model of C implementation C implementation (operational semantics) We use two SMT solvers, Z3 [de Moura and Bjørner 2008] and Sonolar [Peleska et al. 2011]. We use Z3 first with a small time-out, because it is fast, even though it solves fewer goals. Sonolar is slow but stronger on the theory of arrays and bit vectors which model memory and machine words. gcc -O1 HOL4 + SMT One key aspect of this work is the link between two existing semantics and the link to an existing proof: we join a well-validated hardware model with the Isabelle C semantics and the invariants and assertions that have already been proven on it. The latter is important, because traditional translation validation approaches must assume what the C standard gives in terms of language guarantees, similarly to the read bytes CompCert theorem. Since, as mentioned, OS kernel code purposefully breaks the C Model of binary standard, these approaches typically failseL4 binary at such code. Our approach, however, can (Cambridge ARM semantics) adapt assertions to fit with existing memory invariants, giving the translation valida- tion proof more information, even where the C standard is followed only partially. Not only does this make the translation validation succeed, it also gives assurance that the compiled code has the expected behaviour, even where it is outside the standard.35 / 52 Using this approach, we have managed to verify the binary correctness of all seL4
• The specification is implemented by the binary. . . • But the abstract specification is itself a complicated program. • Does it have the desired properties? Abstract specification refinement lateral refinement Executable translator fastpath Haskell prototype specification manual c-refinement c-refinement implementation parser Model of C implementation C implementation (operational semantics) gcc -O1 HOL4 + SMT read bytes Model of binary seL4 binary (Cambridge ARM semantics) 35 / 52
Capacity dis- tribution pas-refinement Abstract specification refinement lateral refinement Executable translator fastpath Haskell prototype specification manual c-refinement c-refinement implementation parser Model of C implementation C implementation (operational semantics) gcc -O1 HOL4 + SMT read bytes Model of binary seL4 binary (Cambridge ARM semantics) 35 / 52
integrity Capacity dis- Access control and tribution information flow pas-refinement pas-refinement Abstract specification refinement lateral refinement Executable translator fastpath Haskell prototype specification manual c-refinement c-refinement implementation parser Model of C implementation C implementation (operational semantics) gcc -O1 HOL4 + SMT read bytes Model of binary seL4 binary (Cambridge ARM semantics) 35 / 52
Model of capability distribution and access control [?, Figure 13] 36 / 52
Assumptions made by the proof • Correctness of the initialization code (no longer the case). • Correctness of the C compiler and linker (no longer the case). • Correctness of assembly code and hardware: • Register save and restore; • Context switch on kernel exit; • Cache consistency, colouring and TLB flushing. 37 / 52
Assumptions made by the proof • Correctness of the initialization code (no longer the case). • Correctness of the C compiler and linker (no longer the case). • Correctness of assembly code and hardware: • Register save and restore; • Context switch on kernel exit; • Cache consistency, colouring and TLB flushing. What about mistakes in the proof? 37 / 52
Guarantees given by the proof • No code injection attacks (not allowed by spec) • No buffer overflows • All array accesses within bounds. • All pointer accesses are well typed. • No NULL pointer access: proof obligation at every pointer access • No ill-typed pointer access: proof obligation at every pointer access • No memory leaks: consequence of design, proven. • Termination: all kernel calls terminate. • No arithmetic or other exceptions: modelled at C-level, proven. • No unchecked user arguments: all user input is checked and validated. • Aligned objects: all objects are aligned to their size; none overlap. • Well-formed data structures: properties of linked lists. • Algorithmic invariants: many optimizations rely on certain properties being true. These are shown as invariants. 38 / 52
seL4: Size of code, specs and proofs [?, Figure 17] 39 / 52
Fig. 19. Development and Proof Efforts (starred numbers come from rigorous effort counting, others are conservative estimates). ACM Transactions on Computer Systems, Vol. 32, No. 1, Article 2, Publication date: February 2014.
highest level of certification. EAL7 does not require the code to be formally linked to the design model, and the industry rule-of-thumb for the lower EAL6 is already $1000/LOC.” Fig. 19. Development and Proof Efforts (starred numbers come from rigorous effort counting, others are conservative estimates). ACM Transactions on Computer Systems, Vol. 32, No. 1, Article 2, Publication date: February 2014. 40 / 52
seL4: Bugs [?, Figure 20] 41 / 52
Maintenance de la preuve 42 / 52
Ordonnancement dans seL4 TCB .. . tcbState tcbPriority tcbQueued tcbTimeSlice .. .
Ordonnancement dans seL4 TCB setThreadState(): runnable / .. blocked / idle . tcbState tcbPriority tcbQueued tcbTimeSlice .. .
Ordonnancement dans seL4 TCB setThreadState(): runnable / .. blocked / idle . tcbState tcbPriority tcbQueued tcbTimeSlice .. . decremented by timerTick()
Ordonnancement dans seL4 Globals TCB setThreadState(): runnable / ksCurThread tcb .. blocked / idle . .. tcbState . 255 tcbPriority 254 tcb ksReadyQueues tcbQueued tcbSchedEnqueue() 253 tcb tcb tcbSchedDequeue() tcbTimeSlice .. .. tcbSchedAppend() . . .. . decremented 0 by timerTick() ksSchedulerAction
Ordonnancement dans seL4 Globals TCB setThreadState(): runnable / ksCurThread tcb .. blocked / idle . .. tcbState . 255 tcbPriority 254 tcb ksReadyQueues tcbQueued tcbSchedEnqueue() 253 tcb tcb tcbSchedDequeue() tcbTimeSlice .. .. tcbSchedAppend() . . .. . decremented 0 by timerTick() ksSchedulerAction utilisateur utilisateur callKernel() schedule() système chooseThread()
Ordonnancement dans seL4 Globals TCB setThreadState(): runnable / ksCurThread tcb .. blocked / idle . .. tcbState . 255 tcbPriority 254 tcb ksReadyQueues tcbQueued tcbSchedEnqueue() 253 tcb tcb tcbSchedDequeue() tcbTimeSlice .. .. tcbSchedAppend() . . .. . decremented 0 by timerTick() ksSchedulerAction ResumeCurrentThread utilisateur utilisateur SwitchToThread possibleSwitchTo() callKernel() schedule() système ChooseNewThread chooseThread()
Ordonnancement dans seL4 Modification ‘Non-lazy’ Globals TCB setThreadState(): Plus dans la file d’attente runnable / ksCurThread tcb .. blocked / idle . .. tcbState . 255 tcbPriority 254 tcb ksReadyQueues tcbQueued tcbSchedEnqueue() 253 tcb tcb tcbSchedDequeue() Runnable tcbTimeSlice .. .. tcbSchedAppend() . . .. . decremented 0 by timerTick() ksSchedulerAction ResumeCurrentThread utilisateur utilisateur SwitchToThread possibleSwitchTo() callKernel() schedule() système ChooseNewThread chooseThread() 43 / 52
Modifications requises Spécification abstraite REFINE Prototype Haskell CREFINE Implémentation C
Modifications requises Spécification abstraite REFINE Prototype Haskell CREFINE Implémentation C 1. patch original
Modifications requises Spécification abstraite REFINE Prototype Haskell 2. patch correspondant CREFINE Implémentation C 1. patch original
Modifications requises Spécification abstraite 3. patch mineur REFINE Prototype Haskell 2. patch correspondant CREFINE Implémentation C 1. patch original
Modifications requises [. . . .] AInvs [HOL] [BASE_REFINE] KernelInit_AI Spécification abstraite Invariants_H LevityCatch 3. patch mineur StateRelation Invocations_R Corres Bits_R 4. correction des Machine_R EmptyFail REFINE preuves KHeap_R SubMonad_R (modifications ArchAcc_R CSpace_I des invariants) CSpace_R TcbAcc_R Prototype Haskell VSpace_R InterruptAcc_R 2. patch Schedule_R Retype_R correspondant IpcCancel_R Detype_R Finalise_R Untyped_R Ipc_R Arch_R CREFINE CNodeInv_R Interrupt_R Tcb_R Syscall_R ADT_H PageTableDuplicates IncKernelInit Implémentation C InitLemmas KernelInit_R Refine 1. patch original Orphanage REFINE
Modifications requises [. . . .] Pure [HOL] AInvs [HOL] [BASE_REFINE] KernelInit_AI [HOL-Word] [VCG-orig] Spécification abstraite Invariants_H LevityCatch [WORD] [UMM] 3. patch mineur [Sep] StateRelation Invocations_R [vcg] Corres [CKERNEL] SimplRewrite [CSPEC] Bits_R CToCRefine [CBASE_REFINE] 4. correction des Machine_R EmptyFail DetWPLib LemmaBucket_C SIMPL_Lemmas MonadicRewrite Move REFINE preuves KHeap_R DetWP CLevityCatch Corres_UL_C XPres SubMonad_R Wellformed_C CCorresLemmas MonadicRewrite_C (modifications ArchAcc_R StateRelation_C SR_lemmas_C CSpace_I des invariants) CSpace_R TcbQueue_C Corres_C Ctac TcbAcc_R Prototype Haskell VSpace_R InterruptAcc_R CSpaceAcc_C Machine_C TcbAcc_C PSpace_C Detype_C 2. patch Schedule_R Retype_R CSpace_RAB_C CSpace_C correspondant IpcCancel_R Detype_R CSpace_All VSpace_C Finalise_R Untyped_R StoreWord_C Ipc_R Arch_R CREFINE CNodeInv_R Interrupt_R SyscallArgs_C IpcCancel_C Retype_C 5. correction Tcb_R Syscall_R Interrupt_C Finalise_C Ipc_C Delete_C des preuves ADT_H PageTableDuplicates Recycle_C Tcb_C IncKernelInit Arch_C Invoke_C Schedule_C Implémentation C Syscall_C ADT_C InitLemmas KernelInit_R FastpathMachine_C Init_C Refine Fastpath_C 1. patch original Orphanage Refine_C REFINE CREFINE 44 / 52
Chronogramme master implémentation C / prototype Haskell nonlazysched 3 févr. 15 févr. 29 févr. 27 mars 3 avr. 7 juin 21 juin 28 juin ajuste isBlocked/isRunnable patch original supprime tcbSchedDequeue master raffinement / raffinement-c nonlazysched 3 févr. 15 févr. 27 févr. 23 mars 2 avr. 10 avr. 15 May 26 juin 28 juin invs’:1 invs’:2 invs’:3 invs’:4 invs’:5 raffinement complet raffinement-c complet mise à jour des specs branchement 45 / 52
Chronogramme master implémentation C / prototype Haskell nonlazysched 3 févr. 15 févr. 29 févr. 27 mars 3 avr. 7 juin 21 juin 28 juin ajuste isBlocked/isRunnable patch original modèles supprime tcbSchedDequeue (1.0 ETP) 0.6 semaines raffinement (1.6 ETP) 20.4 semaines raffinement-c (1.2 ETP) 4.0 semaines merge (1.0 ETP) 0.4 semaines master (1 semaine = 35 heures) raffinement / raffinement-c 38.44 semaines nonlazysched 3 févr. 15 févr. 27 févr. 23 mars 2 avr. 10 avr. 15 May 26 juin 28 juin invs’:1 invs’:2 invs’:3 invs’:4 invs’:5 raffinement complet raffinement-c complet mise à jour des specs branchement 45 / 52
Invariants invs’ inQ p tcb ≡ tcbQueued tcb ∧ tcbPriority tcb = p valid-queues ≡ λs. ∀ p. (∀ t∈set (ksReadyQueues s p). obj-at’ (inQ p) t s) ∧ distinct (ksReadyQueues s p) valid-queues’ ≡ λs. ∀ p t. obj-at’ (inQ p) t s −→ t ∈ set (ksReadyQueues s p) 46 / 52
Invariants invs’ :1 (15 février) inQ p tcb ≡ tcbQueued tcb ∧ tcbPriority tcb = p ∧ tcbState tcb = Running valid-queues ≡ λs. ∀ p. (∀ t∈set (ksReadyQueues s p). obj-at’ (inQ p) t s) ∧ distinct (ksReadyQueues s p) valid-queues’ ≡ λs. ∀ p t. obj-at’ (inQ p) t s −→ t ∈ set (ksReadyQueues s p) 46 / 52
Invariants invs’ :2 (27 février) inQ p tcb ≡ tcbQueued tcb ∧ tcbPriority tcb = p ∧ runnable’ (tcbState tcb) valid-queues ≡ λs. ∀ p. (∀ t∈set (ksReadyQueues s p). obj-at’ (inQ p) t s) ∧ distinct (ksReadyQueues s p) valid-queues’ ≡ λs. ∀ p t. obj-at’ (inQ p) t s −→ t ∈ set (ksReadyQueues s p) 46 / 52
Invariants invs’ :3 (23 mars) inQ p tcb ≡ tcbQueued tcb ∧ tcbPriority tcb = p valid-queues ≡ λs. ∀ p. (∀ t∈set (ksReadyQueues s p). obj-at’ (inQ p and runnable’ ◦ tcbState) t s) ∧ distinct (ksReadyQueues s p) valid-queues’ ≡ λs. ∀ p t. obj-at’ (inQ p) t s −→ t ∈ set (ksReadyQueues s p) 46 / 52
Invariants invs’ :4 ( 2 avril) inQ p tcb ≡ tcbQueued tcb ∧ tcbPriority tcb = p valid-queues ≡ λs. ∀ p. (∀ t∈set (ksReadyQueues s p). obj-at’ (inQ p and runnable’ ◦ tcbState) t s) ∧ distinct (ksReadyQueues s p) valid-queues’ ≡ λs. ∀ p t. obj-at’ (inQ p) t s −→ t ∈ set (ksReadyQueues s p) ct-not-inQ ≡ λs. obj-at’ (Not ◦ tcbQueued) (ksCurThread s) s 46 / 52
Invariants invs’ :5 (10 avril) inQ p tcb ≡ tcbQueued tcb ∧ tcbPriority tcb = p valid-queues ≡ λs. ∀ p. (∀ t∈set (ksReadyQueues s p). obj-at’ (inQ p and runnable’ ◦ tcbState) t s) ∧ distinct (ksReadyQueues s p) valid-queues’ ≡ λs. ∀ p t. obj-at’ (inQ p) t s −→ t ∈ set (ksReadyQueues s p) ct-not-inQ ≡ λs. ksSchedulerAction s = ResumeCurrentThread −→ obj-at’ (Not ◦ tcbQueued) (ksCurThread s) s 46 / 52
Appels aux tcbSchedEnqueue et tcbSchedAppend handleSyscall handleInvocation handleWait handleInterrupt decodeInvocation handleReply timerTick handleYield schedule decodeCNodeInvocation performInvocation_Reply tcbSchedAppend invokeCNodeDelete invokeCNodeRevoke invokeCNodeRecycle decodeTCBInvocation doReplyTransfer cteRecycle decodeSetIPCBuffer decodeSetSpace decodeTCBConfigure decodeSetPriority decodeWriteRegisters decodeCopyRegisters cteRevoke recycleCap invokeTCB_ThreadControl invokeTCB_Resume invokeTCB_WriteRegisters invokeTCB_CopyRegisters cteDelete restart decodeReadRegisters deleteCallerCap finaliseSlot setPriority invokeTCB_Suspend invokeTCB_ReadRegisters reduceZombie finaliseCap epCancelBadgedSends epCancelAll possibleSwitchTo aepCancelAll rescheduleRequired suspend decodeIRQHandlerInvocation deletingIRQHandler tcbSchedEnqueue ipcCancel invokeIRQHandler_SetIRQHandler invokeIRQHandler_ClearIRQHandler cteDeleteOne 47 / 52
Appels aux tcbSchedEnqueue et tcbSchedAppend handleSyscall handleInvocation handleWait handleInterrupt decodeInvocation handleReply timerTick handleYield schedule decodeCNodeInvocation performInvocation_Reply tcbSchedAppend invokeCNodeDelete invokeCNodeRevoke invokeCNodeRecycle decodeTCBInvocation doReplyTransfer cteRecycle decodeSetIPCBuffer decodeSetSpace decodeTCBConfigure decodeSetPriority decodeWriteRegisters decodeCopyRegisters cteRevoke recycleCap invokeTCB_ThreadControl invokeTCB_Resume invokeTCB_WriteRegisters invokeTCB_CopyRegisters cteDelete restart decodeReadRegisters deleteCallerCap finaliseSlot setPriority invokeTCB_Suspend invokeTCB_ReadRegisters reduceZombie finaliseCap epCancelBadgedSends epCancelAll possibleSwitchTo aepCancelAll rescheduleRequired suspend decodeIRQHandlerInvocation deletingIRQHandler tcbSchedEnqueue ipcCancel invokeIRQHandler_SetIRQHandler invokeIRQHandler_ClearIRQHandler cteDeleteOne {|invs’ and st-tcb-at’ runnable’ t and (λs. ksSchedulerAction s = ResumeCurrentThread −→ ksCurThread s 6= t)|} tcbSchedEnqueue t {|λ-. invs’|} 47 / 52
Appels aux tcbSchedEnqueue et tcbSchedAppend handleSyscall handleInvocation handleWait handleInterrupt sa = ChooseNewThread / SwitchToThread decodeInvocation handleReply timerTick handleYield schedule decodeCNodeInvocation performInvocation_Reply tcbSchedAppend invokeCNodeDelete invokeCNodeRevoke invokeCNodeRecycle decodeTCBInvocation doReplyTransfer cteRecycle decodeSetIPCBuffer decodeSetSpace decodeTCBConfigure decodeSetPriority decodeWriteRegisters decodeCopyRegisters cteRevoke recycleCap invokeTCB_ThreadControl invokeTCB_Resume invokeTCB_WriteRegisters invokeTCB_CopyRegisters cteDelete restart decodeReadRegisters deleteCallerCap finaliseSlot setPriority invokeTCB_Suspend invokeTCB_ReadRegisters reduceZombie finaliseCap epCancelBadgedSends epCancelAll possibleSwitchTo aepCancelAll rescheduleRequired suspend decodeIRQHandlerInvocation deletingIRQHandler tcbSchedEnqueue ipcCancel invokeIRQHandler_SetIRQHandler invokeIRQHandler_ClearIRQHandler cteDeleteOne {|invs’ and st-tcb-at’ runnable’ t and (λs. ksSchedulerAction s = ResumeCurrentThread −→ ksCurThread s 6= t)|} tcbSchedEnqueue t {|λ-. invs’|} 47 / 52
Appels aux tcbSchedEnqueue et tcbSchedAppend handleSyscall handleInvocation handleWait handleInterrupt sa = ChooseNewThread / SwitchToThread decodeInvocation handleReply timerTick handleYield schedule decodeCNodeInvocation performInvocation_Reply tcbSchedAppend invokeCNodeDelete invokeCNodeRevoke invokeCNodeRecycle decodeTCBInvocation doReplyTransfer cteRecycle decodeSetIPCBuffer decodeSetSpace decodeTCBConfigure decodeSetPriority decodeWriteRegisters decodeCopyRegisters cteRevoke recycleCap invokeTCB_ThreadControl invokeTCB_Resume invokeTCB_WriteRegisters invokeTCB_CopyRegisters cteDelete restart decodeReadRegisters deleteCallerCap finaliseSlot setPriority invokeTCB_Suspend invokeTCB_ReadRegisters reduceZombie finaliseCap epCancelBadgedSends mis en file d’attente des threads, appel à RescheduleRequired epCancelAll possibleSwitchTo aepCancelAll utilise: all-invs-but-ct-not-inQ rescheduleRequired suspend decodeIRQHandlerInvocation deletingIRQHandler tcbSchedEnqueue ipcCancel invokeIRQHandler_SetIRQHandler invokeIRQHandler_ClearIRQHandler cteDeleteOne {|invs’ and st-tcb-at’ runnable’ t and (λs. ksSchedulerAction s = ResumeCurrentThread −→ ksCurThread s 6= t)|} tcbSchedEnqueue t {|λ-. invs’|} 47 / 52
Appels aux tcbSchedEnqueue et tcbSchedAppend handleSyscall handleInvocation handleWait handleInterrupt sa = ChooseNewThread / SwitchToThread decodeInvocation handleReply timerTick handleYield schedule decodeCNodeInvocation performInvocation_Reply tcbSchedAppend invokeCNodeDelete invokeCNodeRevoke invokeCNodeRecycle decodeTCBInvocation doReplyTransfer cteRecycle decodeSetIPCBuffer decodeSetSpace decodeTCBConfigure decodeSetPriority decodeWriteRegisters decodeCopyRegisters cteRevoke recycleCap invokeTCB_ThreadControl invokeTCB_Resume invokeTCB_WriteRegisters invokeTCB_CopyRegisters cteDelete retrait puis mis en file d’attente restart decodeReadRegisters deleteCallerCap finaliseSlot setPriority invokeTCB_Suspend invokeTCB_ReadRegisters reduceZombie finaliseCap epCancelBadgedSends mis en file d’attente des threads, appel à RescheduleRequired epCancelAll possibleSwitchTo aepCancelAll utilise: all-invs-but-ct-not-inQ rescheduleRequired suspend decodeIRQHandlerInvocation deletingIRQHandler tcbSchedEnqueue ipcCancel invokeIRQHandler_SetIRQHandler invokeIRQHandler_ClearIRQHandler cteDeleteOne {|invs’ and st-tcb-at’ runnable’ t and (λs. ksSchedulerAction s = ResumeCurrentThread −→ ksCurThread s 6= t)|} tcbSchedEnqueue t {|λ-. invs’|} 47 / 52
Appels aux tcbSchedEnqueue et tcbSchedAppend handleSyscall handleInvocation handleWait handleInterrupt sa = ChooseNewThread / SwitchToThread decodeInvocation handleReply timerTick handleYield schedule decodeCNodeInvocation performInvocation_Reply tcbSchedAppend invokeCNodeDelete invokeCNodeRevoke invokeCNodeRecycle decodeTCBInvocation doReplyTransfer cteRecycle decodeSetIPCBuffer decodeSetSpace decodeTCBConfigure decodeSetPriority decodeWriteRegisters decodeCopyRegisters la cible est bloquée et ResumeCurrentThread cteRevoke recycleCap invokeTCB_ThreadControl invokeTCB_Resume sch-act-wf assure que ksCurThread n’est pas bloqué invokeTCB_WriteRegisters invokeTCB_CopyRegisters cteDelete retrait puis mis en file d’attente restart decodeReadRegisters deleteCallerCap finaliseSlot setPriority invokeTCB_Suspend invokeTCB_ReadRegisters reduceZombie finaliseCap epCancelBadgedSends mis en file d’attente des threads, appel à RescheduleRequired epCancelAll possibleSwitchTo aepCancelAll utilise: all-invs-but-ct-not-inQ rescheduleRequired suspend decodeIRQHandlerInvocation deletingIRQHandler tcbSchedEnqueue ipcCancel invokeIRQHandler_SetIRQHandler invokeIRQHandler_ClearIRQHandler cteDeleteOne {|invs’ and st-tcb-at’ runnable’ t and (λs. ksSchedulerAction s = ResumeCurrentThread −→ ksCurThread s 6= t)|} tcbSchedEnqueue t {|λ-. invs’|} 47 / 52
Résumé des modifications du raffinement number of lemmas affected 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 new: invariant stronger precondition new: crunch minor proof adjustment new: helper lemma proof adjustment modified crunch new: variation minor adjusted statement deleted adjusted statement new: helper lemma (key) weaker precondition stronger assumption new: corres helper new: invariant (key) weaker assumption 48 / 52
Maintenance: résumé • Un programme utile, vérifié ou non, doit être modifié. • La mise à jour des preuves • est chronophage • est (encore plus) difficile à planifier • demande de l’expertise • Mais il y a aussi des points positifs : • L’assistant de preuve localise les parties à corriger. • On peut confier les modifications aux nouveaux arrivants en sachant que les invariants sont documentés et contrôlés. • L’itération dans l’assistant de preuve aide à découvrir la forme correcte des invariants. • La réflexion requise et l’inertie ne sont pas forcément une mauvaise chose pour un système critique. • Il faut bien réfléchir à l’automatisation dès le début du projet (‘tactiques’) 49 / 52
Related Projects • The Verisoft (2004–2007, http://www.verisoft.de ) and Verisoft XT (2007–2010, http://www.verisoftxt.de ) projects • The CompCert project [?] • CertiKOS (http://flint.cs.yale.edu/certikos/index.html) • Prove & Run’s Provencore (http://www.provenrun.com/products/provencore/) • See also Klein’s overview [?] 50 / 52
seL4: key publications [?] [?] [?] [?] [?] [?] [?] [?] [?] [?] 51 / 52
52 / 52
You can also read