CTSRD
Security-Oriented Analysis of Application Programs (SOAAP)
Sandboxing technologies such as Capsicum and CHERI support the fine-grained compartmentalisation of large-scale applications such as web browsers and office suites, as well as multiple-component software such as the UNIX userspace. When deployed correctly, application compartmentalisation offers significant benefits by allowing policies to be imposed within applications, and in mitigating exploited vulnerabilities. However, application compartmentalisation remains an art rather than a science: identifying, implementing, and debugging partitioning strategies requires detailed expertise in both the application and security. SOAAP is exploring semi-automated techniques, grounded in static analysis, dynamic analysis, and automated program transformation, to improve the developer experience. This project is jointly funded by Google and DARPA, and takes place within the context of the CTSRD project.
Conference and journal papers
- William R. Harris (University of Wisconsin, Madison), Somesh Jha (University of Wisconsin, Madison), Thomas Reps (University of Wisconsin, Madison), Jonathan Anderson (University of Cambridge), and Robert N. M. Watson (University of Cambridge). Declarative, Temporal, and Practical Programming with Capabilities. IEEE Symposium on Security and Privacy ("Oakland"), May, 2013.
Workshop papers
- Khilan Gudka, Robert N. M. Watson, Steven Hand, Ben Laurie, and Anil Madhavapeddy. Exploring compartmentalisation hypotheses with SOAAP. Workshop paper, Adaptive Host and Network Security (AHANS 2012), September, 2012.
Presentations
- Khilan Gudka, Robert N. M. Watson, Steven Hand, Ben Laurie, and Anil Madhavapeddy. Exploring compartmentalisation hypotheses with SOAAP. Workshop presentation, Adaptive Host and Network Security (AHANS 2012), September, 2012.
Building SOAAP and related tools
We are pleased to announce that an early prototype version of the Clang/LLVM- based SOAAP toolchain is now available to try out. Please send any queries to Khilan Gudka and Robert Watson.
Some preliminary notes:
- Currently SOAAP is built, run and tested on FreeBSD 9.1.
- Create a directory in which all soaap-related files will reside. In these instructions, we will assume the directory '/home/me/workspace' is used for this purpose.
- CMake >= 2.8.9 and Ninja 1.0.0 are required to build Clang/LLVM and the Soaap LLVM pass.
LLVM/Clang
[me@mymachine ~/workspace]$ git clone https://github.com/CTSRD-SOAAP/llvm.git
[me@mymachine ~/workspace]$ cd llvm
[me@mymachine ~/workspace/llvm]$ git checkout working
[me@mymachine ~/workspace/llvm]$ cd tools
[me@mymachine ~/workspace/llvm/tools]$ git clone https://github.com/CTSRD-SOAAP/clang.git
[me@mymachine ~/workspace/llvm/tools]$ cd clang
[me@mymachine ~/workspace/llvm/tools/clang]$ git checkout working
[me@mymachine ~/workspace/llvm/tools/clang]$ cd ../..
[me@mymachine ~/workspace/llvm]$ mkdir Build
[me@mymachine ~/workspace/llvm]$ cd Build
[me@mymachine ~/workspace/llvm/Build]$ cmake -G Ninja -DCMAKE_BUILD_TYPE:STRING=Debug -DBUILD_SHARED_LIBS:BOOL=ON -DCMAKE_CXX_COMPILER="/usr/bin/clang++" -DCMAKE_CXX_FLAGS="-O1 -idirafter /usr/local/include" -DCMAKE_C_COMPILER="/usr/bin/clang" -DCMAKE_C_FLAGS="-idirafter /usr/local/include" ..
[me@mymachine ~/workspace/llvm/Build]$ ninja (note: you can customise the number of threads used by ninja using the -j flag)
SOAAP LLVM Pass
[me@mymachine ~/workspace/llvm/Build]$ cd ../..
[me@mymachine ~/workspace]$ git clone https://github.com/CTSRD-SOAAP/soaap.git
[me@mymachine ~/workspace]$ cd soaap
[me@mymachine ~/workspace/soaap]$ mkdir Build
[me@mymachine ~/workspace/soaap]$ cd Build
[me@mymachine ~/workspace/soaap/Build]$ cmake -G Ninja -DLLVM_SOURCE_DIR:String=`pwd`/../../llvm -DLLVM_BINARY_DIR:String=`pwd`/../../llvm/Build ..
[me@mymachine ~/workspace/soaap/Build]$ ninja
Everything is built and ready to use!
Annotations
Annotations for validating the functional correctness of a compartmentalisation hypothesis
SOAAP currently supports the following annotations (see ~/workspace/soaap/include/soaap.h):
__soaap_sandbox_persistent
Function-level annotation specifying that this function should execute in the single global persistent sandbox.
Example:
__soaap_sandbox_persistent
void foo(int a, int b) {
...
}
__soaap_sandbox_persistent_named(N)
Same as __soaap_sandbox_persistent, except that a name can be associated with a persistent sandbox. This will be necessary when annotating data as being private to a particular sandbox (see below).
Example:
__soaap_sandbox_persistent_named("network")
void foo(int a, int b) {
...
}
__soaap_sandbox_ephemeral
Function-level annotation specifying that this function should execute in a fresh sandbox, each time it is invoked.
Example:
__soaap_sandbox_ephemeral
void foo(int a, int b) {
...
}
__soaap_var_allow_read
Global variable annotation specifying that the variable can be read from a sandbox.
Example:
int x __soaap_var_allow_read;
int y;
int main(int argc, char** argv) {
...
}
__soaap_var_allow_write
Global variable annotation specifying that the variable can be written to by a sandbox.
Example:
int x;
int y __soaap_var_allow_write;
int main(int argc, char** argv) {
...
}
__soaap_fd_allow_read
Function parameter annotation specifying that the file corresponding to the annotated file descriptor can be read via the read() system call by a sandbox.
Example:
int compress(int in __soaap_fd_allow_read, int out) {
...
read(in, inbuf, 10);
...
}
This annotation can be applied to an integer file descriptor or to a pointer to a struct that contains a file descriptor. For example:
int compress(FILE* in __soaap_fd_allow_read, FILE* out) {
...
fread(inbuf, 1, 10, in);
...
}
__soaap_fd_allow_write
Function parameter annotation specifying that the file corresponding to the annotated file descriptor can be written to via the write() system call by a sandbox.
Example:
int compress(int in, int out __soaap_fd_allow_write) {
...
write(out, outbuf, 10);
...
}
This annotation can be applied to an integer file descriptor or to a pointer to a struct that contains a file descriptor. For example:
int compress(FILE* in, FILE* out __soaap_fd_allow_write) {
...
fwrite(outbuf, 1, 10, out);
...
}
__soaap_callgates(fns...)
Global scope annotation specifying a list of privileged functions that are considered to be callgates and can thus be invoked by a sandbox.
Example:
__soaap_callgates(getservbyname, gethostbyname)
int main(int argc, char** argv) {
...
}
Annotations for specifying the data isolation requirements of a compartmentalisation hypothesis
__soaap_sandbox_private(N)
This annotation can be applied to global variables, struct fields and local variables. It specifies that the annotated data item is private to the persistent sandbox named N (see __soaap_sandbox_persistent_named(N) above).
Example:
int x; // global variable
__soaap_sandbox_persistent_named("box")
void foo() {
int key __soaap_sandbox_private("box");
key = 813;
x = key; // a leak - output warning!
}
__soaap_classify(L) and _soaap_clearance(L)
Allows assigning a confidentiality label L to a struct field or global variable. A sandbox has to be given explicit clearance to access such a data item, using the __soaap_clearance(L) annotation.
Example:
int key __soaap_classify("secret");
__soaap_sandbox_persistent __soaap_clearance("secret")
int encrypt() {
// ... access key ...
}
__soaap_sandbox_ephemeral
void foo() {
key = 1; // disallowed access - output warning!
}
Annotations for emulating the performance of a compartmentalisation hypothesis
__soaap_sandbox_overhead(X)
Function-level annotation indicating the maximum overhead (X is a percentage) you are willing to accept/tolerate. If this is exceeded, a report will be triggered.
Example:
__soaap_sandbox_ephemeral __soaap_sandbox_overhead(80)
int foo() {
...
}
__soaap_data_in
Function parameter (integer type) annotation for indicating that this parameter corresponds to the number of bytes that should be passed as a message to the sandbox. The function needs to have been tagged with __soaap_sandbox_{ephemeral,persistent} as well.
Example:
__soaap_sandbox_ephemeral __soaap_sandbox_overhead(12)
int subtract(int a, int b, int len __soaap_data_in) { // len is the size of a in bytes
return a-b;
}
Running SOAAP on programs
Generating LLVM IR
To run SOAAP on a program, you must first compile all the C files to LLVM IR and if there are several files, link them together into a single LLVM IR file. To compile to LLVM IR, use the following command:
[me@mymachine ~/workspace/scratch]$ clang -cc1 -I ~/workspace/soaap/include -emit-llvm file1.c file2.c file3.c [me@mymachine ~/workspace/scratch]$ llvm-link -o myprog.ll file1.ll file2.ll file3.ll
This produces the LLVM IR file myprog.ll by linking the individual LLVM IR files.
Generating a dynamic call graph
To perform the necessary instrumentation for dynamic call graph generation, execute the following:
[me@mymachine ~/workspace/scratch]$ opt -load ~/workspace/soaap/Build/libcep.so -insert-call-edge-profiling -o myprog.pll myprog.ll
myprog.pll now contains the needed instrumentation. Next, create an executable as follows:
[me@mymachine ~/workspace/scratch]$ llc -filetype=obj myprog.pll [me@mymachine ~/workspace/scratch]$ clang -L ~/workspace/soaap/Build -L ~/workspace/llvm/Build/lib -lprofile_rt -lcep_rt -o myprog myprog.pll.o
Finally execute the program to create an llvmprof.out file containing the dynamic call graph. Make sure that your LD_LIBRARY_PATH is set correctly:
[me@mymachine ~/workspace/scratch]$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:~/workspace/soaap/Build:~/workspace/llvm/Build/lib [me@mymachine ~/workspace/scratch]$ ./myprog
Running SOAAP
Having generated a dynamic call graph, you can now run the SOAAP analysis on myprog.ll as follows:
[me@mymachine ~/workspace/scratch]$ opt -load ~/workspace/soaap/Build/libsoaap.so -soaap -profile-loader -o myprog-soaap.ll myprog.ll
If you specified any performance simulation annotations, then SOAAP will have inserted instrumentation appropriately. To perform the simulation, you need to create an executable and run it:
[me@mymachine ~/workspace/scratch]$ llc -filetype=obj myprog-soaap.ll [me@mymachine ~/workspace/scratch]$ clang -o myprog-soaap myprog-soaap.o [me@mymachine ~/workspace/scratch]$ ./myprog-soaap soaap_perf_tic [215] SANDBOXED FUNCTION PROLOGUE -- TIC! soaap_perf_enter_datain_persistent_sbox [59] Emulating performance of using persistent sandbox. soaap_perf_enter_datain_persistent_sbox [103] DATALEN: 16 soaap_perf_enter_datain_persistent_sbox [122] PARENT: written to the pipe 16 bytes soaap_perf_overhead_toc [222] SANDBOXED FUNCTION OVERHEAD -- SBOX_TOC! Result: 16 [!!!] Sandboxing Overhead 69.998658% (Threshold: 12%) soaap_perf_total_toc_thres [303] [Total Execution Time]: 22349 ns, [Sandboxing Time]: 15644 ns, [Sandboxing Overhead]: 69.998658%
