Type Systems For Safer Code

What is a type system?

Types are a tool for describing your program.

fn main() {
    let an_integer: u64 = 123;
    let a_float: f64 = 1.2;
    let a_string: String = "hello".to_owned();
}

Rust

C++

int main(int argc, char const *argv[]) {
  int an_int = 5;
  float a_float = 1.0;
  std::string a_str = "hello";
  return 0;
}
if __name__ == '__main__':
    an_integer = 5
    a_float = 1.0
    a_string = "Hello"

Python

Vulnerabilities By Type - Firefox


https://www.cvedetails.com/product/3264/Mozilla-Firefox.html?vendor_id=452

#include <iostream>

void vuln(int ** f) {
  int x = 5;
  *f = &x;
}

int main(int argc, char const *argv[]) {
  int * foo = 0;
  std::cout << foo << std::endl;

  vuln(&foo);

  std::cout << foo << std::endl;
  return 0;
}
#include <iostream>

struct Foo {
  int bar[2];
  int baz;
};

int main(int argc, char const *argv[]) {
  struct Foo foo;
  foo.baz = 0;
  foo.bar[0] = 1;
  foo.bar[1] = 2;
  foo.bar[2] = 3;

  std::cout << foo.bar[2] << std::endl;
  std::cout << foo.baz << std::endl;
  return 0;
}
void threaded_push(vector<size_t>& v, size_t i) {
  v.push_back(i);
}

int main(int argc, char const *argv[]) {

  vector<size_t> values;
  std::vector<std::thread> threads;

  for (size_t i = 0; i < 16; i++) {
    threads.push_back(std::thread(threaded_push, std::ref(values), i));
  }

  for (size_t i = 0; i < 16; i++) {
    threads[i].join();
  }
  return 0;
}

Exploitable By Default

  • Unchecked array bounds
  • Manual, unchecked memory management
  • Unmanaged mutable state and raw pointers
  • Manually managed, unchecked concurrency

Modeling composite state machines is not easy.

We systematically tested popular open-source TLS implementations for state machine bugs and discover several new critical security vulnerabilities that have lain hidden in these libraries for years.

“The [TLS] state machine is a big thing,” Salz said. “The whole mechanism, the kindest thing we can say, is that it grew organically. It started with SSL v2, grew from there and things got out of control. That’s one of our big areas, the source of many vulnerabilities and bugs in OpenSSL.”
 

Rich Salz, OpenSSL, on gotofail

 

https://threatpost.com/openssl-past-present-and-future/112485/

Safe Code vs Fast Code

long fib(long n) {
  long a = 1;
  long b = 1;
  for (size_t i = 0; i < n - 2; i++) {
    long tmp = b;
    b = a + b;
    a = tmp;
  }
  return b;
}

C++ (clang): 300ms

public class fib {

  public static long f(long n){
    long a = 1;
    long b = 1;
    for (long i = 0; i < n - 2; i++) {
      long tmp = b;
      b = a + b;
      a = tmp;
    }
    return b;
  }...

}

Java: 530ms

Speed

Safety

Speed

Safety

?

Fast, Safe

  • No data races
  • No dangling pointers
  • No implicit unchecked array access
  • Expressable type system
  • 0 Cost abstractions
fn consume_var(v: Foo) {
    drop(v); // Equivalent to delete / free
}

struct Foo {
    pub bar: u64,
}

fn main() {
    // Initialize our Foo variable on the stack
    let stack_var = Foo { bar: 100 };
    // Hold a reference to that variable
    let stack_ref = &stack_var;
    // Attempt to drop variable while we still hold a reference to it
    consume_var(stack_var);
    // Attempt to print out the variable after drop
    println!("{}", *stack_ref);
}
src/bin/vuln.rs:13:17: 13:26 error: cannot move out of `stack_var` because it is borrowed [E0505]
src/bin/vuln.rs:13     let stack_ref = &stack_var;
                                        ^~~~~~~~~
    +--------------------------+
    |     intiial state        |
    +--------------------------+
                ||    /\ error
                || ===||
                ||
                \/ success
        +------------------+
        |intermediate state|
        +------------------+
                ||    /\ error
                || ===||
                ||
                \/ success
   +---------------------------+
   |        Final State        |
   +---------------------------+

Type Safe State Machines

 

enum StateMachine {
    InitialState,
    IntermediateState,
    FinalState,
}

fn advanced_state(cur_state: StateMachine) -> StateMachine {
    match cur_state {
        StateMachine::InitialState => StateMachine::IntermediateState,
        StateMachine::IntermediateState => StateMachine::FinalState,
        StateMachine::FinalState => panic!("Can not advance beyond final state"),
    }
}

fn main() {
    let mut state = StateMachine::InitialState;

    loop {
        match state {
            StateMachine::InitialState => state = advanced_state(state),
            StateMachine::IntermediateState => state = advanced_state(state),
            StateMachine::FinalState => break,
        }
    }
}

Type Safe State Machines

 

#[derive(Debug)]
struct InitialState;
#[derive(Debug)]
struct IntermediateState;
#[derive(Debug)]
struct FinalState;

impl InitialState {
    fn transition(self) -> Result<IntermediateState, InitialState> {
        Ok(IntermediateState {})
    }
}
impl IntermediateState {
    fn transition(self) -> Result<FinalState, IntermediateState> {
        Err(self)
    }
}
impl FinalState {
    fn consume(self) -> Result<(), FinalState> {
        Ok(())
    }
}

fn main() {
    let init = InitialState {};
    let intermediate = init.transition().unwrap();

    let final_s = match intermediate.transition() {
        Ok(f) => f,
        Err(old_state) => panic!("State transition failed, in old state."),
    };

    final_s.consume().unwrap();
}

Fearless Concurrency

use std::thread;

fn push_item(vec: &mut Vec<usize>, i: usize) {
    vec.push(i);
}

fn main() {
    let mut v = Vec::new();

    for i in 0..16 {
        thread::spawn(move || {
            v.push(i);
        });
    }
}
src/bin/vuln.rs:12:13: 12:14 error: capture of moved value: `v` [E0382]
src/bin/vuln.rs:12         thread::spawn(move || {
                                         ^~~~~~~

What's the Cost?

fn fib(n: u64) -> u64 {
    let mut a: u64 = 1;
    let mut b: u64 = 1;

    for _ in 0..n - 2 {
        let tmp: u64 = b;
        b = a + b;
        a = tmp;
    }

    return b;
}

Rust: 300ms

long fib(long n) {
  long a = 1;
  long b = 1;
  for (size_t i = 0; i < n - 2; i++) {
    long tmp = b;
    b = a + b;
    a = tmp;
  }
  return b;
}

C++: 300ms

Questions?

Type Systems For Safety

By insanitybit

Type Systems For Safety

  • 874