|
|
@ -1,25 +1,21 @@
|
|
|
|
use std::arch::asm;
|
|
|
|
use std::{io, fs, fmt, os, path};
|
|
|
|
use std::ffi::{CStr, CString};
|
|
|
|
use io::Read;
|
|
|
|
use std::fs::File;
|
|
|
|
use fmt::Display;
|
|
|
|
use std::io::Read;
|
|
|
|
use os::fd::{AsFd, AsRawFd};
|
|
|
|
use std::os::fd::{AsFd, AsRawFd};
|
|
|
|
use os::unix::{fs::PermissionsExt, process::CommandExt};
|
|
|
|
use std::os::unix::fs::PermissionsExt;
|
|
|
|
use path::{Path, PathBuf};
|
|
|
|
use std::os::unix::process::CommandExt;
|
|
|
|
|
|
|
|
use nix::libc::{self, setgid, CLONE_NEWCGROUP, MS_NODEV, MS_NOSUID};
|
|
|
|
|
|
|
|
use nix::sched::{clone, CloneCb, CloneFlags, setns};
|
|
|
|
use nix::sched::{clone, CloneCb, CloneFlags, setns};
|
|
|
|
use nix::sys::signal::{kill, Signal};
|
|
|
|
use nix::sys::{signal::{kill, Signal}, wait::{waitpid, WaitPidFlag}};
|
|
|
|
use nix::sys::wait::{wait, waitpid, waitid, WaitPidFlag};
|
|
|
|
use nix::unistd::{dup2, pivot_root, setuid, setgid, Gid, Pid, Uid, User, setgroups};
|
|
|
|
use nix::unistd::{chdir, chroot, dup2, execv, pivot_root, setuid, sleep, Gid, Pid, Uid, User, setgroups};
|
|
|
|
|
|
|
|
use nix::mount::{mount, MntFlags, MsFlags, umount2};
|
|
|
|
use nix::mount::{mount, MntFlags, MsFlags, umount2};
|
|
|
|
use std::path::{Path, PathBuf};
|
|
|
|
|
|
|
|
use clap::Parser;
|
|
|
|
|
|
|
|
use error::{Result, RockerError};
|
|
|
|
|
|
|
|
mod error;
|
|
|
|
|
|
|
|
use uuid;
|
|
|
|
use uuid;
|
|
|
|
use std::{io, fs};
|
|
|
|
|
|
|
|
use toml;
|
|
|
|
use toml;
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
use std::fmt::Display;
|
|
|
|
use clap::Parser;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use error::{Result, RockerError};
|
|
|
|
|
|
|
|
mod error;
|
|
|
|
|
|
|
|
|
|
|
|
static WORKSPACE: &str = "/root/rocker";
|
|
|
|
static WORKSPACE: &str = "/root/rocker";
|
|
|
|
static USER_NAME: &str = "rocker";
|
|
|
|
static USER_NAME: &str = "rocker";
|
|
|
@ -197,7 +193,7 @@ fn init_container_env(env: Option<&String>) -> Result<()>{
|
|
|
|
let env_vec = if env.starts_with("./") || env.starts_with("/") {
|
|
|
|
let env_vec = if env.starts_with("./") || env.starts_with("/") {
|
|
|
|
// 读取出路径指定的文件作为env
|
|
|
|
// 读取出路径指定的文件作为env
|
|
|
|
let env_path = Path::new(env);
|
|
|
|
let env_path = Path::new(env);
|
|
|
|
let mut env_file = File::open(env_path)?;
|
|
|
|
let mut env_file = fs::File::open(env_path)?;
|
|
|
|
let text = {
|
|
|
|
let text = {
|
|
|
|
let mut s = String::new();
|
|
|
|
let mut s = String::new();
|
|
|
|
env_file.read_to_string(&mut s)?;
|
|
|
|
env_file.read_to_string(&mut s)?;
|
|
|
@ -263,7 +259,7 @@ fn init_container_mount() -> Result<()> {
|
|
|
|
fn init_container_log(log: bool) -> Result<()> {
|
|
|
|
fn init_container_log(log: bool) -> Result<()> {
|
|
|
|
let log_path = Path::new("logs");
|
|
|
|
let log_path = Path::new("logs");
|
|
|
|
create_dir(log_path, true)?;
|
|
|
|
create_dir(log_path, true)?;
|
|
|
|
let log_fd = File::create(log_path.join("log"))?;
|
|
|
|
let log_fd = fs::File::create(log_path.join("log"))?;
|
|
|
|
if log {
|
|
|
|
if log {
|
|
|
|
unsafe {
|
|
|
|
unsafe {
|
|
|
|
let log_fd_raw = log_fd.as_raw_fd();
|
|
|
|
let log_fd_raw = log_fd.as_raw_fd();
|
|
|
@ -276,10 +272,8 @@ fn init_container_log(log: bool) -> Result<()> {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn init_container_user(uid: Uid, gid: Gid) -> Result<()>{
|
|
|
|
fn init_container_user(uid: Uid, gid: Gid) -> Result<()>{
|
|
|
|
unsafe {
|
|
|
|
setgid(gid)?;
|
|
|
|
setgid(gid.as_raw());
|
|
|
|
setgroups(&[gid])?;
|
|
|
|
setgroups(&[gid])?;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
setuid(uid)?;
|
|
|
|
setuid(uid)?;
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -292,16 +286,6 @@ fn create_dir<P: AsRef<Path>>(path: P, is_any:bool) -> Result<()> {
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn parse_cmd(run: &String) -> Vec<CString>{
|
|
|
|
|
|
|
|
let args= run
|
|
|
|
|
|
|
|
.split(" ")
|
|
|
|
|
|
|
|
.filter_map(|s| CString::new(s).ok())
|
|
|
|
|
|
|
|
.collect::<Vec<CString>>();
|
|
|
|
|
|
|
|
args
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn check_container_is_running(pid: &Pid, main_exe: &Path) -> Result<bool> {
|
|
|
|
fn check_container_is_running(pid: &Pid, main_exe: &Path) -> Result<bool> {
|
|
|
|
// 检查pid对应的exe是否和外部传过来的相同
|
|
|
|
// 检查pid对应的exe是否和外部传过来的相同
|
|
|
|
let child_exe_s= format!("/proc/{pid}/exe");
|
|
|
|
let child_exe_s= format!("/proc/{pid}/exe");
|
|
|
@ -317,7 +301,7 @@ fn init_exec_ns(pid: i32) -> Result<()>{
|
|
|
|
// 把当前进程加入到指定pid的namespace
|
|
|
|
// 把当前进程加入到指定pid的namespace
|
|
|
|
for ns_name in vec!["ipc", "uts", "net", "pid", "mnt"] {
|
|
|
|
for ns_name in vec!["ipc", "uts", "net", "pid", "mnt"] {
|
|
|
|
let ns_path = format!("/proc/{pid}/ns/{ns_name}");
|
|
|
|
let ns_path = format!("/proc/{pid}/ns/{ns_name}");
|
|
|
|
let ns_fild = File::open(ns_path)?;
|
|
|
|
let ns_fild = fs::File::open(ns_path)?;
|
|
|
|
setns(ns_fild.as_fd(), CloneFlags::from_bits_retain(0))? }
|
|
|
|
setns(ns_fild.as_fd(), CloneFlags::from_bits_retain(0))? }
|
|
|
|
Ok(())
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|