Skip to content

Commit 82f49a0

Browse files
alexandruagalxiord
authored andcommitted
jailer: the chroot base dir is now a parameter
Jails no longer have to be somewhere in "/srv/jail", which is now just a default. Instead, a different base directory can be specified using the --chroot-base-dir command line parameter. Signed-off-by: Alexandru Agache <[email protected]>
1 parent 8ea3498 commit 82f49a0

File tree

3 files changed

+36
-12
lines changed

3 files changed

+36
-12
lines changed

jailer/src/env.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ use libc;
99
use super::cgroup::Cgroup;
1010
use super::{Error, JailerArgs, Result};
1111

12-
const CHROOT_DIR_BASE: &str = "/srv/jailer";
13-
1412
pub struct Env {
1513
cgroup: Cgroup,
1614
chroot_dir: PathBuf,
@@ -24,7 +22,8 @@ impl Env {
2422
let exec_file_name = args.exec_file_name()?;
2523
let cgroup = Cgroup::new(args.id, exec_file_name)?;
2624

27-
let mut chroot_dir = PathBuf::from(CHROOT_DIR_BASE);
25+
let mut chroot_dir = PathBuf::from(&args.chroot_base_dir);
26+
2827
chroot_dir.push(exec_file_name);
2928
chroot_dir.push(args.id);
3029
chroot_dir.push("root");

jailer/src/lib.rs

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ pub enum Error {
3737
Gid(String),
3838
Metadata(PathBuf, io::Error),
3939
NotAFile(PathBuf),
40+
NotAFolder(PathBuf),
4041
OpenDevKvm(sys_util::Error),
4142
OpenDevNetTun(sys_util::Error),
4243
ReadLine(PathBuf, io::Error),
@@ -55,12 +56,19 @@ pub type Result<T> = result::Result<T, Error>;
5556
pub struct JailerArgs<'a> {
5657
id: &'a str,
5758
exec_file_path: PathBuf,
59+
chroot_base_dir: PathBuf,
5860
uid: u32,
5961
gid: u32,
6062
}
6163

6264
impl<'a> JailerArgs<'a> {
63-
pub fn new(id: &'a str, exec_file: &'a str, uid: &str, gid: &str) -> Result<Self> {
65+
pub fn new(
66+
id: &'a str,
67+
exec_file: &str,
68+
chroot_base: &str,
69+
uid: &str,
70+
gid: &str,
71+
) -> Result<Self> {
6472
let exec_file_path =
6573
canonicalize(exec_file).map_err(|e| Error::Canonicalize(PathBuf::from(exec_file), e))?;
6674

@@ -71,6 +79,16 @@ impl<'a> JailerArgs<'a> {
7179
return Err(Error::NotAFile(exec_file_path));
7280
}
7381

82+
let chroot_base_dir = canonicalize(chroot_base)
83+
.map_err(|e| Error::Canonicalize(PathBuf::from(chroot_base), e))?;
84+
85+
if !metadata(&chroot_base_dir)
86+
.map_err(|e| Error::Metadata(exec_file_path.clone(), e))?
87+
.is_dir()
88+
{
89+
return Err(Error::NotAFolder(chroot_base_dir));
90+
}
91+
7492
let uid = uid.parse::<u32>()
7593
.map_err(|_| Error::Uid(String::from(uid)))?;
7694
let gid = gid.parse::<u32>()
@@ -79,6 +97,7 @@ impl<'a> JailerArgs<'a> {
7997
Ok(JailerArgs {
8098
id,
8199
exec_file_path,
100+
chroot_base_dir,
82101
uid,
83102
gid,
84103
})
@@ -93,15 +112,14 @@ impl<'a> JailerArgs<'a> {
93112

94113
pub fn run(args: JailerArgs) -> Result<()> {
95114
// We open /dev/kvm, /dev/tun, and create the listening socket. These file descriptors will be
96-
// passed on to Firecracker post exec, and used as file descriptors 3, 4, and 5, respectively.
115+
// passed on to Firecracker post exec, and used via knowing their values in advance.
97116

98117
// TODO: use dup2 to make sure we're actually getting 3, 4, and 5?
99118

100119
// TODO: can a malicious guest that takes over firecracker use its access to the KVM fd to
101-
// starve the host of resources? (cgroups should take care of that, but do they currently?)
120+
// starve the host of resources? (cgroups should take care of that, but do they currently?)
102121

103-
// Safe because we use a constant nul-terminated string and verify the result. We should
104-
// get our fd = 3 here.
122+
// Safe because we use a constant null-terminated string and verify the result.
105123
let ret = unsafe { libc::open("/dev/kvm\0".as_ptr() as *const libc::c_char, libc::O_RDWR) };
106124
if ret < 0 {
107125
return Err(Error::OpenDevKvm(sys_util::Error::last()));
@@ -111,8 +129,7 @@ pub fn run(args: JailerArgs) -> Result<()> {
111129
}
112130

113131
// TODO: is RDWR required for /dev/tun (most likely)?
114-
// Safe because we use a constant nul-terminated string and verify the result. We should
115-
// get our fd = 4 here.
132+
// Safe because we use a constant null-terminated string and verify the result.
116133
let ret = unsafe {
117134
libc::open(
118135
"/dev/net/tun\0".as_ptr() as *const libc::c_char,
@@ -128,7 +145,6 @@ pub fn run(args: JailerArgs) -> Result<()> {
128145

129146
let env = Env::new(args)?;
130147

131-
// We should get our fd = 5 here.
132148
let listener = UnixListener::bind(env.chroot_dir().join(SOCKET_FILE_NAME))
133149
.map_err(|e| Error::UnixListener(e))?;
134150

src/bin/jailer.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ fn main() -> jailer::Result<()> {
3434
.arg(
3535
Arg::with_name("exec_file")
3636
.long("exec-file")
37-
.help("File path to exec into")
37+
.help("File path to exec into.")
3838
.required(true)
3939
.takes_value(true),
4040
)
@@ -52,12 +52,21 @@ fn main() -> jailer::Result<()> {
5252
.required(true)
5353
.takes_value(true),
5454
)
55+
.arg(
56+
Arg::with_name("chroot_base")
57+
.long("chroot-base-dir")
58+
.help("The base folder where chroot jails are located.")
59+
.required(false)
60+
.default_value("/srv/jailer")
61+
.takes_value(true),
62+
)
5563
.get_matches();
5664

5765
// All arguments are either mandatory, or have default values, so the unwraps should not fail.
5866
let args = JailerArgs::new(
5967
cmd_arguments.value_of("id").unwrap(),
6068
cmd_arguments.value_of("exec_file").unwrap(),
69+
cmd_arguments.value_of("chroot_base").unwrap(),
6170
cmd_arguments.value_of("uid").unwrap(),
6271
cmd_arguments.value_of("gid").unwrap(),
6372
)?;

0 commit comments

Comments
 (0)