Memory corruption vulnerabilities are endemic to unsafe languages, such as C, and they can even be found in safe languages that themselves are implemented in unsafe languages or linked with libraries implemented in unsafe languages. Robust compilation mitigates the threat of linking with memory-unsafe libraries. The source language is a C-like language, enriched with a notion of a component which encapsulates data and code, exposing functionality through well-defined interfaces. Robust compilation defines what security properties a component still has, even, if one or more components are compromised. The main contribution of this work is to demonstrate that the compartmentalization necessary for a compiler that has the robust compilation property can be realized on a basic RISC processor using software fault isolation.
Software fault isolation was proposed in 1993 by Wahbe @cite_14 . A distrusted module is sandboxed into its own fault domain, a logical region of the address space. To prevent it from modifying data or executing code belonging to the rest of the application, its object code is instrumented. The physical address is split logically into a segment id and offset, and the introduced instrumentation does not allow writes outside the data domain and execution to escape the code domain, other than predefined exit points. Many applications that use software fault isolation followed. Google's Native Client @cite_3 uses software fault isolation to sandbox C C++ code in the Chrome web browser. Morrissett @cite_6 proposed a semantics of the x86 architecture and constructed a machine verified checker of Native Client. ARMor @cite_2 is a machine verified system that uses software isolation to sandbox application code running on embedded processors. In this research, we combine ideas from this previous work and apply them to support robust compilation on a processor without specialized hardware.
@cite_14 @cite_6 @cite_3 @cite_2
2079029390 2009248821 2105842205 2138538875
One way to provide fault isolation among cooperating software modules is to place each in its own address space. However, for tightly-coupled modules, this solution incurs prohibitive context switch overhead. In this paper, we present a software approach to implementing fault isolation within a single address space.Our approach has two parts. First, we load the code and data for a distrusted module into its own fault do main, a logically separate portion of the application's address space. Second, we modify the object code of a distrusted module to prevent it from writing or jumping to an address outside its fault domain. Both these software operations are portable and programming language independent.Our approach poses a tradeoff relative to hardware fault isolation: substantially faster communication between fault domains, at a cost of slightly increased execution time for distrusted modules. We demonstrate that for frequently communicating modules, implementing fault isolation in software rather than hardware can substantially improve end-to-end application performance. Software-based fault isolation (SFI), as used in Google's Native Client (NaCl), relies upon a conceptually simple machine-code analysis to enforce a security policy. But for complicated architectures such as the x86, it is all too easy to get the details of the analysis wrong. We have built a new checker that is smaller, faster, and has a much reduced trusted computing base when compared to Google's original analysis. The key to our approach is automatically generating the bulk of the analysis from a declarative description which we relate to a formal model of a subset of the x86 instruction set architecture. The x86 model, developed in Coq, is of independent interest and should be usable for a wide range of machine-level verification tasks. This paper describes the design, implementation and evaluation of Native Client, a sandbox for untrusted x86 native code. Native Client aims to give browser-based applications the computational performance of native applications without compromising safety. Native Client uses software fault isolation and a secure runtime to direct system interaction and side effects through interfaces managed by Native Client. Native Client provides operating system portability for binary code while supporting performance-oriented features generally absent from web application programming environments, such as thread support, instruction set extensions such as SSE, and use of compiler intrinsics and hand-coded assembler. We combine these properties in an open architecture that encourages community review and 3rd-party tools. We have designed and implemented ARMor, a system that uses software fault isolation (SFI) to sandbox application code running on small embedded processors. Sandboxing can be used to protect components such as the RTOS and critical control loops from other, less-trusted components. ARMor guarantees memory safety and control flow integrity; it works by rewriting a binary to put a check in front of every potentially dangerous operation. We formally and automatically verify that an ARMored application respects the SFI safety properties using the HOL theorem prover. Thus, ARMor provides strong isolation guarantees and has an exceptionally small trusted computing base - there is no trusted compiler, binary rewriter, verifier, or operating system.