@@ -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>;
5556pub 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
6264impl < ' 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
94113pub 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
0 commit comments