clone3 wrapper

This commit is contained in:
Jake Hillion 2022-02-11 16:27:45 +00:00
parent b46cc001be
commit 565c1567c4
7 changed files with 425 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

4
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "rust-lang.rust"
}

241
Cargo.lock generated Normal file
View File

@ -0,0 +1,241 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "clone-shim"
version = "0.1.0"
dependencies = [
"env_logger",
"libc",
"log",
"nix",
"thiserror",
]
[[package]]
name = "env_logger"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"
dependencies = [
"atty",
"humantime",
"log",
"regex",
"termcolor",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
"libc",
]
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "libc"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e74d72e0f9b65b5b4ca49a346af3976df0f9c61d550727f349ecd559f251a26c"
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "nix"
version = "0.23.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
"memoffset",
]
[[package]]
name = "proc-macro2"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
dependencies = [
"proc-macro2",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "syn"
version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "termcolor"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4"
dependencies = [
"winapi-util",
]
[[package]]
name = "thiserror"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

14
Cargo.toml Normal file
View File

@ -0,0 +1,14 @@
[package]
name = "clone-shim"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
log = "0.4"
env_logger = "0.9"
thiserror = "1"
libc = "0.2.117"
nix = "0.23.1"

130
src/clone.rs Normal file
View File

@ -0,0 +1,130 @@
use std::fs::File;
use std::marker::PhantomData;
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use libc::{pid_t, syscall, SYS_clone3};
use nix::errno::Errno;
pub use nix::sched::CloneFlags;
use nix::sys::signal::Signal;
use nix::unistd::Pid;
pub struct CloneArgs<'a> {
pub flags: CloneFlags,
pub pidfd: Option<&'a mut File>,
pidfd_int: RawFd,
pub child_tid: Option<&'a mut Pid>,
child_tid_int: pid_t,
pub parent_tid: Option<&'a mut Pid>,
parent_tid_int: pid_t,
pub exit_signal: Option<Signal>,
pub stack: Option<&'a mut [u8]>,
pub set_tid: Option<&'a [Pid]>,
pub cgroup: Option<&'a File>,
}
#[repr(C)]
struct CloneArgsInternal<'a> {
flags: u64,
pidfd: u64,
child_tid: u64,
parent_tid: u64,
exit_signal: u64,
stack: u64,
stack_size: u64,
tls: u64,
set_tid: u64,
set_tid_size: u64,
cgroup: u64,
phantom: PhantomData<&'a ()>,
}
impl<'a: 'b, 'b: 'c, 'c> CloneArgs<'a> {
pub fn new(flags: CloneFlags) -> CloneArgs<'a> {
CloneArgs {
flags,
pidfd: None,
pidfd_int: 0,
child_tid: None,
child_tid_int: 0,
parent_tid: None,
parent_tid_int: 0,
exit_signal: None,
stack: None,
set_tid: None,
cgroup: None,
}
}
fn process(&'b mut self) -> CloneArgsInternal<'c> {
CloneArgsInternal {
flags: self.flags.bits() as u64,
pidfd: self
.pidfd
.as_ref()
.map(|_| (self.pidfd_int) as *mut RawFd as u64)
.unwrap_or(0),
child_tid: self
.child_tid
.as_ref()
.map(|_| self.child_tid_int as *mut pid_t as u64)
.unwrap_or(0),
parent_tid: self
.parent_tid
.as_ref()
.map(|_| self.parent_tid_int as *mut pid_t as u64)
.unwrap_or(0),
exit_signal: self.exit_signal.map(|s| s as i32 as u64).unwrap_or(0),
stack: self
.stack
.as_mut()
.map(|s| s.as_mut_ptr() as u64)
.unwrap_or(0),
stack_size: self.stack.as_ref().map(|s| s.len() as u64).unwrap_or(0),
tls: 0,
set_tid: self
.set_tid
.as_ref()
.map(|s| s.as_ptr() as u64)
.unwrap_or(0),
set_tid_size: self.set_tid.as_ref().map(|s| s.len() as u64).unwrap_or(0),
cgroup: self.cgroup.map(|c| c.as_raw_fd() as u64).unwrap_or(0),
phantom: PhantomData,
}
}
fn finalise(&mut self) {
if let Some(r) = &mut self.pidfd {
**r = unsafe { File::from_raw_fd(self.pidfd_int) };
}
if let Some(r) = &mut self.child_tid {
**r = Pid::from_raw(self.child_tid_int);
}
if let Some(r) = &mut self.parent_tid {
**r = Pid::from_raw(self.parent_tid_int);
}
}
}
pub fn clone3(mut args: CloneArgs) -> nix::Result<Pid> {
let args_int: CloneArgsInternal = args.process();
let result = unsafe { syscall(SYS_clone3, &args_int, std::mem::size_of_val(&args_int)) };
let out = Errno::result(result).map(|p| Pid::from_raw(p as i32))?;
args.finalise();
Ok(out)
}

7
src/error.rs Normal file
View File

@ -0,0 +1,7 @@
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("{msg}: {src}")]
Nix { msg: &'static str, src: nix::Error },
}

28
src/main.rs Normal file
View File

@ -0,0 +1,28 @@
use log::info;
mod clone;
mod error;
use clone::{clone3, CloneArgs, CloneFlags};
use error::Error;
use nix::unistd::Pid;
fn main() -> Result<(), Error> {
let env = env_logger::Env::new().filter_or("LOG", "info");
env_logger::init_from_env(env);
info!("getting started");
if clone3(CloneArgs::new(CloneFlags::empty())).map_err(|e| Error::Nix {
msg: "clone3",
src: e,
})? != Pid::from_raw(0)
{
info!("hello from the child");
} else {
info!("hello from the parent");
}
Ok(())
}