diff --git a/src/main.rs b/src/main.rs index d18cb28..e631f96 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,39 @@ +use std::{self, ffi::CString, path}; + // Usage: your_docker.sh run ... fn main() { - // You can use print statements as follows for debugging, they'll be visible when running tests. - // println!("Logs from your program will appear here!"); - - // Uncomment this block to pass the first stage! let args: Vec<_> = std::env::args().collect(); let command = &args[3]; let command_args = &args[4..]; + + let base = "/tmp/mydocker"; + let base_path = path::Path::new(base); + + // prevent cryptic "no such file or directory" error inside chroot + std::fs::create_dir_all(base_path.join("dev")).unwrap(); + std::fs::File::create(base_path.join("dev/null")).unwrap(); + + // copy over binary into chroot + let command_path = path::Path::new(command).strip_prefix("/").unwrap(); + std::fs::create_dir_all(base_path.join(command_path.parent().unwrap())) + .expect("Failed to create directory for executed binary"); + std::fs::copy(command, base_path.join(command_path)) + .expect("Failed copying executed binary to chroot directory"); + + // create and change into chroot + let cbase_path = CString::new(base.to_owned()).unwrap(); + unsafe { + libc::chroot(cbase_path.as_ptr()); + } + + // ensure that directory changed to root of jail + std::env::set_current_dir("/").expect("Failed to change to root dir"); + let output = std::process::Command::new(command) .args(command_args) .output() .unwrap(); - + let std_out = std::str::from_utf8(&output.stdout).unwrap(); print!("{}", std_out); let std_err = std::str::from_utf8(&output.stderr).unwrap(); @@ -19,6 +41,6 @@ fn main() { match output.status.code() { Some(code) => std::process::exit(code), - None => std::process::exit(1) + None => std::process::exit(1), } }