about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-04-03 15:30:10 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-04-09 17:07:02 -0700
commitd6c72306c8fc2ec0fd9d6e499c32f2bf52f0b8ba (patch)
tree049c8e404c1f5a73b1a418ea9c69acb0224dab50 /src/libstd/sys
parent88fc543866c2c48b3b1a32e9d55a4eb77d1dee66 (diff)
downloadrust-d6c72306c8fc2ec0fd9d6e499c32f2bf52f0b8ba.tar.gz
rust-d6c72306c8fc2ec0fd9d6e499c32f2bf52f0b8ba.zip
std: Set CLOEXEC for all fds opened on unix
This commit starts to set the CLOEXEC flag for all files and sockets opened by
the standard library by default on all unix platforms. There are a few points of
note in this commit:

* The implementation is not 100% satisfactory in the face of threads. File
  descriptors only have the `F_CLOEXEC` flag set *after* they are opened,
  allowing for a fork/exec to happen in the middle and leak the descriptor.
  Some platforms do support atomically opening a descriptor while setting the
  `CLOEXEC` flag, and it is left as a future extension to bind these apis as it
  is unclear how to do so nicely at this time.

* The implementation does not offer a method of opting into the old behavior of
  not setting `CLOEXEC`. This will possibly be added in the future through
  extensions on `OpenOptions`, for example.

* This change does not yet audit any Windows APIs to see if the handles are
  inherited by default by accident.

This is a breaking change for users who call `fork` or `exec` outside of the
standard library itself and expect file descriptors to be inherted. All file
descriptors created by the standard library will no longer be inherited.

[breaking-change]
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/unix/c.rs42
-rw-r--r--src/libstd/sys/unix/fd.rs15
-rw-r--r--src/libstd/sys/unix/fs2.rs4
-rw-r--r--src/libstd/sys/unix/net.rs15
-rw-r--r--src/libstd/sys/unix/pipe2.rs4
5 files changed, 50 insertions, 30 deletions
diff --git a/src/libstd/sys/unix/c.rs b/src/libstd/sys/unix/c.rs
index 5ae508e4610..282e5668e6e 100644
--- a/src/libstd/sys/unix/c.rs
+++ b/src/libstd/sys/unix/c.rs
@@ -26,39 +26,35 @@ use libc;
           target_os = "dragonfly",
           target_os = "bitrig",
           target_os = "openbsd"))]
-pub const FIONBIO: libc::c_ulong = 0x8004667e;
-#[cfg(any(all(target_os = "linux",
-              any(target_arch = "x86",
-                  target_arch = "x86_64",
-                  target_arch = "arm",
-                  target_arch = "aarch64")),
-          target_os = "android"))]
-pub const FIONBIO: libc::c_ulong = 0x5421;
-#[cfg(all(target_os = "linux",
-          any(target_arch = "mips",
-              target_arch = "mipsel",
-              target_arch = "powerpc")))]
-pub const FIONBIO: libc::c_ulong = 0x667e;
-
-#[cfg(any(target_os = "macos",
-          target_os = "ios",
-          target_os = "freebsd",
-          target_os = "dragonfly",
-          target_os = "bitrig",
-          target_os = "openbsd"))]
-pub const FIOCLEX: libc::c_ulong = 0x20006601;
+mod consts {
+    use libc;
+    pub const FIONBIO: libc::c_ulong = 0x8004667e;
+    pub const FIOCLEX: libc::c_ulong = 0x20006601;
+    pub const FIONCLEX: libc::c_ulong = 0x20006602;
+}
 #[cfg(any(all(target_os = "linux",
               any(target_arch = "x86",
                   target_arch = "x86_64",
                   target_arch = "arm",
                   target_arch = "aarch64")),
           target_os = "android"))]
-pub const FIOCLEX: libc::c_ulong = 0x5451;
+mod consts {
+    use libc;
+    pub const FIONBIO: libc::c_ulong = 0x5421;
+    pub const FIOCLEX: libc::c_ulong = 0x5451;
+    pub const FIONCLEX: libc::c_ulong = 0x5450;
+}
 #[cfg(all(target_os = "linux",
           any(target_arch = "mips",
               target_arch = "mipsel",
               target_arch = "powerpc")))]
