Today's software needs to isolate not only processes but the many components within a process from each other. Process-level isolation via jails, sandboxes, VMs, or hypervisors is finally becoming mainstream, but it misses an important point about modern software: its growing number of libraries that are all loaded into the same address space, and may all interact with complex inputs by way of vulnerable parsers. A process, even isolated, is as weak as the weakest of its components, but is as valuable as the most sensitive data it holds. Heartbleed was a perfect example of this: a faulty parser in a library could read absolutely everything in memory; there are many others less famous but no better. The biggest challenge of making intra-process memory protection practical is that it cannot require major changes to how software is written. A practical granular memory protection scheme must work for the existing C/C++ build chains, nor should it change the ABI. Further, it cannot rely on concepts that aren't already intuitively clear to C/C++ programmers. Many academic proposals for more granular memory access control stopped short of this. They disregard the glue what keeps the development process and runtime together: the ABI.
We demonstrate ELFbac, a system that uses the Linux ELF ABI to express access control policies between a program's components, such as libraries, and requires no changes to the GNU build chain. It enforces these policies by using a modified Linux loader and the Linux virtual memory system. ELFbac policies operate on the level of ELF object file sections. Custom data and code units can be created with existing GCC C/C++ attributes with a one-line annotation per unit; they are no more complex than C's static scoping. We have developed prototypes for ARM and x86. We used our ARM prototype to protect a validating proxy firewall for DNP3, a popular ICS protocol, and our x86 one to write a basic policy for Nginx. We will also demonstrate a policy for protecting OpenSSH.