-
Notifications
You must be signed in to change notification settings - Fork 23
/
dotcntr.rs
86 lines (77 loc) · 2.36 KB
/
dotcntr.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use libc::pid_t;
use nix::fcntl::{self, OFlag};
use nix::sys::stat;
use nix::unistd::Pid;
use simple_error::try_with;
use std::fs::{self, File};
use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::{
fs::{set_permissions, Permissions},
os::unix::fs::PermissionsExt,
};
use crate::capabilities;
use crate::procfs::ProcStatus;
use crate::result::Result;
use crate::tmp;
/// Hidden directory with CAP_CHROOT enabled cntr-exec binary
pub struct DotcntrDir {
pub file: File,
pub dir: tmp::TempDir,
}
impl DotcntrDir {
pub fn write_pid_file(&self, target_pid: Pid) -> Result<()> {
let path = self.dir.path().join("pid");
let mut file = try_with!(File::create(&path), "failed to create {}", path.display());
let raw_pid: pid_t = target_pid.into();
try_with!(
file.write_all(format!("{}", raw_pid).as_bytes()),
"failed to write {}",
path.display()
);
Ok(())
}
pub fn write_setcap_exe(&self) -> Result<()> {
let path = self.dir.path().join("cntr-exec");
try_with!(
fs::copy("/proc/self/exe", &path),
"failed to copy /proc/self/exe to {}",
path.display()
);
try_with!(
capabilities::set_chroot_capability(&path),
"Failed set file capability CAP_SYS_CHROOT on {}",
path.display()
);
Ok(())
}
}
pub fn create(process_status: &ProcStatus) -> Result<DotcntrDir> {
let dotcntr_dir = try_with!(tmp::tempdir(), "failed to create temporary directory");
let permissions = Permissions::from_mode(0o755);
try_with!(
set_permissions(dotcntr_dir.path(), permissions),
"cannot change permissions of '{}'",
dotcntr_dir.path().display()
);
let dotcntr_fd = try_with!(
fcntl::open(
dotcntr_dir.path(),
OFlag::O_RDONLY | OFlag::O_CLOEXEC,
stat::Mode::all(),
),
"failed to open '{}' directory",
dotcntr_dir.path().display()
);
let dotcntr_file = unsafe { File::from_raw_fd(dotcntr_fd) };
let d = DotcntrDir {
file: dotcntr_file,
dir: dotcntr_dir,
};
try_with!(d.write_setcap_exe(), "failed to create setcap executable");
try_with!(
d.write_pid_file(process_status.local_pid),
"failed to create pid file"
);
Ok(d)
}