Skip to content

Commit

Permalink
auto merge of #16340 : thestinger/rust/pie, r=brson
Browse files Browse the repository at this point in the history
Rust already builds all code as position independent by default, so the
linker can be told to build a position independent executable if it's
not disabled with `-C relocation-model=dynamic-no-pic`. Position
independent code does have a significant cost on i686 (not on x86_64 or
ARM) but there's no significant cost to linking code that's already
position independent as a position independent executable.

Address space layout randomization makes exploiting vulnerabilities much
more difficult by providing a statistical defence against an attempt to
find or modify existing code / data. Without ASLR, it's trivial to use a
vulnerability to take over control of the process via return-oriented
programming.

Rust code can be used for return-oriented programming whether it is safe
or unsafe, so even a fully safe application needs to be built as a
position independent executable to defend against vulnerabilities in
unsafe blocks or C libraries.

Sample program:

    extern crate libc;

    use std::mem;

    static mut global: u32 = 5;
    static constant: u32 = 5;
    fn foo() {}

    fn main() {
        let local = 5;
        println!("stack: {}, global: {}, constant: {}, fn: {}, lib fn: {}",
                 &local as *const u32,
                 unsafe { &global as *const u32 },
                 &constant as *const u32,
                 unsafe { mem::transmute::<_, *const ()>(foo) },
                 unsafe { mem::transmute::<_, *const ()>(libc::mprotect) });
    }

Before:

    stack: 0x3ff15eb9f94, global: 0x6ab488, constant: 0x47db40, fn: 0x4030e0, lib fn: 0x32749547530
    stack: 0x3b5d47d80e4, global: 0x6ab488, constant: 0x47db40, fn: 0x4030e0, lib fn: 0x394469a7530
    stack: 0x3fe2c4e5564, global: 0x6ab488, constant: 0x47db40, fn: 0x4030e0, lib fn: 0x399734a2530
    stack: 0x3e525e0fb24, global: 0x6ab488, constant: 0x47db40, fn: 0x4030e0, lib fn: 0x2f62a810530
    stack: 0x3b50fb3eae4, global: 0x6ab488, constant: 0x47db40, fn: 0x4030e0, lib fn: 0x2e590e86530

After:

    stack: 0x38cf12c90a4, global: 0x3e2d46b488, constant: 0x3e2d23cf80, fn: 0x3e2d1c2510, lib fn: 0x2617d3b4530
    stack: 0x3d733faf474, global: 0x7eb1839488, constant: 0x7eb160af80, fn: 0x7eb1590510, lib fn: 0x32d30c1f530
    stack: 0x3bb42212ec4, global: 0x5bbb365488, constant: 0x5bbb136f80, fn: 0x5bbb0bc510, lib fn: 0x3595e6c1530
    stack: 0x39f678c1ab4, global: 0x22c4e3c488, constant: 0x22c4c0df80, fn: 0x22c4b93510, lib fn: 0x3835b727530
    stack: 0x3afb25bd394, global: 0x493eab2488, constant: 0x493e883f80, fn: 0x493e809510, lib fn: 0x3478d6a7530

This may also be necessary on other platforms, but I can only test on
Linux right now. Note that GDB gained support for debugging position
independent executables in version 7.1 (March 2010).
  • Loading branch information
bors committed Aug 9, 2014
2 parents 1712ab2 + 3cbff72 commit f9a4323
Showing 1 changed file with 15 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1400,6 +1400,20 @@ fn link_args(cmd: &mut Command,
cmd.arg("-Wl,--gc-sections");
}

let used_link_args = sess.cstore.get_used_link_args().borrow();

// Dynamically linked executables can be compiled as position independent if the default
// relocation model of position independent code is not changed. This is a requirement to take
// advantage of ASLR, as otherwise the functions in the executable are not randomized and can
// be used during an exploit of a vulnerability in any code.
if sess.targ_cfg.os == abi::OsLinux {
let mut args = sess.opts.cg.link_args.iter().chain(used_link_args.iter());
if !dylib && sess.opts.cg.relocation_model.as_slice() == "pic" &&
!args.any(|x| x.as_slice() == "-static") {
cmd.arg("-pie");
}
}

if sess.targ_cfg.os == abi::OsLinux || sess.targ_cfg.os == abi::OsDragonfly {
// GNU-style linkers will use this to omit linking to libraries which
// don't actually fulfill any relocations, but only for libraries which
Expand Down Expand Up @@ -1568,9 +1582,7 @@ fn link_args(cmd: &mut Command,
// Finally add all the linker arguments provided on the command line along
// with any #[link_args] attributes found inside the crate
cmd.args(sess.opts.cg.link_args.as_slice());
for arg in sess.cstore.get_used_link_args().borrow().iter() {
cmd.arg(arg.as_slice());
}
cmd.args(used_link_args.as_slice());
}

// # Native library linking
Expand Down

0 comments on commit f9a4323

Please sign in to comment.