From: Johannes Löthberg Date: Mon, 10 Jul 2017 18:57:45 +0000 (+0200) Subject: Add support for full RELRO X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=230668765d5a1c435cfd6d6a101aaee0f67de2dc;p=rust.git Add support for full RELRO This commit adds support for full RELRO, and enables it for the platforms I know have support for it. Full RELRO makes the PLT+GOT data read-only on startup, preventing it from being overwritten. http://tk-blog.blogspot.com/2009/02/relro-not-so-well-known-memory.html Fixes rust-lang/rust#29877. Signed-off-by: Johannes Löthberg --- diff --git a/src/librustc_back/target/bitrig_base.rs b/src/librustc_back/target/bitrig_base.rs index 5c4e01886a4..5a0ab83cd72 100644 --- a/src/librustc_back/target/bitrig_base.rs +++ b/src/librustc_back/target/bitrig_base.rs @@ -19,6 +19,7 @@ pub fn opts() -> TargetOptions { linker_is_gnu: true, has_rpath: true, position_independent_executables: true, + full_relro: true, .. Default::default() } diff --git a/src/librustc_back/target/dragonfly_base.rs b/src/librustc_back/target/dragonfly_base.rs index e44cd393289..ca116e82379 100644 --- a/src/librustc_back/target/dragonfly_base.rs +++ b/src/librustc_back/target/dragonfly_base.rs @@ -33,6 +33,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, pre_link_args: args, position_independent_executables: true, + full_relro: true, exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() } diff --git a/src/librustc_back/target/freebsd_base.rs b/src/librustc_back/target/freebsd_base.rs index e44cd393289..ca116e82379 100644 --- a/src/librustc_back/target/freebsd_base.rs +++ b/src/librustc_back/target/freebsd_base.rs @@ -33,6 +33,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, pre_link_args: args, position_independent_executables: true, + full_relro: true, exe_allocation_crate: super::maybe_jemalloc(), .. Default::default() } diff --git a/src/librustc_back/target/haiku_base.rs b/src/librustc_back/target/haiku_base.rs index 8e7f463563c..c52b28708c3 100644 --- a/src/librustc_back/target/haiku_base.rs +++ b/src/librustc_back/target/haiku_base.rs @@ -18,6 +18,7 @@ pub fn opts() -> TargetOptions { executables: true, has_rpath: false, target_family: Some("unix".to_string()), + full_relro: true, linker_is_gnu: true, no_integrated_as: true, .. Default::default() diff --git a/src/librustc_back/target/linux_base.rs b/src/librustc_back/target/linux_base.rs index 722d2fa16ef..e4e7f062f88 100644 --- a/src/librustc_back/target/linux_base.rs +++ b/src/librustc_back/target/linux_base.rs @@ -36,6 +36,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, pre_link_args: args, position_independent_executables: true, + full_relro: true, exe_allocation_crate: super::maybe_jemalloc(), has_elf_tls: true, .. Default::default() diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index edbbcf6f0b6..673c01f4b7e 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -367,6 +367,9 @@ pub struct TargetOptions { /// the functions in the executable are not randomized and can be used /// during an exploit of a vulnerability in any code. pub position_independent_executables: bool, + /// Full RELRO makes the dynamic linker resolve all symbols at startup and marks the GOT + /// read-only before starting the program, preventing overwriting the GOT. + pub full_relro: bool, /// Format that archives should be emitted in. This affects whether we use /// LLVM to assemble an archive or fall back to the system linker, and /// currently only "gnu" is used to fall into LLVM. Unknown strings cause @@ -454,6 +457,7 @@ fn default() -> TargetOptions { has_rpath: false, no_default_libraries: true, position_independent_executables: false, + full_relro: false, pre_link_objects_exe: Vec::new(), pre_link_objects_dll: Vec::new(), post_link_objects: Vec::new(), @@ -683,6 +687,7 @@ macro_rules! key { key!(has_rpath, bool); key!(no_default_libraries, bool); key!(position_independent_executables, bool); + key!(full_relro, bool); key!(archive_format); key!(allow_asm, bool); key!(custom_unwind_resume, bool); @@ -870,6 +875,7 @@ macro_rules! target_option_val { target_option_val!(has_rpath); target_option_val!(no_default_libraries); target_option_val!(position_independent_executables); + target_option_val!(full_relro); target_option_val!(archive_format); target_option_val!(allow_asm); target_option_val!(custom_unwind_resume); diff --git a/src/librustc_back/target/netbsd_base.rs b/src/librustc_back/target/netbsd_base.rs index 63245fcae76..1d7d1b36008 100644 --- a/src/librustc_back/target/netbsd_base.rs +++ b/src/librustc_back/target/netbsd_base.rs @@ -33,6 +33,7 @@ pub fn opts() -> TargetOptions { has_rpath: true, pre_link_args: args, position_independent_executables: true, + full_relro: true, .. Default::default() } } diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index 051028d5c4a..df17f853b3b 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -34,6 +34,7 @@ pub fn opts() -> TargetOptions { is_like_openbsd: true, pre_link_args: args, position_independent_executables: true, + full_relro: true, .. Default::default() } } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index a4bbdef82f0..238b7fd2e19 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -1029,6 +1029,10 @@ fn link_args(cmd: &mut Linker, } } + if t.options.full_relro { + cmd.full_relro(); + } + // Pass optimization flags down to the linker. cmd.optimize(); diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 0b15886083a..025b5795659 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -104,6 +104,7 @@ pub trait Linker { fn add_object(&mut self, path: &Path); fn gc_sections(&mut self, keep_metadata: bool); fn position_independent_executable(&mut self); + fn full_relro(&mut self); fn optimize(&mut self); fn debuginfo(&mut self); fn no_default_libraries(&mut self); @@ -175,6 +176,7 @@ impl<'a> Linker for GccLinker<'a> { fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); } fn add_object(&mut self, path: &Path) { self.cmd.arg(path); } fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); } + fn full_relro(&mut self) { self.linker_arg("-z,relro,-z,now"); } fn args(&mut self, args: &[String]) { self.cmd.args(args); } fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { @@ -428,6 +430,10 @@ fn position_independent_executable(&mut self) { // noop } + fn full_relro(&mut self) { + // noop + } + fn no_default_libraries(&mut self) { // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC // as there's been trouble in the past of linking the C++ standard @@ -595,6 +601,10 @@ fn position_independent_executable(&mut self) { // noop } + fn full_relro(&mut self) { + // noop + } + fn args(&mut self, args: &[String]) { self.cmd.args(args); }