extrasafe 0.1.2

Make your code extrasafe by preventing it from calling unneeded syscalls.
Documentation
// Technically this test is redundant since cargo test runs multiple threads in the same process
// and we would see errors there. It's still good documentation though.
//
// TODO we should write a test showing that seccomp filters don't override filters in
// different threads as documentation.

use extrasafe::builtins::SystemIO;

use std::sync::mpsc::sync_channel;
use std::thread;

use std::fs::File;

#[test]
/// When using per-thread contexts, check that you can enabled different filters on different
/// threads. This is achieved in this test by blocking IO on one thread and not on another, and
/// checking IO can be performed in the other thread after loading the context in the first.
fn different_threads_with_different_contexts() {

    // These channels will block on send until the receiver has called recv.
    let (sender1, recv1) = sync_channel::<()>(0);
    let (sender2, recv2) = sync_channel::<()>(0);

    let seccomp_thread = thread::spawn(move || {
        extrasafe::SafetyContext::new()
            .enable(SystemIO::nothing()
                .allow_stdout()
                .allow_stderr()).unwrap()
            .apply_to_current_thread().unwrap();
        // setup_done
        sender1.send(()).unwrap();

        // don't close this thread until the other thread is done asserting. This way we can be
        // sure the thread with the filter is definitely active when the other thread runs.
        let _io_test_passed = recv2.recv().unwrap();
        println!("exit seccomp thread");
    });

    let io_thread = thread::spawn(move || {
        let _setup_done = recv1.recv().unwrap();

        let dir = tempfile::tempdir().unwrap();
        let mut path = dir.path().to_path_buf();
        path.push("can_open.txt");

        let res = File::create(&path);
        assert!(
            res.is_ok(),
            "Failed to open file even though there's no seccomp filter loaded in this thread."
        );

        // io_test_passed
        sender2.send(()).unwrap();
        println!("exit io thread");
    });

    let seccomp_res = seccomp_thread.join();
    assert!(
        seccomp_res.is_ok(),
        "seccomp thread failed: {:?}",
        seccomp_res.unwrap_err()
    );
    let io_res = io_thread.join();
    assert!(
        io_res.is_ok(),
        "io thread failed: {:?}",
        io_res.unwrap_err()
    );
}