mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-10 12:09:31 +00:00
io_jail: Remove now that the code lives in aosp/external/minijail
io_jail has been migrated to aosp/external/minijail/rust/minijail. This removes the crosvm copy and updates the references to use the new location. BUG=chromium:1096175 TEST=cargo test Cq-Depend: chromium:2254418 Change-Id: I29d5c6178b6faf5e52671cfbe6fc7e51f0d21dd2 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2254298 Tested-by: Allen Webb <allenwebb@google.com> Reviewed-by: Dylan Reid <dgreid@chromium.org> Commit-Queue: Allen Webb <allenwebb@google.com>
This commit is contained in:
parent
436296b1f0
commit
f3024c8976
20 changed files with 39 additions and 966 deletions
|
@ -55,14 +55,13 @@ disk = { path = "disk" }
|
|||
enumn = { path = "enumn" }
|
||||
gpu_buffer = { path = "gpu_buffer", optional = true }
|
||||
gpu_renderer = { path = "gpu_renderer", optional = true }
|
||||
io_jail = { path = "io_jail" }
|
||||
kernel_cmdline = { path = "kernel_cmdline" }
|
||||
kernel_loader = { path = "kernel_loader" }
|
||||
kvm = { path = "kvm" }
|
||||
kvm_sys = { path = "kvm_sys" }
|
||||
libc = "0.2.65"
|
||||
libcras = "*"
|
||||
minijail-sys = "*" # provided by ebuild
|
||||
minijail = "*" # provided by ebuild
|
||||
msg_socket = { path = "msg_socket" }
|
||||
net_util = { path = "net_util" }
|
||||
p9 = { path = "p9" }
|
||||
|
@ -92,7 +91,7 @@ audio_streams = { path = "../../third_party/adhd/audio_streams" } # ignored by e
|
|||
data_model = { path = "data_model" }
|
||||
libcras = { path = "../../third_party/adhd/cras/client/libcras" } # ignored by ebuild
|
||||
libvda = { path = "../../platform2/arc/vm/libvda/rust" } # ignored by ebuild
|
||||
minijail-sys = { path = "../../aosp/external/minijail/rust/minijail-sys" } # ignored by ebuild
|
||||
minijail = { path = "../../aosp/external/minijail/rust/minijail" } # ignored by ebuild
|
||||
poll_token_derive = { path = "sys_util/poll_token_derive" }
|
||||
sync = { path = "sync" }
|
||||
sys_util = { path = "sys_util" }
|
||||
|
|
|
@ -229,7 +229,6 @@ crates are:
|
|||
|
||||
* `crosvm` - The top-level binary front-end for using crosvm.
|
||||
* `devices` - Virtual devices exposed to the guest OS.
|
||||
* `io_jail` - Creates jailed process using `libminijail`.
|
||||
* `kernel_loader` - Loads elf64 kernel files to a slice of memory.
|
||||
* `kvm_sys` - Low-level (mostly) auto-generated structures and constants for using KVM.
|
||||
* `kvm` - Unsafe, low-level wrapper code for using `kvm_sys`.
|
||||
|
|
|
@ -8,11 +8,11 @@ edition = "2018"
|
|||
arch = { path = "../arch" }
|
||||
data_model = { path = "../data_model" }
|
||||
devices = { path = "../devices" }
|
||||
io_jail = { path = "../io_jail" }
|
||||
kernel_cmdline = { path = "../kernel_cmdline" }
|
||||
kvm = { path = "../kvm" }
|
||||
kvm_sys = { path = "../kvm_sys" }
|
||||
libc = "*"
|
||||
minijail = "*"
|
||||
remain = "*"
|
||||
resources = { path = "../resources" }
|
||||
sync = { path = "../sync" }
|
||||
|
|
|
@ -16,7 +16,7 @@ use arch::{
|
|||
VmComponents, VmImage,
|
||||
};
|
||||
use devices::{Bus, BusError, PciAddress, PciConfigMmio, PciDevice, PciInterruptPin};
|
||||
use io_jail::Minijail;
|
||||
use minijail::Minijail;
|
||||
use remain::sorted;
|
||||
use resources::SystemAllocator;
|
||||
use sync::Mutex;
|
||||
|
|
|
@ -7,10 +7,10 @@ edition = "2018"
|
|||
[dependencies]
|
||||
acpi_tables = { path = "../acpi_tables" }
|
||||
devices = { path = "../devices" }
|
||||
io_jail = { path = "../io_jail" }
|
||||
kernel_cmdline = { path = "../kernel_cmdline" }
|
||||
kvm = { path = "../kvm" }
|
||||
libc = "*"
|
||||
minijail = "*"
|
||||
resources = { path = "../resources" }
|
||||
sync = { path = "../sync" }
|
||||
sys_util = { path = "../sys_util" }
|
||||
|
|
|
@ -23,8 +23,8 @@ use devices::{
|
|||
Bus, BusDevice, BusError, PciAddress, PciDevice, PciDeviceError, PciInterruptPin, PciRoot,
|
||||
ProxyDevice,
|
||||
};
|
||||
use io_jail::Minijail;
|
||||
use kvm::{IoeventAddress, Kvm, Vcpu, Vm};
|
||||
use minijail::Minijail;
|
||||
use resources::SystemAllocator;
|
||||
use sync::Mutex;
|
||||
use sys_util::{syslog, EventFd, GuestAddress, GuestMemory, GuestMemoryError};
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::str::FromStr;
|
|||
use std::sync::Arc;
|
||||
|
||||
use devices::{Bus, ProxyDevice, Serial, SerialDevice};
|
||||
use io_jail::Minijail;
|
||||
use minijail::Minijail;
|
||||
use sync::Mutex;
|
||||
use sys_util::{read_raw_stdin, syslog, EventFd};
|
||||
|
||||
|
|
|
@ -54,7 +54,6 @@ TEST_MODULES_PARALLEL = [
|
|||
]
|
||||
|
||||
TEST_MODULES_SERIAL = [
|
||||
'io_jail',
|
||||
'sys_util',
|
||||
]
|
||||
|
||||
|
|
|
@ -25,13 +25,13 @@ gpu_buffer = { path = "../gpu_buffer", optional = true }
|
|||
gpu_display = { path = "../gpu_display", optional = true }
|
||||
gpu_renderer = { path = "../gpu_renderer", optional = true }
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
io_jail = { path = "../io_jail" }
|
||||
kvm = { path = "../kvm" }
|
||||
kvm_sys = { path = "../kvm_sys" }
|
||||
libc = "*"
|
||||
libcras = "*"
|
||||
libvda = { version = "*", optional = true }
|
||||
linux_input_sys = { path = "../linux_input_sys" }
|
||||
minijail = "*"
|
||||
msg_on_socket_derive = { path = "../msg_socket/msg_on_socket_derive" }
|
||||
msg_socket = { path = "../msg_socket" }
|
||||
net_sys = { path = "../net_sys" }
|
||||
|
|
|
@ -9,8 +9,8 @@ use std::os::unix::io::{AsRawFd, RawFd};
|
|||
use std::time::Duration;
|
||||
use std::{self, io};
|
||||
|
||||
use io_jail::{self, Minijail};
|
||||
use libc::{self, pid_t};
|
||||
use minijail::{self, Minijail};
|
||||
use msg_socket::{MsgOnSocket, MsgReceiver, MsgSender, MsgSocket};
|
||||
use sys_util::{error, net::UnixSeqpacket};
|
||||
|
||||
|
@ -19,7 +19,7 @@ use crate::BusDevice;
|
|||
/// Errors for proxy devices.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
ForkingJail(io_jail::Error),
|
||||
ForkingJail(minijail::Error),
|
||||
Io(io::Error),
|
||||
}
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
|
|
@ -23,7 +23,7 @@ During the device creation routine, each device will be created and then wrapped
|
|||
|
||||
## Sandboxing Policy
|
||||
|
||||
Every sandbox is made with [minijail], invoked using the `io_jail` crate in crosvm, and starts with `create_base_minijail` in `linux.rs` which set some very restrictive settings. Linux namespaces and seccomp filters are used extensively. Each seccomp policy can be found under `seccomp/{arch}/{device}.policy` and should start by `@include`-ing the `common_device.policy`. With the exception of architecture specific devices (such as `Pl030` on ARM or `I8042` on x86_64), every device will need a different policy for each supported architecture.
|
||||
Every sandbox is made with [minijail] and starts with `create_base_minijail` in `linux.rs` which set some very restrictive settings. Linux namespaces and seccomp filters are used extensively. Each seccomp policy can be found under `seccomp/{arch}/{device}.policy` and should start by `@include`-ing the `common_device.policy`. With the exception of architecture specific devices (such as `Pl030` on ARM or `I8042` on x86_64), every device will need a different policy for each supported architecture.
|
||||
|
||||
## The VM Control Sockets
|
||||
|
||||
|
@ -79,4 +79,4 @@ Note that the limitations of `PollContext` are the same as the limitations of `e
|
|||
|
||||
Using raw sockets and pipes to communicate is very inconvenient for rich data types. To help make this easier and less error prone, crosvm has the `msg_socket` crate. Included is a trait for messages encodable on a Unix socket (`MsgOnSocket`), a set of traits for sending and receiving (`MsgSender`/`MsgReceiver`), and implementations of those traits over `UnixSeqpacket` (`MsgSocket`/`Sender`/`Receiver`). To make implementing `MsgOnSocket` very easy, a custom derive for that trait can be utilized with `#[derive(MsgOnSocket)]`. The custom derive will work for enums and structs with nested data, primitive types, and anything that implements `AsRawFd`. However, structures with no fixed upper limit in size, such as `Vec` or `BTreeMap`, are not supported.
|
||||
|
||||
[minijail]: https://android.googlesource.com/platform/external/minijail
|
||||
[minijail]: https://android.googlesource.com/platform/external/minijail
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
[package]
|
||||
name = "io_jail"
|
||||
version = "0.1.0"
|
||||
authors = ["The Chromium OS Authors"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
libc = "*"
|
||||
minijail-sys = "*"
|
|
@ -1,774 +0,0 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
use libc::pid_t;
|
||||
use minijail_sys::*;
|
||||
use std::ffi::CString;
|
||||
use std::fmt::{self, Display};
|
||||
use std::fs;
|
||||
use std::io;
|
||||
use std::os::raw::{c_char, c_ulong, c_ushort};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::ptr::{null, null_mut};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
// minijail failed to accept bind mount.
|
||||
BindMount {
|
||||
errno: i32,
|
||||
src: PathBuf,
|
||||
dst: PathBuf,
|
||||
},
|
||||
// minijail failed to accept mount.
|
||||
Mount {
|
||||
errno: i32,
|
||||
src: PathBuf,
|
||||
dest: PathBuf,
|
||||
fstype: String,
|
||||
flags: usize,
|
||||
data: String,
|
||||
},
|
||||
/// Failure to count the number of threads in /proc/self/tasks.
|
||||
CheckingMultiThreaded(io::Error),
|
||||
/// minjail_new failed, this is an allocation failure.
|
||||
CreatingMinijail,
|
||||
/// minijail_fork failed with the given error code.
|
||||
ForkingMinijail(i32),
|
||||
/// Attempt to `fork` while already multithreaded.
|
||||
ForkingWhileMultiThreaded,
|
||||
/// The seccomp policy path doesn't exist.
|
||||
SeccompPath(PathBuf),
|
||||
/// The string passed in didn't parse to a valid CString.
|
||||
StrToCString(String),
|
||||
/// The path passed in didn't parse to a valid CString.
|
||||
PathToCString(PathBuf),
|
||||
/// Failed to call dup2 to set stdin, stdout, or stderr to /dev/null.
|
||||
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.
|
||||
SetRlimit { errno: i32, kind: libc::c_int },
|
||||
/// chroot failed with the provided errno.
|
||||
SettingChrootDirectory(i32, PathBuf),
|
||||
/// pivot_root failed with the provided errno.
|
||||
SettingPivotRootDirectory(i32, PathBuf),
|
||||
/// There is an entry in /proc/self/fd that isn't a valid PID.
|
||||
ReadFdDirEntry(io::Error),
|
||||
/// /proc/self/fd failed to open.
|
||||
ReadFdDir(io::Error),
|
||||
/// An entry in /proc/self/fd is not an integer
|
||||
ProcFd(String),
|
||||
/// Minijail refused to preserve an FD in the inherit list of `fork()`.
|
||||
PreservingFd(i32),
|
||||
/// Program size is too large
|
||||
ProgramTooLarge,
|
||||
/// Alignment of file should be divisible by the alignment of sock_filter.
|
||||
WrongProgramAlignment,
|
||||
/// File size should be non-zero and a multiple of sock_filter
|
||||
WrongProgramSize,
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use self::Error::*;
|
||||
|
||||
match self {
|
||||
BindMount { src, dst, errno } => write!(
|
||||
f,
|
||||
"failed to accept bind mount {} -> {}: {}",
|
||||
src.display(),
|
||||
dst.display(),
|
||||
io::Error::from_raw_os_error(*errno),
|
||||
),
|
||||
Mount {
|
||||
errno,
|
||||
src,
|
||||
dest,
|
||||
fstype,
|
||||
flags,
|
||||
data,
|
||||
} => write!(
|
||||
f,
|
||||
"failed to accept mount {} -> {} of type {:?} with flags 0x{:x} \
|
||||
and data {:?}: {}",
|
||||
src.display(),
|
||||
dest.display(),
|
||||
fstype,
|
||||
flags,
|
||||
data,
|
||||
io::Error::from_raw_os_error(*errno),
|
||||
),
|
||||
CheckingMultiThreaded(e) => write!(
|
||||
f,
|
||||
"Failed to count the number of threads from /proc/self/tasks {}",
|
||||
e
|
||||
),
|
||||
CreatingMinijail => write!(f, "minjail_new failed due to an allocation failure"),
|
||||
ForkingMinijail(e) => write!(f, "minijail_fork failed with error {}", e),
|
||||
ForkingWhileMultiThreaded => write!(f, "Attempt to call fork() while multithreaded"),
|
||||
SeccompPath(p) => write!(f, "missing seccomp policy path: {}", p.display()),
|
||||
StrToCString(s) => write!(f, "failed to convert string into CString: {}", s),
|
||||
PathToCString(s) => write!(f, "failed to convert path into CString: {}", s.display()),
|
||||
DupDevNull(errno) => write!(
|
||||
f,
|
||||
"failed to call dup2 to set stdin, stdout, or stderr to /dev/null: {}",
|
||||
io::Error::from_raw_os_error(*errno),
|
||||
),
|
||||
OpenDevNull(e) => write!(
|
||||
f,
|
||||
"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 {}: {}",
|
||||
name,
|
||||
io::Error::from_raw_os_error(*errno),
|
||||
),
|
||||
SetRlimit { errno, kind } => write!(f, "failed to set rlimit {}: {}", kind, errno),
|
||||
SettingChrootDirectory(errno, p) => write!(
|
||||
f,
|
||||
"failed to set chroot {}: {}",
|
||||
p.display(),
|
||||
io::Error::from_raw_os_error(*errno),
|
||||
),
|
||||
SettingPivotRootDirectory(errno, p) => write!(
|
||||
f,
|
||||
"failed to set pivot root {}: {}",
|
||||
p.display(),
|
||||
io::Error::from_raw_os_error(*errno),
|
||||
),
|
||||
ReadFdDirEntry(e) => write!(f, "failed to read an entry in /proc/self/fd: {}", e),
|
||||
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)"),
|
||||
WrongProgramAlignment => write!(
|
||||
f,
|
||||
"the alignment of bpf file was not a multiple of that of sock_filter"
|
||||
),
|
||||
WrongProgramSize => write!(f, "bpf file was empty or not a multiple of sock_filter"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
/// Configuration to jail a process based on wrapping libminijail.
|
||||
///
|
||||
/// Intentionally leave out everything related to `minijail_run`. Forking is
|
||||
/// hard to reason about w.r.t. memory and resource safety. It is better to avoid
|
||||
/// forking from rust code. Leave forking to the library user, who can make
|
||||
/// an informed decision about when to fork to minimize risk.
|
||||
/// # Examples
|
||||
/// * Load seccomp policy - like "minijail0 -n -S myfilter.policy"
|
||||
///
|
||||
/// ```
|
||||
/// # use std::path::Path;
|
||||
/// # use io_jail::Minijail;
|
||||
/// # fn seccomp_filter_test() -> Result<(), ()> {
|
||||
/// let mut j = Minijail::new().map_err(|_| ())?;
|
||||
/// j.no_new_privs();
|
||||
/// j.parse_seccomp_filters(Path::new("my_filter.policy")).map_err(|_| ())?;
|
||||
/// j.use_seccomp_filter();
|
||||
/// unsafe { // `fork` will close all the programs FDs.
|
||||
/// j.fork(None).map_err(|_| ())?;
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// * Keep stdin, stdout, and stderr open after jailing.
|
||||
///
|
||||
/// ```
|
||||
/// # use io_jail::Minijail;
|
||||
/// # use std::os::unix::io::RawFd;
|
||||
/// # fn seccomp_filter_test() -> Result<(), ()> {
|
||||
/// let j = Minijail::new().map_err(|_| ())?;
|
||||
/// let preserve_fds: Vec<RawFd> = vec![0, 1, 2];
|
||||
/// unsafe { // `fork` will close all the programs FDs.
|
||||
/// j.fork(Some(&preserve_fds)).map_err(|_| ())?;
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
/// # Errors
|
||||
/// The `fork` function might not return an error if it fails after forking. A
|
||||
/// partial jail is not recoverable and will instead result in killing the
|
||||
/// process.
|
||||
pub struct Minijail {
|
||||
jail: *mut minijail,
|
||||
}
|
||||
|
||||
impl Minijail {
|
||||
/// Creates a new jail configuration.
|
||||
pub fn new() -> Result<Minijail> {
|
||||
let j = unsafe {
|
||||
// libminijail actually owns the minijail structure. It will live until we call
|
||||
// minijail_destroy.
|
||||
minijail_new()
|
||||
};
|
||||
if j.is_null() {
|
||||
return Err(Error::CreatingMinijail);
|
||||
}
|
||||
Ok(Minijail { jail: j })
|
||||
}
|
||||
|
||||
// The following functions are safe because they only set values in the
|
||||
// struct already owned by minijail. The struct's lifetime is tied to
|
||||
// `struct Minijail` so it is guaranteed to be valid
|
||||
|
||||
pub fn change_uid(&mut self, uid: libc::uid_t) {
|
||||
unsafe {
|
||||
minijail_change_uid(self.jail, uid);
|
||||
}
|
||||
}
|
||||
pub fn change_gid(&mut self, gid: libc::gid_t) {
|
||||
unsafe {
|
||||
minijail_change_gid(self.jail, gid);
|
||||
}
|
||||
}
|
||||
pub fn set_supplementary_gids(&mut self, ids: &[libc::gid_t]) {
|
||||
unsafe {
|
||||
minijail_set_supplementary_gids(self.jail, ids.len(), ids.as_ptr());
|
||||
}
|
||||
}
|
||||
pub fn keep_supplementary_gids(&mut self) {
|
||||
unsafe {
|
||||
minijail_keep_supplementary_gids(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn set_rlimit(
|
||||
&mut self,
|
||||
kind: libc::c_int,
|
||||
cur: libc::rlim64_t,
|
||||
max: libc::rlim64_t,
|
||||
) -> Result<()> {
|
||||
let errno = unsafe { minijail_rlimit(self.jail, kind, cur, max) };
|
||||
if errno == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(Error::SetRlimit { errno, kind })
|
||||
}
|
||||
}
|
||||
pub fn use_seccomp(&mut self) {
|
||||
unsafe {
|
||||
minijail_use_seccomp(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn no_new_privs(&mut self) {
|
||||
unsafe {
|
||||
minijail_no_new_privs(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn use_seccomp_filter(&mut self) {
|
||||
unsafe {
|
||||
minijail_use_seccomp_filter(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn set_seccomp_filter_tsync(&mut self) {
|
||||
unsafe {
|
||||
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::<sock_filter>() != 0 {
|
||||
return Err(Error::WrongProgramSize);
|
||||
}
|
||||
let count = buffer.len() / std::mem::size_of::<sock_filter>();
|
||||
if count > (!0 as u16) as usize {
|
||||
return Err(Error::ProgramTooLarge);
|
||||
}
|
||||
if buffer.as_ptr() as usize % std::mem::align_of::<sock_filter>() != 0 {
|
||||
return Err(Error::WrongProgramAlignment);
|
||||
}
|
||||
|
||||
// Safe cast because we checked that the buffer address is divisible by the alignment of
|
||||
// sock_filter.
|
||||
#[allow(clippy::cast_ptr_alignment)]
|
||||
let header = sock_fprog {
|
||||
len: count as c_ushort,
|
||||
filter: buffer.as_ptr() as *mut sock_filter,
|
||||
};
|
||||
unsafe {
|
||||
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()));
|
||||
}
|
||||
|
||||
let pathstring = path
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(path.to_owned()))?;
|
||||
let filename =
|
||||
CString::new(pathstring).map_err(|_| Error::PathToCString(path.to_owned()))?;
|
||||
unsafe {
|
||||
minijail_parse_seccomp_filters(self.jail, filename.as_ptr());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn log_seccomp_filter_failures(&mut self) {
|
||||
unsafe {
|
||||
minijail_log_seccomp_filter_failures(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn use_caps(&mut self, capmask: u64) {
|
||||
unsafe {
|
||||
minijail_use_caps(self.jail, capmask);
|
||||
}
|
||||
}
|
||||
pub fn capbset_drop(&mut self, capmask: u64) {
|
||||
unsafe {
|
||||
minijail_capbset_drop(self.jail, capmask);
|
||||
}
|
||||
}
|
||||
pub fn set_ambient_caps(&mut self) {
|
||||
unsafe {
|
||||
minijail_set_ambient_caps(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn reset_signal_mask(&mut self) {
|
||||
unsafe {
|
||||
minijail_reset_signal_mask(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn run_as_init(&mut self) {
|
||||
unsafe {
|
||||
minijail_run_as_init(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_pids(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_pids(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_user(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_user(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_user_disable_setgroups(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_user_disable_setgroups(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_vfs(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_vfs(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn new_session_keyring(&mut self) {
|
||||
unsafe {
|
||||
minijail_new_session_keyring(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn skip_remount_private(&mut self) {
|
||||
unsafe {
|
||||
minijail_skip_remount_private(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_ipc(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_ipc(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_net(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_net(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn namespace_cgroups(&mut self) {
|
||||
unsafe {
|
||||
minijail_namespace_cgroups(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn remount_proc_readonly(&mut self) {
|
||||
unsafe {
|
||||
minijail_remount_proc_readonly(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn set_remount_mode(&mut self, mode: c_ulong) {
|
||||
unsafe { minijail_remount_mode(self.jail, mode) }
|
||||
}
|
||||
pub fn uidmap(&mut self, uid_map: &str) -> Result<()> {
|
||||
let map_cstring =
|
||||
CString::new(uid_map).map_err(|_| Error::StrToCString(uid_map.to_owned()))?;
|
||||
unsafe {
|
||||
minijail_uidmap(self.jail, map_cstring.as_ptr());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn gidmap(&mut self, gid_map: &str) -> Result<()> {
|
||||
let map_cstring =
|
||||
CString::new(gid_map).map_err(|_| Error::StrToCString(gid_map.to_owned()))?;
|
||||
unsafe {
|
||||
minijail_gidmap(self.jail, map_cstring.as_ptr());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn inherit_usergroups(&mut self) {
|
||||
unsafe {
|
||||
minijail_inherit_usergroups(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn use_alt_syscall(&mut self, table_name: &str) -> Result<()> {
|
||||
let table_name_string =
|
||||
CString::new(table_name).map_err(|_| Error::StrToCString(table_name.to_owned()))?;
|
||||
let ret = unsafe { minijail_use_alt_syscall(self.jail, table_name_string.as_ptr()) };
|
||||
if ret < 0 {
|
||||
return Err(Error::SetAltSyscallTable {
|
||||
errno: ret,
|
||||
name: table_name.to_owned(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn enter_chroot(&mut self, dir: &Path) -> Result<()> {
|
||||
let pathstring = dir
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(dir.to_owned()))?;
|
||||
let dirname = CString::new(pathstring).map_err(|_| Error::PathToCString(dir.to_owned()))?;
|
||||
let ret = unsafe { minijail_enter_chroot(self.jail, dirname.as_ptr()) };
|
||||
if ret < 0 {
|
||||
return Err(Error::SettingChrootDirectory(ret, dir.to_owned()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn enter_pivot_root(&mut self, dir: &Path) -> Result<()> {
|
||||
let pathstring = dir
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(dir.to_owned()))?;
|
||||
let dirname = CString::new(pathstring).map_err(|_| Error::PathToCString(dir.to_owned()))?;
|
||||
let ret = unsafe { minijail_enter_pivot_root(self.jail, dirname.as_ptr()) };
|
||||
if ret < 0 {
|
||||
return Err(Error::SettingPivotRootDirectory(ret, dir.to_owned()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn mount(&mut self, src: &Path, dest: &Path, fstype: &str, flags: usize) -> Result<()> {
|
||||
self.mount_with_data(src, dest, fstype, flags, "")
|
||||
}
|
||||
pub fn mount_with_data(
|
||||
&mut self,
|
||||
src: &Path,
|
||||
dest: &Path,
|
||||
fstype: &str,
|
||||
flags: usize,
|
||||
data: &str,
|
||||
) -> Result<()> {
|
||||
let src_os = src
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(src.to_owned()))?;
|
||||
let src_path = CString::new(src_os).map_err(|_| Error::StrToCString(src_os.to_owned()))?;
|
||||
let dest_os = dest
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(dest.to_owned()))?;
|
||||
let dest_path =
|
||||
CString::new(dest_os).map_err(|_| Error::StrToCString(dest_os.to_owned()))?;
|
||||
let fstype_string =
|
||||
CString::new(fstype).map_err(|_| Error::StrToCString(fstype.to_owned()))?;
|
||||
let data_string = CString::new(data).map_err(|_| Error::StrToCString(data.to_owned()))?;
|
||||
let ret = unsafe {
|
||||
minijail_mount_with_data(
|
||||
self.jail,
|
||||
src_path.as_ptr(),
|
||||
dest_path.as_ptr(),
|
||||
fstype_string.as_ptr(),
|
||||
flags as _,
|
||||
data_string.as_ptr(),
|
||||
)
|
||||
};
|
||||
if ret < 0 {
|
||||
return Err(Error::Mount {
|
||||
errno: ret,
|
||||
src: src.to_owned(),
|
||||
dest: dest.to_owned(),
|
||||
fstype: fstype.to_owned(),
|
||||
flags,
|
||||
data: data.to_owned(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub fn mount_dev(&mut self) {
|
||||
unsafe {
|
||||
minijail_mount_dev(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn mount_tmp(&mut self) {
|
||||
unsafe {
|
||||
minijail_mount_tmp(self.jail);
|
||||
}
|
||||
}
|
||||
pub fn mount_tmp_size(&mut self, size: usize) {
|
||||
unsafe {
|
||||
minijail_mount_tmp_size(self.jail, size);
|
||||
}
|
||||
}
|
||||
pub fn mount_bind(&mut self, src: &Path, dest: &Path, writable: bool) -> Result<()> {
|
||||
let src_os = src
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(src.to_owned()))?;
|
||||
let src_path = CString::new(src_os).map_err(|_| Error::StrToCString(src_os.to_owned()))?;
|
||||
let dest_os = dest
|
||||
.as_os_str()
|
||||
.to_str()
|
||||
.ok_or(Error::PathToCString(dest.to_owned()))?;
|
||||
let dest_path =
|
||||
CString::new(dest_os).map_err(|_| Error::StrToCString(dest_os.to_owned()))?;
|
||||
let ret = unsafe {
|
||||
minijail_bind(
|
||||
self.jail,
|
||||
src_path.as_ptr(),
|
||||
dest_path.as_ptr(),
|
||||
writable as _,
|
||||
)
|
||||
};
|
||||
if ret < 0 {
|
||||
return Err(Error::BindMount {
|
||||
errno: ret,
|
||||
src: src.to_owned(),
|
||||
dst: dest.to_owned(),
|
||||
});
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Forks and execs a child and puts it in the previously configured minijail.
|
||||
/// FDs 0, 1, and 2 are overwritten with /dev/null FDs unless they are included in the
|
||||
/// inheritable_fds list. This function may abort in the child on error because a partially
|
||||
/// entered jail isn't recoverable.
|
||||
pub fn run(&self, cmd: &Path, inheritable_fds: &[RawFd], args: &[&str]) -> Result<pid_t> {
|
||||
let cmd_os = cmd.to_str().ok_or(Error::PathToCString(cmd.to_owned()))?;
|
||||
let cmd_cstr = CString::new(cmd_os).map_err(|_| Error::StrToCString(cmd_os.to_owned()))?;
|
||||
|
||||
// Converts each incoming `args` string to a `CString`, and then puts each `CString` pointer
|
||||
// into a null terminated array, suitable for use as an argv parameter to `execve`.
|
||||
let mut args_cstr = Vec::with_capacity(args.len());
|
||||
let mut args_array = Vec::with_capacity(args.len());
|
||||
for &arg in args {
|
||||
let arg_cstr = CString::new(arg).map_err(|_| Error::StrToCString(arg.to_owned()))?;
|
||||
args_array.push(arg_cstr.as_ptr());
|
||||
args_cstr.push(arg_cstr);
|
||||
}
|
||||
args_array.push(null());
|
||||
|
||||
for fd in inheritable_fds {
|
||||
let ret = unsafe { minijail_preserve_fd(self.jail, *fd, *fd) };
|
||||
if ret < 0 {
|
||||
return Err(Error::PreservingFd(ret));
|
||||
}
|
||||
}
|
||||
|
||||
let dev_null = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open("/dev/null")
|
||||
.map_err(Error::OpenDevNull)?;
|
||||
// Set stdin, stdout, and stderr to /dev/null unless they are in the inherit list.
|
||||
// These will only be closed when this process exits.
|
||||
for io_fd in &[libc::STDIN_FILENO, libc::STDOUT_FILENO, libc::STDERR_FILENO] {
|
||||
if !inheritable_fds.contains(io_fd) {
|
||||
let ret = unsafe { minijail_preserve_fd(self.jail, dev_null.as_raw_fd(), *io_fd) };
|
||||
if ret < 0 {
|
||||
return Err(Error::PreservingFd(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe {
|
||||
minijail_close_open_fds(self.jail);
|
||||
}
|
||||
|
||||
let mut pid = 0;
|
||||
let ret = unsafe {
|
||||
minijail_run_pid_pipes(
|
||||
self.jail,
|
||||
cmd_cstr.as_ptr(),
|
||||
args_array.as_ptr() as *const *mut c_char,
|
||||
&mut pid,
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
null_mut(),
|
||||
)
|
||||
};
|
||||
if ret < 0 {
|
||||
return Err(Error::ForkingMinijail(ret));
|
||||
}
|
||||
Ok(pid)
|
||||
}
|
||||
|
||||
/// Forks a child and puts it in the previously configured minijail.
|
||||
/// `fork` is unsafe because it closes all open FD for this process. That
|
||||
/// could cause a lot of trouble if not handled carefully. FDs 0, 1, and 2
|
||||
/// are overwritten with /dev/null FDs unless they are included in the
|
||||
/// inheritable_fds list.
|
||||
/// This Function may abort in the child on error because a partially
|
||||
/// entered jail isn't recoverable.
|
||||
pub unsafe fn fork(&self, inheritable_fds: Option<&[RawFd]>) -> Result<pid_t> {
|
||||
if !is_single_threaded().map_err(Error::CheckingMultiThreaded)? {
|
||||
// This test will fail during `cargo test` because the test harness always spawns a test
|
||||
// thread. We will make an exception for that case because the tests for this module
|
||||
// should always be run in a serial fashion using `--test-threads=1`.
|
||||
#[cfg(not(test))]
|
||||
return Err(Error::ForkingWhileMultiThreaded);
|
||||
}
|
||||
|
||||
if let Some(keep_fds) = inheritable_fds {
|
||||
for fd in keep_fds {
|
||||
let ret = minijail_preserve_fd(self.jail, *fd, *fd);
|
||||
if ret < 0 {
|
||||
return Err(Error::PreservingFd(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let dev_null = fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.open("/dev/null")
|
||||
.map_err(Error::OpenDevNull)?;
|
||||
// Set stdin, stdout, and stderr to /dev/null unless they are in the inherit list.
|
||||
// These will only be closed when this process exits.
|
||||
for io_fd in &[libc::STDIN_FILENO, libc::STDOUT_FILENO, libc::STDERR_FILENO] {
|
||||
if inheritable_fds.is_none() || !inheritable_fds.unwrap().contains(io_fd) {
|
||||
let ret = minijail_preserve_fd(self.jail, dev_null.as_raw_fd(), *io_fd);
|
||||
if ret < 0 {
|
||||
return Err(Error::PreservingFd(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
minijail_close_open_fds(self.jail);
|
||||
|
||||
let ret = minijail_fork(self.jail);
|
||||
if ret < 0 {
|
||||
return Err(Error::ForkingMinijail(ret));
|
||||
}
|
||||
Ok(ret as pid_t)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Minijail {
|
||||
/// Frees the Minijail created in Minijail::new.
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// Destroys the minijail's memory. It is safe to do here because all references to
|
||||
// this object have been dropped.
|
||||
minijail_destroy(self.jail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Count the number of files in the directory specified by `path`.
|
||||
fn count_dir_entries<P: AsRef<Path>>(path: P) -> io::Result<usize> {
|
||||
Ok(fs::read_dir(path)?.count())
|
||||
}
|
||||
|
||||
// Return true if the current thread is the only thread in the process.
|
||||
fn is_single_threaded() -> io::Result<bool> {
|
||||
match count_dir_entries("/proc/self/task") {
|
||||
Ok(1) => Ok(true),
|
||||
Ok(_) => Ok(false),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn create_and_free() {
|
||||
unsafe {
|
||||
let j = minijail_new();
|
||||
assert_ne!(std::ptr::null_mut(), j);
|
||||
minijail_destroy(j);
|
||||
}
|
||||
|
||||
let j = Minijail::new().unwrap();
|
||||
drop(j);
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Test that setting a seccomp filter with no-new-privs works as non-root.
|
||||
// This is equivalent to minijail0 -n -S <seccomp_policy>
|
||||
fn seccomp_no_new_privs() {
|
||||
let mut j = Minijail::new().unwrap();
|
||||
j.no_new_privs();
|
||||
j.parse_seccomp_filters(Path::new("src/test_filter.policy"))
|
||||
.unwrap();
|
||||
j.use_seccomp_filter();
|
||||
unsafe {
|
||||
j.fork(None).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Test that open FDs get closed and that FDs in the inherit list are left open.
|
||||
fn close_fds() {
|
||||
unsafe {
|
||||
// Using libc to open/close FDs for testing.
|
||||
const FILE_PATH: &[u8] = b"/dev/null\0";
|
||||
let j = Minijail::new().unwrap();
|
||||
let first = libc::open(FILE_PATH.as_ptr() as *const i8, libc::O_RDONLY);
|
||||
assert!(first >= 0);
|
||||
let second = libc::open(FILE_PATH.as_ptr() as *const i8, libc::O_RDONLY);
|
||||
assert!(second >= 0);
|
||||
let fds: Vec<RawFd> = vec![0, 1, 2, first];
|
||||
if j.fork(Some(&fds)).unwrap() == 0 {
|
||||
assert!(libc::close(second) < 0); // Should fail as second should be closed already.
|
||||
assert_eq!(libc::close(first), 0); // Should succeed as first should be untouched.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // privileged operation.
|
||||
fn chroot() {
|
||||
let mut j = Minijail::new().unwrap();
|
||||
j.enter_chroot(Path::new(".")).unwrap();
|
||||
unsafe {
|
||||
j.fork(None).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore] // privileged operation.
|
||||
fn namespace_vfs() {
|
||||
let mut j = Minijail::new().unwrap();
|
||||
j.namespace_vfs();
|
||||
unsafe {
|
||||
j.fork(None).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn run() {
|
||||
let j = Minijail::new().unwrap();
|
||||
j.run(Path::new("/bin/true"), &[], &[]).unwrap();
|
||||
}
|
||||
}
|
|
@ -1,134 +0,0 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
use libc::{gid_t, pid_t, rlim64_t, uid_t};
|
||||
use std::os::raw::{c_char, c_int, c_ulong};
|
||||
|
||||
/// Struct minijail is an opaque type inside libminijail.
|
||||
/// See the minijail man page for a description of functions.
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub enum minijail {}
|
||||
|
||||
#[link(name = "minijail")]
|
||||
extern "C" {
|
||||
pub fn minijail_new() -> *mut minijail;
|
||||
pub fn minijail_change_uid(j: *mut minijail, uid: uid_t);
|
||||
pub fn minijail_change_gid(j: *mut minijail, gid: gid_t);
|
||||
pub fn minijail_set_supplementary_gids(j: *mut minijail, size: usize, list: *const gid_t);
|
||||
pub fn minijail_keep_supplementary_gids(j: *mut minijail);
|
||||
pub fn minijail_change_user(j: *mut minijail, user: *const c_char) -> c_int;
|
||||
pub fn minijail_change_group(j: *mut minijail, group: *const c_char) -> c_int;
|
||||
pub fn minijail_rlimit(j: *mut minijail, kind: c_int, cur: rlim64_t, max: rlim64_t) -> c_int;
|
||||
pub fn minijail_use_seccomp(j: *mut minijail);
|
||||
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);
|
||||
pub fn minijail_use_caps(j: *mut minijail, capmask: u64);
|
||||
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_ulong);
|
||||
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;
|
||||
pub fn minijail_gidmap(j: *mut minijail, gidmap: *const c_char) -> c_int;
|
||||
pub fn minijail_remount_proc_readonly(j: *mut minijail);
|
||||
pub fn minijail_run_as_init(j: *mut minijail);
|
||||
pub fn minijail_write_pid_file(j: *mut minijail, path: *const c_char) -> c_int;
|
||||
pub fn minijail_inherit_usergroups(j: *mut minijail);
|
||||
pub fn minijail_use_alt_syscall(j: *mut minijail, table: *const c_char) -> c_int;
|
||||
pub fn minijail_add_to_cgroup(j: *mut minijail, path: *const c_char) -> c_int;
|
||||
pub fn minijail_enter_chroot(j: *mut minijail, dir: *const c_char) -> c_int;
|
||||
pub fn minijail_enter_pivot_root(j: *mut minijail, dir: *const c_char) -> c_int;
|
||||
pub fn minijail_fork(j: *mut minijail) -> pid_t;
|
||||
pub fn minijail_get_original_path(j: *mut minijail, chroot_path: *const c_char) -> *mut c_char;
|
||||
pub fn minijail_mount_dev(j: *mut minijail);
|
||||
pub fn minijail_mount_tmp(j: *mut minijail);
|
||||
pub fn minijail_mount_tmp_size(j: *mut minijail, size: usize);
|
||||
pub fn minijail_mount_with_data(
|
||||
j: *mut minijail,
|
||||
src: *const c_char,
|
||||
dest: *const c_char,
|
||||
type_: *const c_char,
|
||||
flags: c_ulong,
|
||||
data: *const c_char,
|
||||
) -> c_int;
|
||||
pub fn minijail_mount(
|
||||
j: *mut minijail,
|
||||
src: *const c_char,
|
||||
dest: *const c_char,
|
||||
type_: *const c_char,
|
||||
flags: c_ulong,
|
||||
) -> c_int;
|
||||
pub fn minijail_bind(
|
||||
j: *mut minijail,
|
||||
src: *const c_char,
|
||||
dest: *const c_char,
|
||||
writeable: c_int,
|
||||
) -> c_int;
|
||||
pub fn minijail_preserve_fd(j: *mut minijail, parent_fd: c_int, child_fd: c_int) -> c_int;
|
||||
pub fn minijail_enter(j: *const minijail);
|
||||
pub fn minijail_run(
|
||||
j: *mut minijail,
|
||||
filename: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
) -> c_int;
|
||||
pub fn minijail_run_no_preload(
|
||||
j: *mut minijail,
|
||||
filename: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
) -> c_int;
|
||||
pub fn minijail_run_pid(
|
||||
j: *mut minijail,
|
||||
filename: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
pchild_pid: *mut pid_t,
|
||||
) -> c_int;
|
||||
pub fn minijail_run_pipe(
|
||||
j: *mut minijail,
|
||||
filename: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
pstdin_fd: *mut c_int,
|
||||
) -> c_int;
|
||||
pub fn minijail_run_pid_pipes(
|
||||
j: *mut minijail,
|
||||
filename: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
pchild_pid: *mut pid_t,
|
||||
pstdin_fd: *mut c_int,
|
||||
pstdout_fd: *mut c_int,
|
||||
pstderr_fd: *mut c_int,
|
||||
) -> c_int;
|
||||
pub fn minijail_run_pid_pipes_no_preload(
|
||||
j: *mut minijail,
|
||||
filename: *const c_char,
|
||||
argv: *const *const c_char,
|
||||
pchild_pid: *mut pid_t,
|
||||
pstdin_fd: *mut c_int,
|
||||
pstdout_fd: *mut c_int,
|
||||
pstderr_fd: *mut c_int,
|
||||
) -> c_int;
|
||||
pub fn minijail_kill(j: *mut minijail) -> c_int;
|
||||
pub fn minijail_wait(j: *mut minijail) -> c_int;
|
||||
pub fn minijail_destroy(j: *mut minijail);
|
||||
} // extern "C"
|
|
@ -1,7 +0,0 @@
|
|||
close: 1
|
||||
exit: 1
|
||||
futex: 1
|
||||
getpid: 1
|
||||
lseek: 1
|
||||
read: 1
|
||||
write: 1
|
18
src/linux.rs
18
src/linux.rs
|
@ -35,8 +35,8 @@ use devices::{
|
|||
self, Ac97Backend, Ac97Dev, HostBackendDeviceProvider, PciDevice, VfioContainer, VfioDevice,
|
||||
VfioPciDevice, VirtioPciDevice, XhciController,
|
||||
};
|
||||
use io_jail::{self, Minijail};
|
||||
use kvm::*;
|
||||
use minijail::{self, Minijail};
|
||||
use msg_socket::{MsgError, MsgReceiver, MsgSender, MsgSocket};
|
||||
use net_util::{Error as NetError, MacAddress, Tap};
|
||||
use remain::sorted;
|
||||
|
@ -96,8 +96,8 @@ pub enum Error {
|
|||
CreateTpmStorage(PathBuf, io::Error),
|
||||
CreateUsbProvider(devices::usb::host_backend::error::Error),
|
||||
CreateVfioDevice(devices::vfio::VfioError),
|
||||
DeviceJail(io_jail::Error),
|
||||
DevicePivotRoot(io_jail::Error),
|
||||
DeviceJail(minijail::Error),
|
||||
DevicePivotRoot(minijail::Error),
|
||||
Disk(PathBuf, io::Error),
|
||||
DiskImageLock(sys_util::Error),
|
||||
DropCapabilities(sys_util::Error),
|
||||
|
@ -107,7 +107,7 @@ pub enum Error {
|
|||
InputEventsOpen(std::io::Error),
|
||||
InvalidFdPath,
|
||||
InvalidWaylandPath,
|
||||
IoJail(io_jail::Error),
|
||||
IoJail(minijail::Error),
|
||||
LoadKernel(Box<dyn StdError>),
|
||||
MemoryTooLarge,
|
||||
NetDeviceNew(virtio::NetError),
|
||||
|
@ -138,9 +138,9 @@ pub enum Error {
|
|||
ReservePmemMemory(sys_util::MmapError),
|
||||
ResetTimerFd(sys_util::Error),
|
||||
RngDeviceNew(virtio::RngError),
|
||||
SettingGidMap(io_jail::Error),
|
||||
SettingMaxOpenFiles(io_jail::Error),
|
||||
SettingUidMap(io_jail::Error),
|
||||
SettingGidMap(minijail::Error),
|
||||
SettingMaxOpenFiles(minijail::Error),
|
||||
SettingUidMap(minijail::Error),
|
||||
SignalFd(sys_util::SignalFdError),
|
||||
SpawnVcpu(io::Error),
|
||||
TimerFd(sys_util::Error),
|
||||
|
@ -248,8 +248,8 @@ impl Display for Error {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<io_jail::Error> for Error {
|
||||
fn from(err: io_jail::Error) -> Self {
|
||||
impl From<minijail::Error> for Error {
|
||||
fn from(err: minijail::Error) -> Self {
|
||||
Error::IoJail(err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ use libc::{
|
|||
use protobuf::ProtobufError;
|
||||
use remain::sorted;
|
||||
|
||||
use io_jail::{self, Minijail};
|
||||
use kvm::{Cap, Datamatch, IoeventAddress, Kvm, Vcpu, VcpuExit, Vm};
|
||||
use minijail::{self, Minijail};
|
||||
use net_util::{Error as TapError, Tap, TapT};
|
||||
use sys_util::{
|
||||
block_signal, clear_signal, drop_capabilities, error, getegid, geteuid, info, pipe,
|
||||
|
@ -50,7 +50,7 @@ pub enum Error {
|
|||
CloneVcpuPipe(io::Error),
|
||||
CreateEventFd(SysError),
|
||||
CreateIrqChip(SysError),
|
||||
CreateJail(io_jail::Error),
|
||||
CreateJail(minijail::Error),
|
||||
CreateKvm(SysError),
|
||||
CreateMainSocket(SysError),
|
||||
CreatePIT(SysError),
|
||||
|
@ -64,21 +64,21 @@ pub enum Error {
|
|||
DecodeRequest(ProtobufError),
|
||||
DropCapabilities(SysError),
|
||||
EncodeResponse(ProtobufError),
|
||||
Mount(io_jail::Error),
|
||||
MountDev(io_jail::Error),
|
||||
MountLib(io_jail::Error),
|
||||
MountLib64(io_jail::Error),
|
||||
MountPlugin(io_jail::Error),
|
||||
MountPluginLib(io_jail::Error),
|
||||
MountProc(io_jail::Error),
|
||||
MountRoot(io_jail::Error),
|
||||
Mount(minijail::Error),
|
||||
MountDev(minijail::Error),
|
||||
MountLib(minijail::Error),
|
||||
MountLib64(minijail::Error),
|
||||
MountPlugin(minijail::Error),
|
||||
MountPluginLib(minijail::Error),
|
||||
MountProc(minijail::Error),
|
||||
MountRoot(minijail::Error),
|
||||
NoRootDir,
|
||||
ParsePivotRoot(io_jail::Error),
|
||||
ParseSeccomp(io_jail::Error),
|
||||
ParsePivotRoot(minijail::Error),
|
||||
ParseSeccomp(minijail::Error),
|
||||
PluginFailed(i32),
|
||||
PluginKill(SysError),
|
||||
PluginKilled(i32),
|
||||
PluginRunJail(io_jail::Error),
|
||||
PluginRunJail(minijail::Error),
|
||||
PluginSocketHup,
|
||||
PluginSocketPoll(SysError),
|
||||
PluginSocketRecv(SysError),
|
||||
|
@ -90,8 +90,8 @@ pub enum Error {
|
|||
PollContextAdd(SysError),
|
||||
RootNotAbsolute,
|
||||
RootNotDir,
|
||||
SetGidMap(io_jail::Error),
|
||||
SetUidMap(io_jail::Error),
|
||||
SetGidMap(minijail::Error),
|
||||
SetUidMap(minijail::Error),
|
||||
SigChild {
|
||||
pid: u32,
|
||||
signo: u32,
|
||||
|
|
|
@ -20,9 +20,9 @@ use libc::{pid_t, waitpid, EINVAL, ENODATA, ENOTTY, WEXITSTATUS, WIFEXITED, WNOH
|
|||
|
||||
use protobuf::Message;
|
||||
|
||||
use io_jail::Minijail;
|
||||
use kvm::{dirty_log_bitmap_size, Datamatch, IoeventAddress, IrqRoute, IrqSource, PicId, Vm};
|
||||
use kvm_sys::{kvm_clock_data, kvm_ioapic_state, kvm_pic_state, kvm_pit_state2};
|
||||
use minijail::Minijail;
|
||||
use protos::plugin::*;
|
||||
use sync::Mutex;
|
||||
use sys_util::{
|
||||
|
|
|
@ -9,12 +9,12 @@ arch = { path = "../arch" }
|
|||
assertions = { path = "../assertions" }
|
||||
data_model = { path = "../data_model" }
|
||||
devices = { path = "../devices" }
|
||||
io_jail = { path = "../io_jail" }
|
||||
kernel_cmdline = { path = "../kernel_cmdline" }
|
||||
kernel_loader = { path = "../kernel_loader" }
|
||||
kvm = { path = "../kvm" }
|
||||
kvm_sys = { path = "../kvm_sys" }
|
||||
libc = "*"
|
||||
minijail = "*"
|
||||
remain = "*"
|
||||
resources = { path = "../resources" }
|
||||
sync = { path = "../sync" }
|
||||
|
|
|
@ -65,8 +65,8 @@ use devices::{
|
|||
Ioapic, PciAddress, PciConfigIo, PciDevice, PciInterruptPin, Pic, IOAPIC_BASE_ADDRESS,
|
||||
IOAPIC_MEM_LENGTH_BYTES,
|
||||
};
|
||||
use io_jail::Minijail;
|
||||
use kvm::*;
|
||||
use minijail::Minijail;
|
||||
use remain::sorted;
|
||||
use resources::SystemAllocator;
|
||||
use sync::Mutex;
|
||||
|
|
Loading…
Reference in a new issue