netsim_embed_machine/
namespace.rs

1use std::fs::File;
2use std::io::{self, Write};
3use std::os::unix::io::AsRawFd;
4
5pub fn unshare_user() -> Result<(), io::Error> {
6    let uid = unsafe { libc::geteuid() };
7    let gid = unsafe { libc::getegid() };
8
9    unsafe { errno!(libc::unshare(libc::CLONE_NEWUSER))? };
10
11    let mut f = File::create("/proc/self/uid_map")?;
12    let s = format!("0 {uid} 1\n");
13    f.write_all(s.as_bytes())?;
14
15    let mut f = File::create("/proc/self/setgroups")?;
16    f.write_all(b"deny\n")?;
17
18    let mut f = File::create("/proc/self/gid_map")?;
19    let s = format!("0 {gid} 1\n");
20    f.write_all(s.as_bytes())?;
21
22    Ok(())
23}
24
25#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
26pub struct Namespace {
27    pid: i32,
28    tid: i64,
29}
30
31impl Namespace {
32    pub fn current() -> Result<Self, io::Error> {
33        unsafe {
34            let pid = errno!(libc::getpid())?;
35            let tid = errno!(libc::syscall(libc::SYS_gettid))?;
36            Ok(Self { pid, tid })
37        }
38    }
39
40    pub fn unshare() -> Result<Self, io::Error> {
41        unsafe {
42            errno!(libc::unshare(libc::CLONE_NEWNET | libc::CLONE_NEWUTS))?;
43        }
44        Self::current()
45    }
46
47    pub fn enter(&self) -> Result<(), io::Error> {
48        let fd = File::open(self.to_string())?;
49        unsafe {
50            errno!(libc::setns(fd.as_raw_fd(), libc::CLONE_NEWNET))?;
51        }
52        Ok(())
53    }
54}
55
56impl std::fmt::Display for Namespace {
57    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
58        write!(f, "/proc/{}/task/{}/ns/net", self.pid, self.tid)
59    }
60}