diff --git a/Cargo.lock b/Cargo.lock index 4bf9d121f9..bd9675a1e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,6 +236,7 @@ name = "io_jail" version = "0.1.0" dependencies = [ "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "net_sys 0.1.0", ] [[package]] diff --git a/io_jail/Cargo.toml b/io_jail/Cargo.toml index 5e7ca5d042..31f8e6f3b0 100644 --- a/io_jail/Cargo.toml +++ b/io_jail/Cargo.toml @@ -6,3 +6,4 @@ edition = "2018" [dependencies] libc = "*" +net_sys = { path = "../net_sys" } diff --git a/io_jail/src/lib.rs b/io_jail/src/lib.rs index 7e66ec5347..59d6887d84 100644 --- a/io_jail/src/lib.rs +++ b/io_jail/src/lib.rs @@ -9,10 +9,12 @@ mod libminijail; use libc::pid_t; +use net_sys::{sock_filter, sock_fprog}; use std::ffi::CString; use std::fmt::{self, Display}; use std::fs; use std::io; +use std::os::raw::c_ushort; use std::os::unix::io::{AsRawFd, RawFd}; use std::path::{Path, PathBuf}; use std::ptr::{null, null_mut}; @@ -52,6 +54,8 @@ pub enum Error { DupDevNull(i32), /// Failed to set up /dev/null for FDs 0, 1, or 2. OpenDevNull(io::Error), + /// Failed to read policy bpf from file. + ReadProgram(io::Error), /// Setting the specified alt-syscall table failed with errno. Is the table in the kernel? SetAltSyscallTable { errno: i32, name: String }, /// Setting the specified rlimit failed with errno. @@ -68,6 +72,10 @@ pub enum Error { ProcFd(String), /// Minijail refused to preserve an FD in the inherit list of `fork()`. PreservingFd(i32), + /// Program size is too large + ProgramTooLarge, + /// File size should be non-zero and a multiple of sock_filter + WrongProgramSize, } impl Display for Error { @@ -121,6 +129,7 @@ impl Display for Error { "fail to open /dev/null for setting FDs 0, 1, or 2: {}", e, ), + ReadProgram(e) => write!(f, "failed to read from bpf file: {}", e), SetAltSyscallTable { name, errno } => write!( f, "failed to set alt-syscall table {}: {}", @@ -144,6 +153,8 @@ impl Display for Error { ReadFdDir(e) => write!(f, "failed to open /proc/self/fd: {}", e), ProcFd(s) => write!(f, "an entry in /proc/self/fd is not an integer: {}", s), PreservingFd(e) => write!(f, "fork failed in minijail_preserve_fd with error {}", e), + ProgramTooLarge => write!(f, "bpf program is too large (max 64K instructions)"), + WrongProgramSize => write!(f, "bpf file was empty or not a multiple of sock_filter"), } } } @@ -269,6 +280,28 @@ impl Minijail { libminijail::minijail_set_seccomp_filter_tsync(self.jail); } } + pub fn parse_seccomp_program(&mut self, path: &Path) -> Result<()> { + if !path.is_file() { + return Err(Error::SeccompPath(path.to_owned())); + } + + let buffer = fs::read(path).map_err(Error::ReadProgram)?; + if buffer.len() % std::mem::size_of::() != 0 { + return Err(Error::WrongProgramSize); + } + let count = buffer.len() / std::mem::size_of::(); + if count > (!0 as u16) as usize { + return Err(Error::ProgramTooLarge); + } + let header = sock_fprog { + len: count as c_ushort, + filter: buffer.as_ptr() as *mut sock_filter, + }; + unsafe { + libminijail::minijail_set_seccomp_filters(self.jail, &header); + } + Ok(()) + } pub fn parse_seccomp_filters(&mut self, path: &Path) -> Result<()> { if !path.is_file() { return Err(Error::SeccompPath(path.to_owned())); diff --git a/io_jail/src/libminijail.rs b/io_jail/src/libminijail.rs index 227e75362f..14175dc053 100644 --- a/io_jail/src/libminijail.rs +++ b/io_jail/src/libminijail.rs @@ -3,7 +3,7 @@ // found in the LICENSE file. use libc::{gid_t, pid_t, rlim_t, uid_t}; -use std::os::raw::{c_char, c_int, c_ulong}; +use std::os::raw::{c_char, c_int, c_long, c_ulong}; /// Struct minijail is an opaque type inside libminijail. /// See the minijail man page for a description of functions. @@ -24,6 +24,7 @@ extern "C" { pub fn minijail_no_new_privs(j: *mut minijail); pub fn minijail_use_seccomp_filter(j: *mut minijail); pub fn minijail_set_seccomp_filter_tsync(j: *mut minijail); + pub fn minijail_set_seccomp_filters(j: *mut minijail, filter: *const net_sys::sock_fprog); pub fn minijail_parse_seccomp_filters(j: *mut minijail, path: *const c_char); pub fn minijail_parse_seccomp_filters_from_fd(j: *mut minijail, fd: c_int); pub fn minijail_log_seccomp_filter_failures(j: *mut minijail); @@ -31,16 +32,22 @@ extern "C" { pub fn minijail_capbset_drop(j: *mut minijail, capmask: u64); pub fn minijail_set_ambient_caps(j: *mut minijail); pub fn minijail_reset_signal_mask(j: *mut minijail); + pub fn minijail_reset_signal_handlers(j: *mut minijail); pub fn minijail_namespace_vfs(j: *mut minijail); pub fn minijail_namespace_enter_vfs(j: *mut minijail, ns_path: *const c_char); pub fn minijail_new_session_keyring(j: *mut minijail); + pub fn minijail_skip_setting_securebits(j: *mut minijail, securebits_skip_mask: u64); pub fn minijail_skip_remount_private(j: *mut minijail); + pub fn minijail_remount_mode(j: *mut minijail, mode: c_long); pub fn minijail_namespace_ipc(j: *mut minijail); + pub fn minijail_namespace_uts(j: *mut minijail); + pub fn minijail_namespace_set_hostname(j: *mut minijail, name: *const c_char) -> c_int; pub fn minijail_namespace_net(j: *mut minijail); pub fn minijail_namespace_enter_net(j: *mut minijail, ns_path: *const c_char); pub fn minijail_namespace_cgroups(j: *mut minijail); pub fn minijail_close_open_fds(j: *mut minijail); pub fn minijail_namespace_pids(j: *mut minijail); + pub fn minijail_namespace_pids_rw_proc(j: *mut minijail); pub fn minijail_namespace_user(j: *mut minijail); pub fn minijail_namespace_user_disable_setgroups(j: *mut minijail); pub fn minijail_uidmap(j: *mut minijail, uidmap: *const c_char) -> c_int;