summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock360
-rw-r--r--Cargo.toml1
-rw-r--r--src/executor.rs7
-rw-r--r--src/main.rs42
-rw-r--r--src/prepared_command.rs100
-rw-r--r--src/runner.rs2
-rw-r--r--src/runner/runc.rs88
-rw-r--r--src/runner/runc/init.rs47
-rw-r--r--src/runner/runc/run.rs18
-rw-r--r--src/types.rs4
-rw-r--r--src/unshare.rs31
-rw-r--r--src/util.rs20
12 files changed, 542 insertions, 178 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 5c5545a..29936a6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,12 +1,34 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
+name = "autocfg"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+
+[[package]]
+name = "bincode"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
+dependencies = [
+ "byteorder",
+ "serde",
+]
+
+[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
+name = "byteorder"
+version = "1.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b"
+
+[[package]]
name = "cc"
version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -14,17 +36,130 @@ checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48"
[[package]]
name = "cfg-if"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
+
+[[package]]
+name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+name = "crossbeam-channel"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
+dependencies = [
+ "crossbeam-utils",
+ "maybe-uninit",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
+dependencies = [
+ "autocfg",
+ "cfg-if 0.1.10",
+ "lazy_static",
+]
+
+[[package]]
name = "dtoa"
version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e"
[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "fuchsia-zircon"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
+dependencies = [
+ "bitflags",
+ "fuchsia-zircon-sys",
+]
+
+[[package]]
+name = "fuchsia-zircon-sys"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
+
+[[package]]
+name = "getrandom"
+version = "0.1.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi 0.9.0+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "getrandom"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "wasi 0.10.2+wasi-snapshot-preview1",
+]
+
+[[package]]
+name = "iovec"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "ipc-channel"
+version = "0.14.1"
+source = "git+https://github.com/NeoRaider/ipc-channel.git?branch=integration#5dc12c729c316574af2245447648632ddd50de63"
+dependencies = [
+ "bincode",
+ "crossbeam-channel",
+ "fnv",
+ "lazy_static",
+ "libc",
+ "mio",
+ "rand 0.7.3",
+ "serde",
+ "tempfile",
+ "uuid",
+]
+
+[[package]]
+name = "kernel32-sys"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
name = "libc"
version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -42,7 +177,55 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
- "cfg-if",
+ "cfg-if 1.0.0",
+]
+
+[[package]]
+name = "maybe-uninit"
+version = "2.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
+
+[[package]]
+name = "mio"
+version = "0.6.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4"
+dependencies = [
+ "cfg-if 0.1.10",
+ "fuchsia-zircon",
+ "fuchsia-zircon-sys",
+ "iovec",
+ "kernel32-sys",
+ "libc",
+ "log",
+ "miow",
+ "net2",
+ "slab",
+ "winapi 0.2.8",
+]
+
+[[package]]
+name = "miow"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
+dependencies = [
+ "kernel32-sys",
+ "net2",
+ "winapi 0.2.8",
+ "ws2_32-sys",
+]
+
+[[package]]
+name = "net2"
+version = "0.2.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae"
+dependencies = [
+ "cfg-if 0.1.10",
+ "libc",
+ "winapi 0.3.9",
]
[[package]]
@@ -53,11 +236,17 @@ checksum = "b2ccba0cfe4fdf15982d1674c69b1fd80bad427d293849982668dfe454bd61f2"
dependencies = [
"bitflags",
"cc",
- "cfg-if",
+ "cfg-if 1.0.0",
"libc",
]
[[package]]
+name = "ppv-lite86"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857"
+
+[[package]]
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -76,9 +265,91 @@ dependencies = [
]
[[package]]
+name = "rand"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
+dependencies = [
+ "getrandom 0.1.16",
+ "libc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc 0.2.0",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
+dependencies = [
+ "libc",
+ "rand_chacha 0.3.0",
+ "rand_core 0.6.1",
+ "rand_hc 0.3.0",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.1",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
+dependencies = [
+ "getrandom 0.1.16",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
+dependencies = [
+ "getrandom 0.2.2",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
+dependencies = [
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
+dependencies = [
+ "rand_core 0.6.1",
+]
+
+[[package]]
name = "rebel"
version = "0.1.0"
dependencies = [
+ "ipc-channel",
"libc",
"nix",
"scopeguard",
@@ -89,6 +360,24 @@ dependencies = [
]
[[package]]
+name = "redox_syscall"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi 0.3.9",
+]
+
+[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -136,6 +425,12 @@ dependencies = [
]
[[package]]
+name = "slab"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
+
+[[package]]
name = "syn"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -147,6 +442,20 @@ dependencies = [
]
[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "rand 0.8.3",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi 0.3.9",
+]
+
+[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -163,17 +472,44 @@ dependencies = [
]
[[package]]
+name = "uuid"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
+dependencies = [
+ "getrandom 0.2.2",
+]
+
+[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
dependencies = [
"same-file",
- "winapi",
+ "winapi 0.3.9",
"winapi-util",
]
[[package]]
+name = "wasi"
+version = "0.9.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+
+[[package]]
+name = "wasi"
+version = "0.10.2+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
+
+[[package]]
+name = "winapi"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
+
+[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -184,6 +520,12 @@ dependencies = [
]
[[package]]
+name = "winapi-build"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+
+[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -195,7 +537,7 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
- "winapi",
+ "winapi 0.3.9",
]
[[package]]
@@ -205,6 +547,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
+name = "ws2_32-sys"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
+dependencies = [
+ "winapi 0.2.8",
+ "winapi-build",
+]
+
+[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index ce0ef33..c32da16 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
+ipc-channel = { git = "https://github.com/NeoRaider/ipc-channel.git", branch = "integration" }
libc = "0.2.84"
nix = "0.19.1"
scopeguard = "1.1.0"
diff --git a/src/executor.rs b/src/executor.rs
index 814aa79..1340f83 100644
--- a/src/executor.rs
+++ b/src/executor.rs
@@ -50,7 +50,7 @@ impl<'a> Executor<'a> {
fn run_one(&mut self, runner: &impl runner::Runner) -> runner::Result<()> {
let task = self.tasks_runnable.pop().expect("No runnable tasks left");
- runner.run(&task)?;
+ runner.run(self.tasks, &task)?;
let rdeps = self.rdeps.get(&task);
@@ -69,10 +69,9 @@ impl<'a> Executor<'a> {
Ok(())
}
- pub fn run(&mut self) -> runner::Result<()> {
- let runner = runner::runc::RuncRunner::new(self.tasks);
+ pub fn run(&mut self, runner: &impl runner::Runner) -> runner::Result<()> {
while !self.tasks_runnable.is_empty() {
- self.run_one(&runner)?;
+ self.run_one(runner)?;
}
assert!(self.tasks_blocked.is_empty(), "No runnable tasks left");
diff --git a/src/main.rs b/src/main.rs
index 8d4787d..d3ac7c8 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,4 @@
mod executor;
-mod prepared_command;
mod recipe;
mod resolve;
mod runner;
@@ -7,43 +6,13 @@ mod types;
mod unshare;
mod util;
-use nix::{
- mount::{self, MsFlags},
- unistd,
-};
-use std::{io::Result, path::Path};
+use std::path::Path;
use types::*;
-use util::ToIOResult;
-
-fn mount_buildtmp() -> Result<()> {
- mount::mount::<_, _, _, str>(
- Some("buildtmp"),
- "build/tmp",
- Some("tmpfs"),
- MsFlags::empty(),
- None,
- )
- .to_io_result()
-}
-
-fn exec_shell() -> Result<std::convert::Infallible> {
- let bin_sh = std::ffi::CString::new("/bin/sh").unwrap();
- unistd::execv(&bin_sh, &[&bin_sh]).to_io_result()
-}
-
-fn execute(mut exc: executor::Executor) -> Result<()> {
- unshare::unshare()?;
- mount_buildtmp()?;
-
- exc.run()?;
-
- exec_shell()?;
-
- Ok(())
-}
fn main() {
+ let runner = unsafe { runner::runc::RuncRunner::new() }.unwrap();
+
let recipes = recipe::read_recipes(Path::new("examples")).unwrap();
let mut tasks: TaskMap = TaskMap::default();
@@ -64,9 +33,8 @@ fn main() {
std::process::exit(1);
}
let taskset = rsv.to_taskset();
- let exc = executor::Executor::new(&tasks, taskset);
-
- if let Err(error) = execute(exc) {
+ let mut exc = executor::Executor::new(&tasks, taskset);
+ if let Err(error) = exc.run(&runner) {
eprintln!("{}", error);
std::process::exit(1);
}
diff --git a/src/prepared_command.rs b/src/prepared_command.rs
deleted file mode 100644
index 8297095..0000000
--- a/src/prepared_command.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-use std::{
- ffi::{CString, OsStr},
- io::{Error, ErrorKind, Result},
- iter,
- os::unix::{ffi::*, io::RawFd},
- ptr,
-};
-
-use libc::{c_char, c_void};
-use nix::{fcntl::OFlag, sys::wait, unistd};
-
-use crate::util::ToIOResult;
-
-#[derive(Clone, Debug)]
-pub struct PreparedCommandBuilder {
- program: CString,
- args: Vec<CString>,
-}
-
-#[derive(Debug)]
-pub struct PreparedCommand {
- child: unistd::Pid,
- pipew: RawFd,
-}
-
-impl Drop for PreparedCommand {
- fn drop(&mut self) {
- assert!(unistd::close(self.pipew).is_ok());
- }
-}
-
-fn os2c<S: AsRef<OsStr>>(s: S) -> CString {
- CString::new(s.as_ref().as_bytes()).unwrap()
-}
-
-impl PreparedCommandBuilder {
- pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self {
- self.args.push(os2c(arg));
- self
- }
-
- pub fn prepare(&mut self) -> Result<PreparedCommand> {
- let exe_p = self.program.as_ptr();
-
- let argv: Vec<*const c_char> = iter::once(exe_p)
- .chain(self.args.iter().map(|arg| arg.as_ptr()))
- .chain(iter::once(ptr::null()))
- .collect();
-
- let argv_p = argv.as_ptr();
-
- let (piper, pipew) = unistd::pipe2(OFlag::O_CLOEXEC).to_io_result()?;
-
- unsafe {
- match unistd::fork().to_io_result()? {
- unistd::ForkResult::Parent { child } => {
- let cmd = PreparedCommand { child, pipew };
- assert!(unistd::close(piper).is_ok());
- return Ok(cmd);
- }
- unistd::ForkResult::Child => {}
- }
-
- // Child process - only async-signal-safe calls allowed
-
- if libc::close(pipew) != 0 {
- libc::_exit(126);
- }
-
- // Wait for run trigger
- let mut buf = [0u8; 1];
- if libc::read(piper, buf.as_mut_ptr() as *mut c_void, buf.len()) != 1 {
- // PreparedCommand was dropped, or controlling process exited
- libc::_exit(126);
- }
-
- libc::execvp(exe_p, argv_p);
-
- // exec failed
- libc::_exit(127);
- }
- }
-}
-
-impl PreparedCommand {
- pub fn new<S: AsRef<OsStr>>(program: S) -> PreparedCommandBuilder {
- PreparedCommandBuilder {
- program: os2c(program),
- args: Vec::new(),
- }
- }
-
- pub fn run(self) -> Result<wait::WaitStatus> {
- if unistd::write(self.pipew, &[0]).to_io_result()? != 1 {
- return Err(Error::new(ErrorKind::Other, "command trigger write failed"));
- }
-
- wait::waitpid(Some(self.child), None).to_io_result()
- }
-}
diff --git a/src/runner.rs b/src/runner.rs
index a290aeb..810586c 100644
--- a/src/runner.rs
+++ b/src/runner.rs
@@ -7,5 +7,5 @@ use crate::types::*;
pub type Result<T> = io::Result<T>;
pub trait Runner {
- fn run(&self, task: &TaskRef) -> Result<()>;
+ fn run(&self, tasks: &TaskMap, task: &TaskRef) -> Result<()>;
}
diff --git a/src/runner/runc.rs b/src/runner/runc.rs
index b323d5d..663dc7a 100644
--- a/src/runner/runc.rs
+++ b/src/runner/runc.rs
@@ -1,21 +1,87 @@
-use super::*;
-use crate::types::TaskMap;
+mod init;
+mod run;
-pub struct RuncRunner<'a> {
- tasks: &'a TaskMap,
+use std::{io, process};
+
+use ipc_channel::ipc;
+use nix::unistd;
+use serde::{Deserialize, Serialize};
+
+use crate::types::*;
+use crate::unshare;
+use crate::util::CheckDisconnect;
+
+#[derive(Debug, Deserialize, Serialize)]
+struct Request(TaskRef, Task, ipc::IpcSender<run::Error>);
+
+fn runner(init_error_sender: ipc::IpcSender<init::Error>, channel: ipc::IpcReceiver<Request>) -> ! {
+ if let Err(error) = init::runc_initialize() {
+ init_error_sender.send(error).expect("IPC send() failed");
+ process::exit(1);
+ }
+
+ drop(init_error_sender);
+
+ while let Ok(request) = channel.recv() {
+ let Request(task, task_def, reply_sender) = request;
+ if let Err(error) = run::handle_task(task, task_def) {
+ reply_sender.send(error).expect("IPC send() failed");
+ }
+ }
+
+ process::exit(0);
+}
+
+pub struct RuncRunner {
+ channel: ipc::IpcSender<Request>,
}
-impl<'a> RuncRunner<'a> {
- pub fn new(tasks: &'a TaskMap) -> Self {
- RuncRunner { tasks }
+impl RuncRunner {
+ /// Creates a new Runc runner
+ ///
+ /// Unsafe: Do not call in multithreaded processes
+ pub unsafe fn new() -> io::Result<Self> {
+ let (tx, rx) = ipc::channel().expect("IPC channel creation failed");
+ let (init_error_tx, init_error_rx) = ipc::channel().expect("IPC channel creation failed");
+
+ let pid = match unistd::fork().expect("fork()") {
+ unistd::ForkResult::Parent { child } => {
+ drop(rx);
+ drop(init_error_tx);
+ child
+ }
+ unistd::ForkResult::Child => {
+ drop(tx);
+ drop(init_error_rx);
+ runner(init_error_tx, rx);
+ /* Not reached */
+ }
+ };
+
+ init_error_rx
+ .recv()
+ .check_disconnect()
+ .expect("IPC recv() error")?;
+
+ unshare::idmap(pid)?;
+
+ Ok(RuncRunner { channel: tx })
}
}
-impl<'a> Runner for RuncRunner<'a> {
- fn run(&self, task: &TaskRef) -> Result<()> {
- let task_def = self.tasks.get(task).expect("Invalid TaskRef");
+impl super::Runner for RuncRunner {
+ fn run(&self, tasks: &TaskMap, task: &TaskRef) -> super::Result<()> {
+ let task_def = tasks.get(task).expect("Invalid TaskRef");
+ let (reply_tx, reply_rx) = ipc::channel().expect("IPC channel creation failed");
+
+ self.channel
+ .send(Request(task.clone(), task_def.clone(), reply_tx))
+ .expect("RuncRunner task submission failed");
- println!("{}:\n\t{:?}", task, task_def);
+ reply_rx
+ .recv()
+ .check_disconnect()
+ .expect("IPC recv() error")?;
Ok(())
}
diff --git a/src/runner/runc/init.rs b/src/runner/runc/init.rs
new file mode 100644
index 0000000..02b89e4
--- /dev/null
+++ b/src/runner/runc/init.rs
@@ -0,0 +1,47 @@
+use std::io;
+
+use nix::{
+ mount::{self, MsFlags},
+ sched::{self, CloneFlags},
+};
+use serde::{Deserialize, Serialize};
+
+fn mount_buildtmp() -> nix::Result<()> {
+ mount::mount::<_, _, _, str>(
+ Some("buildtmp"),
+ "build/tmp",
+ Some("tmpfs"),
+ MsFlags::empty(),
+ None,
+ )
+}
+
+#[derive(Debug, Deserialize, Serialize)]
+pub enum Error {
+ Code(i32),
+ String(String),
+}
+
+impl From<nix::Error> for Error {
+ fn from(error: nix::Error) -> Self {
+ match error {
+ nix::Error::Sys(code) => Error::Code(code as i32),
+ _ => Error::String(error.to_string()),
+ }
+ }
+}
+
+impl From<Error> for io::Error {
+ fn from(error: Error) -> Self {
+ match error {
+ Error::Code(code) => io::Error::from_raw_os_error(code),
+ Error::String(string) => io::Error::new(io::ErrorKind::Other, string),
+ }
+ }
+}
+
+pub fn runc_initialize() -> Result<(), Error> {
+ sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS)?;
+ mount_buildtmp()?;
+ Ok(())
+}
diff --git a/src/runner/runc/run.rs b/src/runner/runc/run.rs
new file mode 100644
index 0000000..2d13330
--- /dev/null
+++ b/src/runner/runc/run.rs
@@ -0,0 +1,18 @@
+use std::io;
+
+use serde::{Deserialize, Serialize};
+
+use crate::types::*;
+#[derive(Debug, Deserialize, Serialize)]
+pub struct Error;
+
+impl From<Error> for io::Error {
+ fn from(_: Error) -> Self {
+ io::Error::new(io::ErrorKind::Other, "Failed to run task")
+ }
+}
+
+pub fn handle_task(task: TaskRef, task_def: Task) -> Result<(), Error> {
+ println!("{}:\n\t{:?}", task, task_def);
+ Ok(())
+}
diff --git a/src/types.rs b/src/types.rs
index 1773504..331b49a 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -1,9 +1,9 @@
-use serde::Deserialize;
+use serde::{Deserialize, Serialize};
use std::collections::HashMap;
pub type TaskRef = String;
-#[derive(Clone, Debug, Deserialize)]
+#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Task {
#[serde(default)]
pub depends: Vec<TaskRef>,
diff --git a/src/unshare.rs b/src/unshare.rs
index a8ec1c1..da16d24 100644
--- a/src/unshare.rs
+++ b/src/unshare.rs
@@ -4,15 +4,13 @@ use std::{
io::{self, BufRead, Result},
os::unix::ffi::*,
path::Path,
+ process,
};
-use nix::{
- sched::{self, CloneFlags},
- unistd,
-};
+use nix::unistd;
-use crate::prepared_command::PreparedCommand;
-use crate::util::{Checkable, ToIOResult};
+// use crate::prepared_command::PreparedCommand;
+use crate::util::Checkable;
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
struct SubIDRange {
@@ -98,27 +96,22 @@ fn get_gid_map() -> Result<Vec<SubIDMap>> {
Ok(generate_idmap(gid, gid_ranges))
}
-fn prepare_idmap_cmd(cmd: &str, pid: &str, map: &Vec<SubIDMap>) -> Result<PreparedCommand> {
- let mut builder = PreparedCommand::new(cmd);
- builder.arg(&pid);
+fn run_idmap_cmd(cmd: &str, pid: &str, map: &Vec<SubIDMap>) -> Result<()> {
+ let mut builder = process::Command::new(cmd);
+ builder.arg(pid);
for uids in map {
builder.arg(uids.lower.to_string());
builder.arg(uids.upper.to_string());
builder.arg(uids.count.to_string());
}
- builder.prepare()
+ builder.status().and_then(|status| status.check())
}
-pub fn unshare() -> Result<()> {
- let pid = unistd::getpid().to_string();
-
- let newuidmap = prepare_idmap_cmd("newuidmap", pid.as_str(), &get_uid_map()?)?;
- let newgidmap = prepare_idmap_cmd("newgidmap", pid.as_str(), &get_gid_map()?)?;
-
- sched::unshare(CloneFlags::CLONE_NEWUSER | CloneFlags::CLONE_NEWNS).to_io_result()?;
+pub fn idmap(pid: unistd::Pid) -> Result<()> {
+ let pid_string = pid.to_string();
- newuidmap.run()?.check()?;
- newgidmap.run()?.check()?;
+ run_idmap_cmd("newuidmap", pid_string.as_str(), &get_uid_map()?)?;
+ run_idmap_cmd("newgidmap", pid_string.as_str(), &get_gid_map()?)?;
Ok(())
}
diff --git a/src/util.rs b/src/util.rs
index 4e996e8..0418c51 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -1,8 +1,10 @@
use std::{
io::{Error, ErrorKind, Result},
process::ExitStatus,
+ result,
};
+use ipc_channel::ipc;
use nix::sys::wait;
pub trait ToIOResult<T> {
@@ -46,3 +48,21 @@ impl Checkable for wait::WaitStatus {
}
}
}
+
+pub trait CheckDisconnect {
+ type Output;
+
+ fn check_disconnect(self) -> Result<Self::Output>;
+}
+
+impl<T> CheckDisconnect for result::Result<T, ipc::IpcError> {
+ type Output = result::Result<(), T>;
+
+ fn check_disconnect(self) -> Result<Self::Output> {
+ match self {
+ Ok(v) => Ok(Err(v)),
+ Err(ipc::IpcError::Disconnected) => Ok(Ok(())),
+ Err(error) => Err(Error::new(ErrorKind::Other, format!("{:?}", error))),
+ }
+ }
+}