Skip to content

Commit f9a4323

Browse files
committed
auto merge of #16340 : thestinger/rust/pie, r=brson
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).
2 parents 1712ab2 + 3cbff72 commit f9a4323

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

src/librustc/back/link.rs

+15-3
Original file line numberDiff line numberDiff line change
@@ -1400,6 +1400,20 @@ fn link_args(cmd: &mut Command,
14001400
cmd.arg("-Wl,--gc-sections");
14011401
}
14021402

1403+
let used_link_args = sess.cstore.get_used_link_args().borrow();
1404+
1405+
// Dynamically linked executables can be compiled as position independent if the default
1406+
// relocation model of position independent code is not changed. This is a requirement to take
1407+
// advantage of ASLR, as otherwise the functions in the executable are not randomized and can
1408+
// be used during an exploit of a vulnerability in any code.
1409+
if sess.targ_cfg.os == abi::OsLinux {
1410+
let mut args = sess.opts.cg.link_args.iter().chain(used_link_args.iter());
1411+
if !dylib && sess.opts.cg.relocation_model.as_slice() == "pic" &&
1412+
!args.any(|x| x.as_slice() == "-static") {
1413+
cmd.arg("-pie");
1414+
}
1415+
}
1416+
14031417
if sess.targ_cfg.os == abi::OsLinux || sess.targ_cfg.os == abi::OsDragonfly {
14041418
// GNU-style linkers will use this to omit linking to libraries which
14051419
// don't actually fulfill any relocations, but only for libraries which
@@ -1568,9 +1582,7 @@ fn link_args(cmd: &mut Command,
15681582
// Finally add all the linker arguments provided on the command line along
15691583
// with any #[link_args] attributes found inside the crate
15701584
cmd.args(sess.opts.cg.link_args.as_slice());
1571-
for arg in sess.cstore.get_used_link_args().borrow().iter() {
1572-
cmd.arg(arg.as_slice());
1573-
}
1585+
cmd.args(used_link_args.as_slice());
15741586
}
15751587

15761588
// # Native library linking

0 commit comments

Comments
 (0)