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.
Abadi @cite_11 defined full abstraction as the property of a compiler to preserve and reflect observational equivalence. Achieving observational equivalence in the presence of side channels such as timing, is impossible. Instead, robust compilation focuses on only mapping back to the source level a context that induces a certain behavior on a program. The robust compilation property for unsafe languages proposed by Fachini @cite_13 is: [ P C_T t. C_T ( P ) t C_S t'. C_S P t' t' t ]
@cite_13 @cite_11
2854926444 2935586798 2167997514 2089561656
Good programming languages provide helpful abstractions for writing more secure code, but the security properties from the source language are generally not preserved when compiling a program and linking it with adversarial low-level code. Linked low-level code that is malicious or compromised can for instance read and write the compiled program's data and code, jump to arbitrary instructions, or smash the stack, blatantly violating any source-level abstraction. By contrast, a secure compilation chain protects source-level abstractions all the way down, ensuring that even an adversarial target-level context cannot break the security properties of a compiled program any more than some source-level context could. However, the precise class of security properties one chooses to preserve crucially impacts not only the supported security goals and the strength of the attacker model, but also the kind of protections the compilation chain has to introduce and the kind of proof techniques one can use. Since efficiently achieving and proving secure compilation at scale are challenging open problems, designers of secure compilation chains have to strike a pragmatic balance between security and efficiency that matches their application domain. To inform this difficult design decision, we thoroughly explore a large space of secure compilation criteria based on the preservation of properties that are robustly satisfied against arbitrary adversarial contexts. We study robustly preserving classes of trace properties such as safety, of hyperproperties such as noninterference, and of relational hyperproperties such as trace equivalence. For each of the studied classes we propose an equivalent "property-free" characterization that is generally better tailored for proofs. We, moreover, order the secure compilation criteria by their relative strength and prove several separation results. ((((cropped)))) Secure compilers generate compiled code that withstands many target-level attacks such as alteration of control flow, data leaks or memory corruption. Many existing secure compilers are proven to be fully abstract, meaning that they reflect and preserve observational equivalence. Fully abstract compilation is strong and useful but, in certain cases, comes at the cost of requiring expensive runtime constructs in compiled code. These constructs may have no relevance for security, but are needed to accommodate differences between the source and target languages that fully abstract compilation necessarily needs. Crossing abstraction boundaries often incurs a substantial run-time overhead in the form of frequent procedure calls. Thus, pervasive use of abstraction, while desirable from a design standpoint, may lead to very inefficient programs. Aggressively optimizing compilers can reduce this overhead but conflict with interactive programming environments because they introduce long compilation pauses and often preclude source-level debugging. Thus, programmers are caught on the horns of two dilemmas: they have to choose between abstraction and efficiency, and between responsive programming environments and efficiency. This dissertation shows how to reconcile these seemingly contradictory goals. Four new techniques work together to achieve this: - Type feedback achieves high performance by allowing the compiler to inline message sends based on information extracted from the runtime system. - Adaptive optimization achieves high responsiveness without sacrificing performance by using a fast compiler to generate initial code while automatically recompiling heavily used program parts with an optimizing compiler. - Dynamic deoptimization allows source-level debugging of optimized code by transparently recreating non-optimized code as needed. - Polymorphic inline caching speeds up message dispatch and, more significantly, collects concrete type information for the compiler. With better performance yet good interactive behavior, these techniques reconcile exploratory programming, ubiquitous abstraction, and high performance. Safe state abstraction in reinforcement learning allows an agent to ignore aspects of its current state that are irrelevant to its current decision, and therefore speeds up dynamic programming and learning. This paper explores safe state abstraction in hierarchical reinforcement learning, where learned behaviors must conform to a given partial, hierarchical program. Unlike previous approaches to this problem, our methods yield significant state abstraction while maintaining hierarchical optimality, i.e., optimality among all policies consistent with the partial program. We show how to achieve this for a partial programming language that is essentially Lisp augmented with nondeterministic constructs. We demonstrate our methods on two variants of Dietterich's taxi domain, showing how state abstraction and hierarchical optimality result in faster learning of better policies and enable the transfer of learned skills from one problem to another.