Build minijail as rust crate

minijail isn't packaged for normal Linux systems. Package it as a crate so it
can be built into the crosvm binary when minijail isn't available via
pkg-config.

BUG=chromium:1032360
TEST=cargo build

Change-Id: I7939d02399b28fe55fcd53fddec246e6129b4181
diff --git a/.gitignore b/.gitignore
index fed0adb..51cd2e7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,3 +37,8 @@
 
 # Google Test.
 googletest-release*
+
+# Cargo build targets.
+/target
+**/*.rs.bk
+Cargo.lock
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..6954d53
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,16 @@
+[package]
+name = "minijail-sys"
+version = "0.0.11"
+authors = ["The Chromium OS Authors"]
+edition = "2018"
+build = "build.rs"
+
+[lib]
+path = "lib.rs"
+
+[dependencies]
+libc = "0.2.44"
+
+[build-dependencies]
+cc = "1.0"
+pkg-config = "0.3"
diff --git a/Makefile b/Makefile
index 4bfa820..07336f2 100644
--- a/Makefile
+++ b/Makefile
@@ -79,6 +79,9 @@
 CC_LIBRARY(libminijail.so): $(CORE_OBJECT_FILES)
 clean: CLEAN(libminijail.so)
 
+CC_STATIC_LIBRARY(libminijail.pic.a): $(CORE_OBJECT_FILES)
+CC_STATIC_LIBRARY(libminijail.pie.a): $(CORE_OBJECT_FILES)
+clean: CLEAN(libminijail.*.a)
 
 CXX_BINARY(libminijail_unittest): CXXFLAGS += -Wno-write-strings \
 						$(GTEST_CXXFLAGS)
diff --git a/OWNERS b/OWNERS
index 6b8fd58..c934dbf 100644
--- a/OWNERS
+++ b/OWNERS
@@ -4,3 +4,6 @@
 drewry@google.com
 keescook@google.com
 vapier@google.com
+
+per-file Cargo.toml = file:/OWNERS.rust
+per-file *.rs = file:/OWNERS.rust
diff --git a/OWNERS.rust b/OWNERS.rust
new file mode 100644
index 0000000..1db5ac3
--- /dev/null
+++ b/OWNERS.rust
@@ -0,0 +1,6 @@
+# Copyright 2019 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+smbarber@google.com
+zachr@google.com
diff --git a/build.rs b/build.rs
new file mode 100644
index 0000000..51cef31
--- /dev/null
+++ b/build.rs
@@ -0,0 +1,40 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// Minijail's build script invoked by cargo.
+///
+/// This script prefers linking against a pkg-config provided libminijail, but will fall back to
+/// building libminijail statically.
+use std::env;
+use std::io;
+use std::process::Command;
+
+fn main() -> io::Result<()> {
+    // Minijail requires libcap at runtime.
+    pkg_config::Config::new().probe("libcap").unwrap();
+
+    // Prefer a system-provided Minijail library.
+    if pkg_config::Config::new().probe("libminijail").is_ok() {
+        return Ok(());
+    }
+
+    let current_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
+    let out_dir = env::var("OUT_DIR").unwrap();
+    let profile = env::var("PROFILE").unwrap();
+
+    let status = Command::new("make")
+        .current_dir(&out_dir)
+        .env("OUT", &out_dir)
+        .env("MODE", if profile == "release" { "opt" } else { "debug" })
+        .arg("-C")
+        .arg(&current_dir)
+        .arg("CC_STATIC_LIBRARY(libminijail.pic.a)")
+        .status()?;
+    if !status.success() {
+        std::process::exit(status.code().unwrap_or(1));
+    }
+    println!("cargo:rustc-link-search=native={}", &out_dir);
+    println!("cargo:rustc-link-lib=static=minijail.pic");
+    Ok(())
+}
diff --git a/lib.rs b/lib.rs
new file mode 100644
index 0000000..3206bde
--- /dev/null
+++ b/lib.rs
@@ -0,0 +1,42 @@
+// Copyright 2019 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// libminijail bindings for Rust.
+
+// TODO(crbug.com/1032672): Generate bindings at build time.
+//
+// Bindgen will invoke the C preprocessor to process headers, which means that the bindings
+// generated can depend on the architecture that actually ran bindgen. In particular, for
+// portability across compilers glibc defines types like __u8 and __rlim64_t in terms of C types
+// like unsigned char and unsigned long. This is problematic for __rlim64_t since that resolves to
+// unsigned long int on amd64, which will end up being 32-bit on 32-bit platforms.
+//
+// As a workaround to let us commit these bindings and still use them on 32-bit platforms, the
+// bindgen invocation blacklists some of the generated fixed-width types and redefines them
+// manually as Rust fixed-width types.
+//
+// Generated in CrOS SDK chroot with:
+// bindgen --default-enum-style rust \
+//         --blacklist-type '__rlim64_t' \
+//         --raw-line 'pub type __rlim64_t = u64;' \
+//         --blacklist-type '__u\d{1,2}' \
+//         --raw-line 'pub type __u8 = u8;' \
+//         --raw-line 'pub type __u16 = u16;' \
+//         --raw-line 'pub type __u32 = u32;' \
+//         --blacklist-type '__uint64_t' \
+//         --whitelist-function '^minijail_.*' \
+//         --whitelist-var '^MINIJAIL_.*' \
+//         --no-layout-tests \
+//         --output libminijail.rs \
+//         libminijail.h -- \
+//         -DUSE_BINDGEN \
+//         -D_FILE_OFFSET_BITS=64 \
+//         -D_LARGEFILE_SOURCE \
+//         -D_LARGEFILE64_SOURCE
+//
+// Enum variants in rust are customarily camel case, but bindgen will leave the original names
+// intact.
+#[allow(non_camel_case_types)]
+mod libminijail;
+pub use crate::libminijail::*;
diff --git a/libminijail.h b/libminijail.h
index 3da845c..286369e 100644
--- a/libminijail.h
+++ b/libminijail.h
@@ -19,6 +19,14 @@
 #include <sys/resource.h>
 #include <sys/types.h>
 
+/*
+ * Rust's bindgen needs the actual definition of sock_fprog in order to
+ * generate usable bindings.
+ */
+#ifdef USE_BINDGEN
+#include <linux/filter.h>
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/libminijail.rs b/libminijail.rs
new file mode 100644
index 0000000..bf1e5ae
--- /dev/null
+++ b/libminijail.rs
@@ -0,0 +1,389 @@
+/* automatically generated by rust-bindgen */
+
+pub type __rlim64_t = u64;
+pub type __u8 = u8;
+pub type __u16 = u16;
+pub type __u32 = u32;
+
+pub type __uid_t = ::std::os::raw::c_uint;
+pub type __gid_t = ::std::os::raw::c_uint;
+pub type __pid_t = ::std::os::raw::c_int;
+pub type rlim_t = __rlim64_t;
+pub type gid_t = __gid_t;
+pub type uid_t = __uid_t;
+pub type pid_t = __pid_t;
+#[repr(C)]
+pub struct sock_filter {
+    pub code: __u16,
+    pub jt: __u8,
+    pub jf: __u8,
+    pub k: __u32,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct sock_fprog {
+    pub len: ::std::os::raw::c_ushort,
+    pub filter: *mut sock_filter,
+}
+pub const MINIJAIL_ERR_NO_ACCESS: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_NO_ACCESS;
+pub const MINIJAIL_ERR_NO_COMMAND: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_NO_COMMAND;
+pub const MINIJAIL_ERR_SIG_BASE: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_SIG_BASE;
+pub const MINIJAIL_ERR_PRELOAD: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_PRELOAD;
+pub const MINIJAIL_ERR_JAIL: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_JAIL;
+pub const MINIJAIL_ERR_INIT: _bindgen_ty_1 = _bindgen_ty_1::MINIJAIL_ERR_INIT;
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum _bindgen_ty_1 {
+    MINIJAIL_ERR_NO_ACCESS = 126,
+    MINIJAIL_ERR_NO_COMMAND = 127,
+    MINIJAIL_ERR_SIG_BASE = 128,
+    MINIJAIL_ERR_PRELOAD = 252,
+    MINIJAIL_ERR_JAIL = 253,
+    MINIJAIL_ERR_INIT = 254,
+}
+#[repr(C)]
+#[derive(Debug, Copy, Clone)]
+pub struct minijail {
+    _unused: [u8; 0],
+}
+pub type minijail_hook_t = ::std::option::Option<
+    unsafe extern "C" fn(context: *mut ::std::os::raw::c_void) -> ::std::os::raw::c_int,
+>;
+#[repr(u32)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum minijail_hook_event_t {
+    MINIJAIL_HOOK_EVENT_PRE_DROP_CAPS = 0,
+    MINIJAIL_HOOK_EVENT_PRE_EXECVE = 1,
+    MINIJAIL_HOOK_EVENT_PRE_CHROOT = 2,
+    MINIJAIL_HOOK_EVENT_MAX = 3,
+}
+extern "C" {
+    pub fn minijail_new() -> *mut minijail;
+}
+extern "C" {
+    pub fn minijail_change_uid(j: *mut minijail, uid: uid_t);
+}
+extern "C" {
+    pub fn minijail_change_gid(j: *mut minijail, gid: gid_t);
+}
+extern "C" {
+    pub fn minijail_set_supplementary_gids(j: *mut minijail, size: usize, list: *const gid_t);
+}
+extern "C" {
+    pub fn minijail_keep_supplementary_gids(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_change_user(
+        j: *mut minijail,
+        user: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_change_group(
+        j: *mut minijail,
+        group: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_use_seccomp(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_no_new_privs(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_use_seccomp_filter(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_set_seccomp_filter_tsync(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_set_seccomp_filters(j: *mut minijail, filter: *const sock_fprog);
+}
+extern "C" {
+    pub fn minijail_parse_seccomp_filters(j: *mut minijail, path: *const ::std::os::raw::c_char);
+}
+extern "C" {
+    pub fn minijail_parse_seccomp_filters_from_fd(j: *mut minijail, fd: ::std::os::raw::c_int);
+}
+extern "C" {
+    pub fn minijail_log_seccomp_filter_failures(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_use_caps(j: *mut minijail, capmask: u64);
+}
+extern "C" {
+    pub fn minijail_capbset_drop(j: *mut minijail, capmask: u64);
+}
+extern "C" {
+    pub fn minijail_set_ambient_caps(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_reset_signal_mask(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_reset_signal_handlers(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_vfs(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_enter_vfs(j: *mut minijail, ns_path: *const ::std::os::raw::c_char);
+}
+extern "C" {
+    pub fn minijail_new_session_keyring(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_skip_setting_securebits(j: *mut minijail, securebits_skip_mask: u64);
+}
+extern "C" {
+    pub fn minijail_skip_remount_private(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_remount_mode(j: *mut minijail, mode: ::std::os::raw::c_ulong);
+}
+extern "C" {
+    pub fn minijail_namespace_ipc(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_uts(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_set_hostname(
+        j: *mut minijail,
+        name: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_namespace_net(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_enter_net(j: *mut minijail, ns_path: *const ::std::os::raw::c_char);
+}
+extern "C" {
+    pub fn minijail_namespace_cgroups(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_close_open_fds(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_pids(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_pids_rw_proc(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_user(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_namespace_user_disable_setgroups(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_uidmap(
+        j: *mut minijail,
+        uidmap: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_gidmap(
+        j: *mut minijail,
+        gidmap: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_remount_proc_readonly(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_run_as_init(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_write_pid_file(
+        j: *mut minijail,
+        path: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_inherit_usergroups(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_use_alt_syscall(
+        j: *mut minijail,
+        table: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_rlimit(
+        j: *mut minijail,
+        type_: ::std::os::raw::c_int,
+        cur: rlim_t,
+        max: rlim_t,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_add_to_cgroup(
+        j: *mut minijail,
+        path: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_forward_signals(j: *mut minijail) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_create_session(j: *mut minijail) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_enter_chroot(
+        j: *mut minijail,
+        dir: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_enter_pivot_root(
+        j: *mut minijail,
+        dir: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_get_original_path(
+        j: *mut minijail,
+        chroot_path: *const ::std::os::raw::c_char,
+    ) -> *mut ::std::os::raw::c_char;
+}
+extern "C" {
+    pub fn minijail_mount_tmp(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_mount_tmp_size(j: *mut minijail, size: usize);
+}
+extern "C" {
+    pub fn minijail_mount_dev(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_mount_with_data(
+        j: *mut minijail,
+        src: *const ::std::os::raw::c_char,
+        dest: *const ::std::os::raw::c_char,
+        type_: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_ulong,
+        data: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_mount(
+        j: *mut minijail,
+        src: *const ::std::os::raw::c_char,
+        dest: *const ::std::os::raw::c_char,
+        type_: *const ::std::os::raw::c_char,
+        flags: ::std::os::raw::c_ulong,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_bind(
+        j: *mut minijail,
+        src: *const ::std::os::raw::c_char,
+        dest: *const ::std::os::raw::c_char,
+        writeable: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_add_hook(
+        j: *mut minijail,
+        hook: minijail_hook_t,
+        payload: *mut ::std::os::raw::c_void,
+        event: minijail_hook_event_t,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_preserve_fd(
+        j: *mut minijail,
+        parent_fd: ::std::os::raw::c_int,
+        child_fd: ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_set_preload_path(
+        j: *mut minijail,
+        preload_path: *const ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_enter(j: *const minijail);
+}
+extern "C" {
+    pub fn minijail_run(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_run_no_preload(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_run_pid(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+        pchild_pid: *mut pid_t,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_run_pipe(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+        pstdin_fd: *mut ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_run_pid_pipes(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+        pchild_pid: *mut pid_t,
+        pstdin_fd: *mut ::std::os::raw::c_int,
+        pstdout_fd: *mut ::std::os::raw::c_int,
+        pstderr_fd: *mut ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_run_pid_pipes_no_preload(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+        pchild_pid: *mut pid_t,
+        pstdin_fd: *mut ::std::os::raw::c_int,
+        pstdout_fd: *mut ::std::os::raw::c_int,
+        pstderr_fd: *mut ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_run_env_pid_pipes_no_preload(
+        j: *mut minijail,
+        filename: *const ::std::os::raw::c_char,
+        argv: *const *mut ::std::os::raw::c_char,
+        envp: *const *mut ::std::os::raw::c_char,
+        pchild_pid: *mut pid_t,
+        pstdin_fd: *mut ::std::os::raw::c_int,
+        pstdout_fd: *mut ::std::os::raw::c_int,
+        pstderr_fd: *mut ::std::os::raw::c_int,
+    ) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_fork(j: *mut minijail) -> pid_t;
+}
+extern "C" {
+    pub fn minijail_kill(j: *mut minijail) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_wait(j: *mut minijail) -> ::std::os::raw::c_int;
+}
+extern "C" {
+    pub fn minijail_destroy(j: *mut minijail);
+}
+extern "C" {
+    pub fn minijail_log_to_fd(fd: ::std::os::raw::c_int, min_priority: ::std::os::raw::c_int);
+}