rewrite it in rust™ (just for fun)
This commit is contained in:
parent
dec216580a
commit
fe0e531718
51
rust/Cargo.lock
generated
Normal file
51
rust/Cargo.lock
generated
Normal file
@ -0,0 +1,51 @@
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.43"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "qsni"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "void"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[metadata]
|
||||
"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
|
||||
"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16"
|
||||
"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3"
|
||||
"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
|
||||
"checksum nix 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d37e713a259ff641624b6cb20e3b12b2952313ba36b6823c0f16e6cfd9e5de17"
|
||||
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
7
rust/Cargo.toml
Normal file
7
rust/Cargo.toml
Normal file
@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "qsni"
|
||||
version = "0.1.0"
|
||||
authors = ["Albert S. <mail@quitesimple.org>"]
|
||||
|
||||
[dependencies]
|
||||
nix = "0.11.0"
|
105
rust/src/main.rs
Normal file
105
rust/src/main.rs
Normal file
@ -0,0 +1,105 @@
|
||||
use std::env;
|
||||
use std::io::BufReader;
|
||||
use std::io::BufRead;
|
||||
use std::io::Error;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Write;
|
||||
use std::ffi::CString;
|
||||
|
||||
static PROFILEPATH : &'static str ="/etc/qsni.d/";
|
||||
static NET_CLS_DIR : &'static str="/sys/fs/cgroup/net_cls/";
|
||||
extern crate nix;
|
||||
|
||||
|
||||
fn ensure_outside_profile()
|
||||
{
|
||||
let fp = std::fs::File::open("/proc/self/cgroup").expect("Error opening cgroups file of process");
|
||||
let bf = BufReader::new(fp);
|
||||
for line in bf.lines() {
|
||||
let currentline = line.expect("Error while reading line");
|
||||
let splitted : Vec<&str> = currentline.split(':').collect();
|
||||
if splitted.len() < 3 {
|
||||
panic!("Misformated line in cgroups file!");
|
||||
}
|
||||
if splitted[1] == "net_cls" && splitted[2] != "/" {
|
||||
panic!("already assigned to a net class, thus you can't use this binary to change that");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init_profile(profilepath : &str)
|
||||
{
|
||||
use nix::unistd::*;
|
||||
use nix::sys::wait::*;
|
||||
match fork()
|
||||
{
|
||||
Ok(ForkResult::Parent { child, .. }) => {
|
||||
let waitresult = waitpid(child, Some(WaitPidFlag::empty())).expect("waitpid failed");
|
||||
match waitresult
|
||||
{
|
||||
WaitStatus::Exited(pid, code) =>
|
||||
{
|
||||
if code != 0
|
||||
{
|
||||
panic!("profile setup script failed");
|
||||
}
|
||||
},
|
||||
_ => { },
|
||||
}
|
||||
}
|
||||
Ok(ForkResult::Child) => {
|
||||
unsafe { nix::libc::clearenv(); }
|
||||
nix::unistd::execv(&CString::new(profilepath).unwrap(), &[CString::new(profilepath).unwrap()]).expect("Faileed execv");},
|
||||
Err(_) => println!("Fork failed"),
|
||||
}
|
||||
}
|
||||
|
||||
fn assign_to_profile(profilename : &str)
|
||||
{
|
||||
let filename = NET_CLS_DIR.to_owned() + "/" + profilename + "/tasks";
|
||||
let mut file = std::fs::OpenOptions::new().write(true).append(true).open(filename).expect("Failed to open net class file for writing");
|
||||
let mypid = nix::unistd::getpid().to_string();
|
||||
write!(file, "{}", mypid).expect("An error occured while writing the pid");
|
||||
|
||||
}
|
||||
|
||||
fn main()
|
||||
{
|
||||
std::panic::set_hook(Box::new(|pi| {
|
||||
if let Some(s) = pi.payload().downcast_ref::<String>() {
|
||||
eprintln!("{}", s);
|
||||
}
|
||||
eprintln!("Details:");
|
||||
eprintln!("{}", pi);
|
||||
}));
|
||||
let args : Vec<String> = std::env::args().collect();
|
||||
if args.len() < 3 {
|
||||
println!("usage: qsni profile command [arguments...]");
|
||||
std::process::exit(1);
|
||||
}
|
||||
ensure_outside_profile();
|
||||
|
||||
let profilename : &str = &args[1];
|
||||
|
||||
let profilefilepath = PROFILEPATH.to_owned() + profilename;
|
||||
if ! std::path::Path::new(&profilefilepath).exists(){
|
||||
eprintln!("The specified profile {} does not exist", profilename);
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let currentuid = nix::unistd::getuid();
|
||||
let currentgid = nix::unistd::getgid();
|
||||
|
||||
nix::unistd::setuid(nix::unistd::Uid::from_raw(0)).expect("Failed to become root");
|
||||
|
||||
init_profile(&profilefilepath);
|
||||
assign_to_profile(&profilename);
|
||||
|
||||
nix::unistd::setgid(currentgid).expect("setgid failed during drop");
|
||||
nix::unistd::setuid(currentuid).expect("setuid failed during drop");
|
||||
|
||||
let cmd = &args[2];
|
||||
let mut execargs : Vec<CString> = args.iter().skip(3).map(|s| { CString::new(s.as_str()).unwrap() }).collect();
|
||||
execargs.insert(0, CString::new(cmd.as_str()).unwrap());
|
||||
nix::unistd::execvp(&CString::new(cmd.as_str()).unwrap(), &execargs).expect("execv failed launching your program");
|
||||
}
|
Loading…
Reference in New Issue
Block a user