about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2016-05-08 12:07:50 -0700
committerSteven Fackler <sfackler@gmail.com>2016-05-12 09:13:58 -0700
commit9393e52d4d2705698a6dfdd2834d41154ee23b64 (patch)
tree891fda15ca59db14bd4131f1ca8c1c9f79a2a902 /src/libstd/sys
parent6dbb0e86aec11050480beb76eade6fb805010ba7 (diff)
downloadrust-9393e52d4d2705698a6dfdd2834d41154ee23b64.tar.gz
rust-9393e52d4d2705698a6dfdd2834d41154ee23b64.zip
Don't use env::current_exe with libbacktrace
If the path we give to libbacktrace doesn't actually correspond to the
current process, libbacktrace will segfault *at best*.

cc #21889
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/common/gnu/libbacktrace.rs49
1 files changed, 12 insertions, 37 deletions
diff --git a/src/libstd/sys/common/gnu/libbacktrace.rs b/src/libstd/sys/common/gnu/libbacktrace.rs
index db719ccce61..b5802afc109 100644
--- a/src/libstd/sys/common/gnu/libbacktrace.rs
+++ b/src/libstd/sys/common/gnu/libbacktrace.rs
@@ -15,7 +15,6 @@ use sys_common::backtrace::{output, output_fileline};
 
 pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void,
              symaddr: *mut libc::c_void) -> io::Result<()> {
-    use env;
     use ffi::CStr;
     use ptr;
 
@@ -110,46 +109,22 @@ pub fn print(w: &mut Write, idx: isize, addr: *mut libc::c_void,
     // that is calculated the first time this is requested. Remember that
     // backtracing all happens serially (one global lock).
     //
-    // An additionally oddity in this function is that we initialize the
-    // filename via self_exe_name() to pass to libbacktrace. It turns out
-    // that on Linux libbacktrace seamlessly gets the filename of the
-    // current executable, but this fails on freebsd. by always providing
-    // it, we make sure that libbacktrace never has a reason to not look up
-    // the symbols. The libbacktrace API also states that the filename must
-    // be in "permanent memory", so we copy it to a static and then use the
-    // static as the pointer.
+    // Things don't work so well on not-Linux since libbacktrace can't track
+    // down that executable this is. We at one point used env::current_exe but
+    // it turns out that there are some serious security issues with that
+    // approach.
     //
-    // FIXME: We also call self_exe_name() on DragonFly BSD. I haven't
-    //        tested if this is required or not.
+    // Specifically, on certain platforms like BSDs, a malicious actor can cause
+    // an arbitrary file to be placed at the path returned by current_exe.
+    // libbacktrace does not behave defensively in the presence of ill-formed
+    // DWARF information, and has been demonstrated to segfault in at least one
+    // case. There is no evidence at the moment to suggest that a more carefully
+    // constructed file can't cause arbitrary code execution. As a result of all
+    // of this, we don't hint libbacktrace with the path to the current process.
     unsafe fn init_state() -> *mut backtrace_state {
         static mut STATE: *mut backtrace_state = ptr::null_mut();
-        static mut LAST_FILENAME: [libc::c_char; 256] = [0; 256];
         if !STATE.is_null() { return STATE }
-        let selfname = if cfg!(target_os = "freebsd") ||
-            cfg!(target_os = "dragonfly") ||
-            cfg!(target_os = "bitrig") ||
-            cfg!(target_os = "openbsd") ||
-            cfg!(target_os = "windows") {
-                env::current_exe().ok()
-            } else {
-                None
-            };
-        let filename = match selfname.as_ref().and_then(|s| s.to_str()) {
-            Some(path) => {
-                let bytes = path.as_bytes();
-                if bytes.len() < LAST_FILENAME.len() {
-                    let i = bytes.iter();
-                    for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
-                        *slot = *val as libc::c_char;
-                    }
-                    LAST_FILENAME.as_ptr()
-                } else {
-                    ptr::null()
-                }
-            }
-            None => ptr::null(),
-        };
-        STATE = backtrace_create_state(filename, 0, error_cb,
+        STATE = backtrace_create_state(ptr::null(), 0, error_cb,
                                        ptr::null_mut());
         STATE
     }