-pub const FIOCLEX: libc::c_ulong = 0x6601;
+mod consts {
+    use libc;
+    pub const FIONBIO: libc::c_ulong = 0x667e;
+    pub const FIOCLEX: libc::c_ulong = 0x6601;
+    pub const FIONCLEX: libc::c_ulong = 0x6600;
+}
+pub use self::consts::*;
 
 #[cfg(any(target_os = "macos",
           target_os = "ios",
diff --git a/src/libstd/sys/unix/fd.rs b/src/libstd/sys/unix/fd.rs
index f7c57c3f5e5..4ef09b91c25 100644
--- a/src/libstd/sys/unix/fd.rs
+++ b/src/libstd/sys/unix/fd.rs
@@ -13,6 +13,7 @@ use core::prelude::*;
 use io;
 use libc::{self, c_int, size_t, c_void};
 use mem;
+use sys::c;
 use sys::cvt;
 use sys_common::AsInner;
 
@@ -51,6 +52,20 @@ impl FileDesc {
         }));
         Ok(ret as usize)
     }
+
+    pub fn set_cloexec(&self) {
+        unsafe {
+            let ret = c::ioctl(self.fd, c::FIOCLEX);
+            debug_assert_eq!(ret, 0);
+        }
+    }
+
+    pub fn unset_cloexec(&self) {
+        unsafe {
+            let ret = c::ioctl(self.fd, c::FIONCLEX);
+            debug_assert_eq!(ret, 0);
+        }
+    }
 }
 
 impl AsInner<c_int> for FileDesc {
diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs
index c0426af051b..20b1aac8f45 100644
--- a/src/libstd/sys/unix/fs2.rs
+++ b/src/libstd/sys/unix/fs2.rs
@@ -215,7 +215,9 @@ impl File {
         let fd = try!(cvt_r(|| unsafe {
             libc::open(path.as_ptr(), flags, opts.mode)
         }));
-        Ok(File(FileDesc::new(fd)))
+        let fd = FileDesc::new(fd);
+        fd.set_cloexec();
+        Ok(File(fd))
     }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs
index 908136a42ab..2e1cbb2a1e1 100644
--- a/src/libstd/sys/unix/net.rs
+++ b/src/libstd/sys/unix/net.rs
@@ -47,7 +47,9 @@ impl Socket {
         };
         unsafe {
             let fd = try!(cvt(libc::socket(fam, ty, 0)));
-            Ok(Socket(FileDesc::new(fd)))
+            let fd = FileDesc::new(fd);
+            fd.set_cloexec();
+            Ok(Socket(fd))
         }
     }
 
@@ -56,13 +58,16 @@ impl Socket {
         let fd = try!(cvt_r(|| unsafe {
             libc::accept(self.0.raw(), storage, len)
         }));
-        Ok(Socket(FileDesc::new(fd)))
+        let fd = FileDesc::new(fd);
+        fd.set_cloexec();
+        Ok(Socket(fd))
     }
 
     pub fn duplicate(&self) -> io::Result<Socket> {
-        cvt(unsafe { libc::dup(self.0.raw()) }).map(|fd| {
-            Socket(FileDesc::new(fd))
-        })
+        let fd = try!(cvt(unsafe { libc::dup(self.0.raw()) }));
+        let fd = FileDesc::new(fd);
+        fd.set_cloexec();
+        Ok(Socket(fd))
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
diff --git a/src/libstd/sys/unix/pipe2.rs b/src/libstd/sys/unix/pipe2.rs
index 7af2c0f0b2a..2fd4d6dd311 100644
--- a/src/libstd/sys/unix/pipe2.rs
+++ b/src/libstd/sys/unix/pipe2.rs
@@ -32,7 +32,9 @@ pub unsafe fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
 
 impl AnonPipe {
     pub fn from_fd(fd: libc::c_int) -> AnonPipe {
-        AnonPipe(FileDesc::new(fd))
+        let fd = FileDesc::new(fd);
+        fd.set_cloexec();
+        AnonPipe(fd)
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {