summary refs log tree commit diff
path: root/io_jail/src
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2017-06-26 18:24:36 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-06-28 00:59:00 -0700
commitfa8c6802b6a392a3dbc6300fabb47eeebf219ed6 (patch)
tree114002ed8b014339c69c25f72b421e6937835bcc /io_jail/src
parentb4af07af9c54e7b5b2f2e55369b9ac74025a6853 (diff)
downloadcrosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.tar
crosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.tar.gz
crosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.tar.bz2
crosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.tar.lz
crosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.tar.xz
crosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.tar.zst
crosvm-fa8c6802b6a392a3dbc6300fabb47eeebf219ed6.zip
io_jail: Overwrite standard I/O FDs
The FDs for stdin, stdout, and stderr shouldn't be left empty.  Just
closing these FDs causes the next open() call from the jailed process to
reuse the 0, 1, or 2 FD.  This confuses basic infrastructure like
println!.

Change-Id: I40ea471b4a011f2be5132e1a0ff50656ae2ec14a
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/549659
Diffstat (limited to 'io_jail/src')
-rw-r--r--io_jail/src/lib.rs25
1 files changed, 21 insertions, 4 deletions
diff --git a/io_jail/src/lib.rs b/io_jail/src/lib.rs
index 0c9af8b..04b8070 100644
--- a/io_jail/src/lib.rs
+++ b/io_jail/src/lib.rs
@@ -12,16 +12,20 @@ mod libminijail;
 
 use std::ffi::CString;
 use std::fs;
-use std::os::unix::io::RawFd;
+use std::os::unix::io::{AsRawFd, RawFd};
 use std::path::Path;
 use std::str::FromStr;
 
-#[derive(Clone, Copy, Debug)]
+#[derive(Debug)]
 pub enum Error {
     /// minjail_new failed, this is an allocation failure.
     CreatingMinijail,
     /// The path or name string passed in didn't parse to a valid CString.
     InvalidCString,
+    /// Failed to call dup2 to set stdin, stdout, or stderr to /dev/null.
+    DupDevNull(i32),
+    /// Failed to set up /dev/null for FDs 0, 1, or 2.
+    OpenDevNull(std::io::Error),
     /// Setting the specified alt-syscall table failed with errno. Is the table in the kernel?
     SetAltSyscallTable(i32),
     /// chroot failed with the provided errno.
@@ -207,8 +211,10 @@ impl Minijail {
 
     /// Enters the previously configured minijail.
     /// `enter` is unsafe because it closes all open FD for this process.  That
-    /// could cause a lot of trouble if not handled carefully.
-    /// This Function aborts on error because a partially entered jail isn't
+    /// could cause a lot of trouble if not handled carefully.  FDs 0, 1, and 2
+    /// are overwritten with /dev/null FDs unless they are included in the
+    /// inheritable_fds list.
+    /// This Function may abort on error because a partially entered jail isn't
     /// recoverable.
     pub unsafe fn enter(&self, inheritable_fds: Option<&[RawFd]>) -> Result<()> {
         if let Some(keep_fds) = inheritable_fds {
@@ -241,6 +247,17 @@ impl Minijail {
             // return an error but won't break anything.
             libc::close(fd);
         }
+        // Set stdin, stdout, and stderr to /dev/null unless they are in the inherit list.
+        // These will only be closed when this process exits.
+        let dev_null = fs::File::open("/dev/null").map_err(Error::OpenDevNull)?;
+        for io_fd in &[libc::STDIN_FILENO, libc::STDOUT_FILENO, libc::STDERR_FILENO] {
+            if !inheritable_fds.contains(io_fd) {
+                let ret = libc::dup2(dev_null.as_raw_fd(), *io_fd);
+                if ret < 0 {
+                    return Err(Error::DupDevNull(*libc::__errno_location()));
+                }
+            }
+        }
         Ok(())
     }
 }