Rev 183 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 183 | Rev 184 | ||
|---|---|---|---|
| Line 2... | Line 2... | ||
| 2 | \usepackage{graphicx} |
2 | \usepackage{graphicx} |
| 3 | 3 | ||
| 4 | \title{A Road to a Formally Verified General-Purpose Operating System} |
4 | \title{A Road to a Formally Verified General-Purpose Operating System} |
| 5 | \author{Martin D\v{e}ck\'{y}} |
5 | \author{Martin D\v{e}ck\'{y}} |
| 6 | \institute{Department of Distributed and Dependable Systems\\ |
6 | \institute{Department of Distributed and Dependable Systems\\ |
| 7 | Faculty of Mathematics and Physics, Charles University\\ |
7 | Faculty of Mathematics and Physics, Charles University\\ |
| 8 | Malostransk\'{e} n\'{a}m\v{e}st\'{i} 25, Prague 1, 118~00, Czech Republic\\ |
8 | Malostransk\'{e} n\'{a}m\v{e}st\'{i} 25, Prague 1, 118~00, Czech Republic\\ |
| 9 | \email{martin.decky@d3s.mff.cuni.cz}} |
9 | \email{martin.decky@d3s.mff.cuni.cz}} |
| 10 | 10 | ||
| 11 | \begin{document} |
11 | \begin{document} |
| 12 | \maketitle |
12 | \maketitle |
| 13 | |
13 | |
| 14 | \begin{abstract} |
14 | \begin{abstract} |
| Line 130... | Line 130... | ||
| 130 | Many development projects such as task snapshoting and migration, support for MMU-less |
130 | Many development projects such as task snapshoting and migration, support for MMU-less |
| 131 | platforms and performance monitoring are currently underway. |
131 | platforms and performance monitoring are currently underway. |
| 132 | |
132 | |
| 133 | \medskip |
133 | \medskip |
| 134 | |
134 | |
| 135 | HelenOS can be briefly described as microkernel multiserver design. However, the actual design |
135 | HelenOS can be briefly described as microkernel multiserver OS. However, the actual design |
| 136 | guiding principles of the HelenOS are more elaborate: |
136 | guiding principles of the HelenOS are more elaborate: |
| 137 | |
137 | |
| 138 | \begin{description} |
138 | \begin{description} |
| 139 | \item[Microkernel principle] Every functionality of the OS that does not |
139 | \item[Microkernel principle] Every functionality of the OS that does not |
| 140 | have to be necessary implemented in the kernel should be implemented in user space. This |
140 | have to be necessary implemented in the kernel should be implemented in user space. This |
| Line 149... | Line 149... | ||
| 149 | It contains features such as AVL and B+ trees, hashing tables, SLAB memory allocator, multiple |
149 | It contains features such as AVL and B+ trees, hashing tables, SLAB memory allocator, multiple |
| 150 | in-kernel synchronization primitives, fine-grained locking and so on. |
150 | in-kernel synchronization primitives, fine-grained locking and so on. |
| 151 | \item[Multiserver principle] Subsystems in user space should be decomposed with the smallest |
151 | \item[Multiserver principle] Subsystems in user space should be decomposed with the smallest |
| 152 | reasonable granularity. Each unit of decomposition should be encapsulated in a separate task. |
152 | reasonable granularity. Each unit of decomposition should be encapsulated in a separate task. |
| 153 | The tasks represent software components with isolated address spaces. From the design point of |
153 | The tasks represent software components with isolated address spaces. From the design point of |
| 154 | view the kernel can be seen as a separate component, too. |
154 | view the kernel can be seen as a separate software component, too. |
| 155 | \item[Split of mechanism and policy] The kernel should only provide low-level mechanisms, |
155 | \item[Split of mechanism and policy] The kernel should only provide low-level me\-chanisms, |
| 156 | while the high-level policies which are built upon these mechanisms should be defined in |
156 | while the high-level policies which are built upon these mechanisms should be defined in |
| 157 | user space. This also implies that the policies should be easily replaceable while keeping |
157 | user space. This also implies that the policies should be easily replaceable while keeping |
| 158 | the low-level mechanisms intact. |
158 | the low-level mechanisms intact. |
| 159 | \item[Encapsulation principle] The communication between the tasks/components should be |
159 | \item[Encapsulation principle] The communication between the tasks/components should be |
| 160 | implemented only via a set of well-defined interfaces. In the user-to-user case the preferred |
160 | implemented only via a set of well-defined interfaces. In the user-to-user case the preferred |
| Line 225... | Line 225... | ||
| 225 | architecture to the programmer in a very straightforward, but still relatively portable way. |
225 | architecture to the programmer in a very straightforward, but still relatively portable way. |
| 226 | |
226 | |
| 227 | However, what is the biggest advantage of C in terms of run-time performance is also the biggest weakness |
227 | However, what is the biggest advantage of C in terms of run-time performance is also the biggest weakness |
| 228 | for formal reasoning. The permissive memory access model of C, the lack of any reference safety |
228 | for formal reasoning. The permissive memory access model of C, the lack of any reference safety |
| 229 | enforcement, the weak type system and generally little semantic information in the code -- all these |
229 | enforcement, the weak type system and generally little semantic information in the code -- all these |
| 230 | properties that do not allow to make many general assumptions about the code. |
230 | properties do not allow to make many general assumptions about the code. |
| 231 | |
231 | |
| 232 | Programming languages which target controlled environments such as Java or C\(\sharp\) are |
232 | Programming languages which target controlled environments such as Java and C\(\sharp\) are |
| 233 | generally easier for formal reasoning because they provide a well-known set of primitives |
233 | generally easier for formal reasoning because they provide a well-known set of primitives |
| 234 | and language constructs for object ownership, threading and synchronization. Many non-imperative |
234 | and language constructs for object ownership, threading and synchronization. Many non-imperative |
| 235 | programming languages can be even considered to be a form of ``executable specification'' and thus |
235 | programming languages can be even considered to be a form of ``executable specification'' and thus |
| 236 | very suitable for formal reasoning. In C, almost everything is left to the programmer who |
236 | very suitable for formal reasoning. In C, almost everything is left to the programmer who |
| 237 | is free to set the rules. |
237 | is free to set the rules. |
| Line 271... | Line 271... | ||
| 271 | |
271 | |
| 272 | Some of the proposed methods cannot be called ``formal methods'' in the rigorous understanding |
272 | Some of the proposed methods cannot be called ``formal methods'' in the rigorous understanding |
| 273 | of the term. However, even methods which are based on semi-formal reasoning and non-exhaustive |
273 | of the term. However, even methods which are based on semi-formal reasoning and non-exhaustive |
| 274 | testing provide some limited guarantees in their specific context. A valued property |
274 | testing provide some limited guarantees in their specific context. A valued property |
| 275 | of the formal methods is to preserve these limited guarantees even on the higher levels |
275 | of the formal methods is to preserve these limited guarantees even on the higher levels |
| 276 | of abstraction, thus complementing the formal guarantees where the formal methods do not provide |
276 | of abstraction, thus allowing the semi-formal methods to complement the big picture |
| 277 | any feasible verification so far. This increases the coverage of the set of all hypothetical |
277 | where the formal methods do not provide any feasible verification so far. This increases |
| 278 | interesting properties of the system (although it is probably impossible to formally define |
278 | the coverage of the set of all hypothetical interesting properties of the system (although |
| 279 | this set). |
279 | it is probably impossible to formally define this entire set). |
| 280 | |
280 | |
| 281 | \medskip |
281 | \medskip |
| 282 | |
282 | |
| 283 | Please note that the titles of the following sections do not follow any particular established |
283 | Please note that the titles of the following sections do not follow any particular established |
| 284 | taxonomy. We have simply chosen the names to be intuitively descriptive. |
284 | taxonomy. We have simply chosen the names to be intuitively descriptive. |
| Line 290... | Line 290... | ||
| 290 | programming language specification and passes only the basic semantic checks (proper number |
290 | programming language specification and passes only the basic semantic checks (proper number |
| 291 | and types of arguments passed to functions, etc.). It is perhaps not very surprising that |
291 | and types of arguments passed to functions, etc.). It is perhaps not very surprising that |
| 292 | these decisions can be made by any plain C compiler. However, with the current implementation |
292 | these decisions can be made by any plain C compiler. However, with the current implementation |
| 293 | of HelenOS even this is not quite trivial. |
293 | of HelenOS even this is not quite trivial. |
| 294 | |
294 | |
| 295 | Besides the requirement to support 7 hardware platforms, the system's compile-time configuration |
295 | Besides the requirement to support 7 hardware platforms, the system's com\-pile-time configuration |
| 296 | can be also affected by approximately 65 configuration options, most of which are booleans, |
296 | can be also affected by approximately 65 configuration options, most of which are booleans, |
| 297 | the rest are enumerated types. |
297 | the rest are enumerated types. |
| 298 | |
298 | |
| 299 | These configuration options are bound by logical propositions in conjunctive or disjunctive |
299 | These configuration options are bound by logical propositions in conjunctive or disjunctive |
| 300 | normal forms and while some options are freely configurable, the value of others gets inferred |
300 | normal forms and while some options are freely configurable, the value of others gets inferred |
| Line 431... | Line 431... | ||
| 431 | On the first sight it does not seem to be reasonable to consider general model checkers as |
431 | On the first sight it does not seem to be reasonable to consider general model checkers as |
| 432 | relevant independent tools for formal verification of an existing OS. While many different |
432 | relevant independent tools for formal verification of an existing OS. While many different |
| 433 | tools use model checkers as their backends, verifying a complete model of the entire |
433 | tools use model checkers as their backends, verifying a complete model of the entire |
| 434 | system created by hand seems to be infeasible both in the sense of time required for the model |
434 | system created by hand seems to be infeasible both in the sense of time required for the model |
| 435 | creation and resources required by the checker to finish the exhaustive traversal of the model's |
435 | creation and resources required by the checker to finish the exhaustive traversal of the model's |
| 436 | address space. |
436 | state space. |
| 437 | |
437 | |
| 438 | Nevertheless, model checkers on their own can still serve a good job verifying abstract |
438 | Nevertheless, model checkers on their own can still serve a good job verifying abstract |
| 439 | properties of key algorithms without dealing with the technical details of the implementation. |
439 | properties of key algorithms without dealing with the technical details of the implementation. |
| 440 | Various properties of synchronization algorithms, data structures and communication protocols |
440 | Various properties of synchronization algorithms, data structures and communication protocols |
| 441 | can be verified in the most generic conditions by model checkers, answering the |
441 | can be verified in the most generic conditions by model checkers, answering the |
| Line 472... | Line 472... | ||
| 472 | \item[Horizontal compliance] Also called \emph{compatibility}. The goal is to check |
472 | \item[Horizontal compliance] Also called \emph{compatibility}. The goal is to check |
| 473 | whether the specifications of components that are bound together are semantically |
473 | whether the specifications of components that are bound together are semantically |
| 474 | compatible. All required interfaces need to be bound to provided interfaces and |
474 | compatible. All required interfaces need to be bound to provided interfaces and |
| 475 | the communication between the components cannot lead to \emph{no activity} (a deadlock), |
475 | the communication between the components cannot lead to \emph{no activity} (a deadlock), |
| 476 | \emph{bad activity} (a livelock) or other communication and synchronization errors. |
476 | \emph{bad activity} (a livelock) or other communication and synchronization errors. |
| 477 | \item[Vertical compliance] Also called \emph{substituability}. The goal is to check whether |
477 | \item[Vertical compliance] Also called \emph{substituability}. The goal is to check whe\-ther |
| 478 | it is possible to replace a set of primitive components that are nested inside a composite |
478 | it is possible to replace a set of primitive components that are nested inside a composite |
| 479 | component by the composite component itself. In other words, this compliance can answer the |
479 | component by the composite component itself. In other words, this compliance can answer the |
| 480 | questions whether the architecture description of the system is sound with respect to the hierarchical |
480 | question whether the architecture description of the system is sound with respect to the hierarchical |
| 481 | composition of the components. |
481 | composition of the components. |
| 482 | \item[Compliance between the specification and the implementation] Using various means |
482 | \item[Specification and implementation compliance] Using various means |
| 483 | for generating artificial environments for an isolated component the checker is able to |
483 | of generating artificial environments for an isolated component a checker is able to |
| 484 | partially answer the question whether the implementation of the component is an instantiation |
484 | partially answer the question whether the implementation of the component is an instantiation |
| 485 | of the component specification. |
485 | of the component specification. |
| 486 | \end{description} |
486 | \end{description} |
| 487 | \item[Description as abstraction] Generating the behavior and architecture description from the |
487 | \item[Description as abstraction] Generating the behavior and architecture description from the |
| 488 | source code by means of abstract interpretation can serve the purpose of verifying various |
488 | source code by means of abstract interpretation can serve the purpose of verifying various |
| 489 | properties of the implementation such as invariants, preconditions and postconditions. |
489 | properties of the implementation such as invariants, preconditions and postconditions. |
| 490 | This is similar to static verification, but on the level of component interfaces. |
490 | This is similar to static verification, but on the level of component interfaces. |
| 491 | \end{description} |
491 | \end{description} |
| 492 | |
492 | |
| 493 | Unfortunately, most of the behavior and architecture formalisms are static, which is not quite suitable |
493 | Unfortunately, most of the behavior and architecture formalisms are static, which is not quite suitable |
| 494 | for the dynamic of most OSes. This limitation can be circumvented by considering a relevant |
494 | for the dynamic nature of most OSes. This limitation can be circumvented by considering a relevant |
| 495 | snapshot of the dynamic run-time architecture. This snapshot fixed in time is equivalent to |
495 | snapshot of the dynamic run-time architecture. This snapshot fixed in time is equivalent to |
| 496 | a statically defined architecture. |
496 | a statically defined architecture. |
| 497 | |
497 | |
| 498 | \medskip |
498 | \medskip |
| 499 | |
499 | |
| Line 555... | Line 555... | ||
| 555 | |
555 | |
| 556 | \medskip |
556 | \medskip |
| 557 | |
557 | |
| 558 | We have spoken only about the functional properties. In general, we cannot apply the same formalisms |
558 | We have spoken only about the functional properties. In general, we cannot apply the same formalisms |
| 559 | and methods on extra-functional properties (e.g. timing properties, performance properties, etc.). |
559 | and methods on extra-functional properties (e.g. timing properties, performance properties, etc.). |
| 560 | And although it probably does make a good sense to reason about component composition for the extra-functional |
560 | And although it probably does make a good sense to reason about component composition for the extra-functi\-onal |
| 561 | properties, the exact relation might be different compared to the functional properties. |
561 | properties, the exact relation might be different compared to the functional properties. |
| 562 | |
562 | |
| 563 | The extra-functional properties need to be tackled by our future work. |
563 | The extra-functional properties need to be tackled by our future work. |
| 564 | |
564 | |
| 565 | \section{Evaluation} |
565 | \section{Evaluation} |
| Line 582... | Line 582... | ||
| 582 | most of the verification checks of the compilers. The compilers trip on common bug antipatterns such |
582 | most of the verification checks of the compilers. The compilers trip on common bug antipatterns such |
| 583 | as implicit typecasting of pointer types, comparison of signed and unsigned integer values (danger |
583 | as implicit typecasting of pointer types, comparison of signed and unsigned integer values (danger |
| 584 | of unchecked overflows), the usage of uninitialized variables, the presence of unused local variables, |
584 | of unchecked overflows), the usage of uninitialized variables, the presence of unused local variables, |
| 585 | NULL-pointer dereferencing (determined by conservative local control flow analysis), functions |
585 | NULL-pointer dereferencing (determined by conservative local control flow analysis), functions |
| 586 | with non-void return typed that do not return any value and so on. We treat all compilation warnings |
586 | with non-void return typed that do not return any value and so on. We treat all compilation warnings |
| 587 | as fatal errors, thus the code base must pass without any warnings. |
587 | as fatal errors (\texttt{-Werror}), thus the code base must pass without any warnings. |
| 588 | |
588 | |
| 589 | We also turn on several more specific and strict checks. These checks helped to discover several |
589 | We also turn on several more specific and strict checks. These checks helped to discover several |
| 590 | latent bugs in the source code: |
590 | latent bugs in the source code: |
| 591 | |
591 | |
| 592 | \begin{description} |
592 | \begin{description} |
| Line 634... | Line 634... | ||
| 634 | \subsection{Instrumentation} |
634 | \subsection{Instrumentation} |
| 635 | We are in the process of implementing our own code instrumentation framework which is motivated mainly |
635 | We are in the process of implementing our own code instrumentation framework which is motivated mainly |
| 636 | by the need to support MMU-less architectures in the future. But this framework might be also very helpful |
636 | by the need to support MMU-less architectures in the future. But this framework might be also very helpful |
| 637 | in detecting memory and generic resource leaks. We have not tried \emph{Valgrind}~\cite{valgrind} or any similar |
637 | in detecting memory and generic resource leaks. We have not tried \emph{Valgrind}~\cite{valgrind} or any similar |
| 638 | existing tool because of the estimated complexity to adopt it for the usage in HelenOS. |
638 | existing tool because of the estimated complexity to adopt it for the usage in HelenOS. |
| 639 | |
- | |
| 640 | HelenOS was also scanned by \emph{Coverity}~\cite{coverity} in 2006 when no errors were detected. However, since |
- | |
| 641 | that time the code base has not been analyzed by Coverity. |
- | |
| 642 | |
639 | |
| 643 | \subsection{Static Analyzer} |
640 | \subsection{Static Analyzer} |
| 644 | The integration of various static analyzers into the HelenOS continuous integration process is underway. |
641 | The integration of various static analyzers into the HelenOS continuous integration process is underway. |
| 645 | For the initial evaluation we have used \emph{Stanse}~\cite{stanse} and \emph{Clang Analyzer}~\cite{clanganalyzer}. |
642 | For the initial evaluation we have used \emph{Stanse}~\cite{stanse} and \emph{Clang Analyzer}~\cite{clanganalyzer}. |
| 646 | Both of them showed to be moderately helpful to point out instances of unreachable dead code, use of language |
643 | Both of them showed to be moderately helpful to point out instances of unreachable dead code, use of language |
| 647 | constructs which have ambiguous semantics in C and one case of possible NULL-pointer dereference. |
644 | constructs which have ambiguous semantics in C and one case of possible NULL-pointer dereference. |
| 648 | |
645 | |
| 649 | The open framework of Clang seems to be very promising for implementing domain-specific checks (and at |
646 | The open framework of Clang seems to be very promising for implementing domain-specific checks (and at |
| 650 | the same time it is also a very promising compiler framework). Our mid-term goal is to incorporate some of the features |
647 | the same time it is also a very promising compiler framework). Our mid-term goal is to incorporate some of the features |
| 651 | of Stanse and VCC (see Section \ref{staticverifier2}) into Clang Analyzer. |
648 | of Stanse and VCC (see Section \ref{staticverifier2}) into Clang Analyzer. |
| - | 649 | |
|
| - | 650 | HelenOS was also scanned by \emph{Coverity}~\cite{coverity} in 2006 when no errors were detected. However, since |
|
| - | 651 | that time the code base has not been analyzed by Coverity. |
|
| 652 | |
652 | |
| 653 | \subsection{Static Verifier} |
653 | \subsection{Static Verifier} |
| 654 | \label{staticverifier2} |
654 | \label{staticverifier2} |
| 655 | We have started to extend the source code of HelenOS kernel with annotations understood |
655 | We have started to extend the source code of HelenOS kernel with annotations understood |
| 656 | by \emph{Frama-C}~\cite{framac} and \emph{VCC}~\cite{vcc}. Initially we have targeted simple kernel data structures |
656 | by \emph{Frama-C}~\cite{framac} and \emph{VCC}~\cite{vcc}. Initially we have targeted simple kernel data structures |