Computer Laboratory

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

  • Robert N. M. Watson, Steven J. Murdoch, Khilan Gudka, Jonathan Anderson, Peter G. Neumann, and Ben Laurie. Towards a theory of application compartmentalisation. Security Protocols Workshop, March, 2013.
  • 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

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 10.0.
  • 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=Release -DBUILD_SHARED_LIBS=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 -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=ON -DLLVM_DIR=`pwd`/../../llvm/Build/share/llvm/cmake -DCMAKE_C_COMPILER=`pwd`/../../llvm/Build/bin/clang -DCMAKE_CXX_COMPILER=`pwd`/../../llvm/Build/bin/clang++ ..
[me@mymachine ~/workspace/soaap/Build]$ ninja

Everything is built and ready to use!

Annotations

SOAAP currently supports the following annotations (see ~/workspace/soaap/include/soaap.h):

Annotations for specifying control-flow information

__soaap_fp(fns...)

Annotation on a function pointer specifying the possible callee targets of the pointer. This can be used for local variables and struct members.

Example:

struct mystruct { 
  void (*myfp)() __soaap_fp(b, c);
};

void a(struct mystruct* s); 
void b();
void c();

int main(int argc, char** argv) {
  struct mystruct s;
  s.myfp = (...) ? b : c;
  a(&s);
  return 0;
}

__soaap_sandbox_persistent("mysandbox")
void a(struct mystruct* s) {
  s->myfp();
  printf("hello from a!\n");
}

void b() {
  printf("hello from b!\n");
}

void c() {
  printf("hello from c!\n");
}

Annotations for specifying sandboxed code scopes

__soaap_sandbox_persistent(N)

Function-level annotation specifying that this function should execute in the single global persistent sandbox. N is the name associated with the sandbox. This name will be necessary when annotating data as being private to a particular sandbox (see below).

Example:

__soaap_sandbox_persistent("network")
void foo(int a, int b) {
  ...
}

__soaap_sandbox_ephemeral(N)

Function-level annotation specifying that this function should execute in a fresh sandbox, each time it is invoked. N is the name associated with the sandbox. This name will be necessary when annotating data as being private to a particular sandbox (see below). In some sense, the name here refers to the group of sandboxes that are created for invocations of the function.

Example:

__soaap_sandbox_ephemeral("codec")
void foo(int a, int b) {
    ...
}

__soaap_sandboxed_region_start(N)

Annotation to mark the start of a non-function sandboxed region. N is the name of this sandbox.

Example:

__soaap_sandboxed_region_start("renderer");
...
...
...
__soaap_sandboxed_region_end("renderer");

__soaap_sandboxed_region_end(N)

Annotation to mark the end of a non-function sandboxed region. N is the name of this sandbox.

Example:

__soaap_sandboxed_region_start("renderer");
...
...
...
__soaap_sandboxed_region_end("renderer");

Annotations for validating the functional correctness of a compartmentalisation hypothesis

__soaap_var_read(N)

Global variable annotation specifying that the variable can be read by sandbox N.

Example:

int x __soaap_var_read("parser");
int y;

int main(int argc, char** argv) {
    ...
}

__soaap_var_write(N)

Global variable annotation specifying that the variable can be written to by sandbox N.

Example:

int x;
int y __soaap_var_write("auth");

int main(int argc, char** argv) {
    ...
}

__soaap_fd_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_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_read, FILE* out) {
    ...
    fread(inbuf, 1, 10, in);
    ...
}

__soaap_fd_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_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_write) {
    ...
    fwrite(outbuf, 1, 10, out);
    ...
}

__soaap_callgates(N, fns...)

Global scope annotation specifying a list of privileged callgates that sandbox N is allowed to invoke.

Example:

__soaap_callgates("network", getservbyname, gethostbyname)

int main(int argc, char** argv) {
    ...
}

Annotations for specifying the data isolation requirements of a compartmentalisation hypothesis

__soaap_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(N) above).

Example:

int x; // global variable

__soaap_sandbox_persistent("box")
void foo() {
  int key __soaap_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 specifying past-vulnerability information

The intended definition of vulnerability for the following annotations is the point at whcih an attacker may gain control.

__soaap_vuln_fn(CVE)

Function-level annotation for indicating that the function contains a vulnerability (somewhere inside it). The argument is the CVE string.

Example:

__soaap_vuln_fn("CVE-2013-0000")
void foo() {
  ...
}

__soaap_vuln_pt(CVE)

Used at a particular program point to indicate that there was a vulnerability here in the past. The argument is the CVE string.

Example:

void foo(int* p) {
  if (p != NULL) {
    __soaap_vuln_pt("CVE-2012-0000");
    *p = 1;
  }
}

Annotations for emulating the performance of a compartmentalisation hypothesis

__soaap_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_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_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%