Skip to content

Commit 94b9cc9

Browse files
committed
Support both partial and full RELRO
Signed-off-by: Johannes Löthberg <[email protected]>
1 parent 2306687 commit 94b9cc9

File tree

12 files changed

+110
-28
lines changed

12 files changed

+110
-28
lines changed

src/librustc/session/config.rs

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use self::DebugInfoLevel::*;
1919
use session::{early_error, early_warn, Session};
2020
use session::search_paths::SearchPaths;
2121

22-
use rustc_back::{LinkerFlavor, PanicStrategy};
22+
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
2323
use rustc_back::target::Target;
2424
use lint;
2525
use middle::cstore;
@@ -654,6 +654,8 @@ macro_rules! options {
654654
Some("a number");
655655
pub const parse_panic_strategy: Option<&'static str> =
656656
Some("either `panic` or `abort`");
657+
pub const parse_relro_level: Option<&'static str> =
658+
Some("one of: `full`, `partial`, or `off`");
657659
pub const parse_sanitizer: Option<&'static str> =
658660
Some("one of: `address`, `leak`, `memory` or `thread`");
659661
pub const parse_linker_flavor: Option<&'static str> =
@@ -665,7 +667,7 @@ macro_rules! options {
665667
#[allow(dead_code)]
666668
mod $mod_set {
667669
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer};
668-
use rustc_back::{LinkerFlavor, PanicStrategy};
670+
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
669671

670672
$(
671673
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
@@ -786,6 +788,16 @@ macro_rules! options {
786788
true
787789
}
788790

791+
fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
792+
match v {
793+
Some("full") => *slot = Some(RelroLevel::Full),
794+
Some("partial") => *slot = Some(RelroLevel::Partial),
795+
Some("off") => *slot = Some(RelroLevel::Off),
796+
_ => return false
797+
}
798+
true
799+
}
800+
789801
fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
790802
match v {
791803
Some("address") => *slote = Some(Sanitizer::Address),
@@ -869,6 +881,8 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options,
869881
"disable the use of the redzone"),
870882
relocation_model: Option<String> = (None, parse_opt_string, [TRACKED],
871883
"choose the relocation model to use (rustc --print relocation-models for details)"),
884+
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
885+
"choose which RELRO level to use"),
872886
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
873887
"choose the code model to use (rustc --print code-models for details)"),
874888
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
@@ -1776,7 +1790,7 @@ mod dep_tracking {
17761790
use super::{Passes, CrateType, OptLevel, DebugInfoLevel,
17771791
OutputTypes, Externs, ErrorOutputType, Sanitizer};
17781792
use syntax::feature_gate::UnstableFeatures;
1779-
use rustc_back::PanicStrategy;
1793+
use rustc_back::{PanicStrategy, RelroLevel};
17801794

17811795
pub trait DepTrackingHash {
17821796
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
@@ -1818,11 +1832,13 @@ mod dep_tracking {
18181832
impl_dep_tracking_hash_via_hash!(Option<String>);
18191833
impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
18201834
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
1835+
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
18211836
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
18221837
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
18231838
impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
18241839
impl_dep_tracking_hash_via_hash!(CrateType);
18251840
impl_dep_tracking_hash_via_hash!(PanicStrategy);
1841+
impl_dep_tracking_hash_via_hash!(RelroLevel);
18261842
impl_dep_tracking_hash_via_hash!(Passes);
18271843
impl_dep_tracking_hash_via_hash!(OptLevel);
18281844
impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
@@ -1904,7 +1920,7 @@ mod tests {
19041920
use std::path::PathBuf;
19051921
use std::rc::Rc;
19061922
use super::{OutputType, OutputTypes, Externs};
1907-
use rustc_back::PanicStrategy;
1923+
use rustc_back::{PanicStrategy, RelroLevel};
19081924
use syntax::symbol::Symbol;
19091925

19101926
fn optgroups() -> getopts::Options {
@@ -2434,6 +2450,10 @@ mod tests {
24342450
opts.cg.relocation_model = Some(String::from("relocation model"));
24352451
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
24362452

2453+
opts = reference.clone();
2454+
opts.cg.relro_level = Some(RelroLevel::Full);
2455+
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2456+
24372457
opts = reference.clone();
24382458
opts.cg.code_model = Some(String::from("code model"));
24392459
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());

src/librustc_back/lib.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,30 @@ impl ToJson for PanicStrategy {
114114
}
115115
}
116116
}
117+
118+
#[derive(Clone, Copy, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
119+
pub enum RelroLevel {
120+
Full,
121+
Partial,
122+
Off,
123+
}
124+
125+
impl RelroLevel {
126+
pub fn desc(&self) -> &str {
127+
match *self {
128+
RelroLevel::Full => "full",
129+
RelroLevel::Partial => "partial",
130+
RelroLevel::Off => "off",
131+
}
132+
}
133+
}
134+
135+
impl ToJson for RelroLevel {
136+
fn to_json(&self) -> Json {
137+
match *self {
138+
RelroLevel::Full => "full".to_json(),
139+
RelroLevel::Partial => "partial".to_json(),
140+
RelroLevel::Off => "off".to_json(),
141+
}
142+
}
143+
}

src/librustc_back/target/bitrig_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::TargetOptions;
11+
use target::{TargetOptions, RelroLevel};
1212
use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
@@ -19,7 +19,7 @@ pub fn opts() -> TargetOptions {
1919
linker_is_gnu: true,
2020
has_rpath: true,
2121
position_independent_executables: true,
22-
full_relro: true,
22+
relro_level: RelroLevel::Full,
2323

2424
.. Default::default()
2525
}

src/librustc_back/target/dragonfly_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use LinkerFlavor;
12-
use target::{LinkArgs, TargetOptions};
12+
use target::{LinkArgs, TargetOptions, RelroLevel};
1313
use std::default::Default;
1414

1515
pub fn opts() -> TargetOptions {
@@ -33,7 +33,7 @@ pub fn opts() -> TargetOptions {
3333
has_rpath: true,
3434
pre_link_args: args,
3535
position_independent_executables: true,
36-
full_relro: true,
36+
relro_level: RelroLevel::Full,
3737
exe_allocation_crate: super::maybe_jemalloc(),
3838
.. Default::default()
3939
}

src/librustc_back/target/freebsd_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use LinkerFlavor;
12-
use target::{LinkArgs, TargetOptions};
12+
use target::{LinkArgs, TargetOptions, RelroLevel};
1313
use std::default::Default;
1414

1515
pub fn opts() -> TargetOptions {
@@ -33,7 +33,7 @@ pub fn opts() -> TargetOptions {
3333
has_rpath: true,
3434
pre_link_args: args,
3535
position_independent_executables: true,
36-
full_relro: true,
36+
relro_level: RelroLevel::Full,
3737
exe_allocation_crate: super::maybe_jemalloc(),
3838
.. Default::default()
3939
}

src/librustc_back/target/haiku_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use target::TargetOptions;
11+
use target::{TargetOptions, RelroLevel};
1212
use std::default::Default;
1313

1414
pub fn opts() -> TargetOptions {
@@ -18,7 +18,7 @@ pub fn opts() -> TargetOptions {
1818
executables: true,
1919
has_rpath: false,
2020
target_family: Some("unix".to_string()),
21-
full_relro: true,
21+
relro_level: RelroLevel::Full,
2222
linker_is_gnu: true,
2323
no_integrated_as: true,
2424
.. Default::default()

src/librustc_back/target/linux_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use LinkerFlavor;
12-
use target::{LinkArgs, TargetOptions};
12+
use target::{LinkArgs, TargetOptions, RelroLevel};
1313
use std::default::Default;
1414

1515
pub fn opts() -> TargetOptions {
@@ -36,7 +36,7 @@ pub fn opts() -> TargetOptions {
3636
has_rpath: true,
3737
pre_link_args: args,
3838
position_independent_executables: true,
39-
full_relro: true,
39+
relro_level: RelroLevel::Full,
4040
exe_allocation_crate: super::maybe_jemalloc(),
4141
has_elf_tls: true,
4242
.. Default::default()

src/librustc_back/target/mod.rs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ use std::default::Default;
5050
use std::io::prelude::*;
5151
use syntax::abi::{Abi, lookup as lookup_abi};
5252

53-
use {LinkerFlavor, PanicStrategy};
53+
use {LinkerFlavor, PanicStrategy, RelroLevel};
5454

5555
mod android_base;
5656
mod apple_base;
@@ -367,9 +367,10 @@ pub struct TargetOptions {
367367
/// the functions in the executable are not randomized and can be used
368368
/// during an exploit of a vulnerability in any code.
369369
pub position_independent_executables: bool,
370-
/// Full RELRO makes the dynamic linker resolve all symbols at startup and marks the GOT
371-
/// read-only before starting the program, preventing overwriting the GOT.
372-
pub full_relro: bool,
370+
/// Either partial, full, or off. Full RELRO makes the dynamic linker
371+
/// resolve all symbols at startup and marks the GOT read-only before
372+
/// starting the program, preventing overwriting the GOT.
373+
pub relro_level: RelroLevel,
373374
/// Format that archives should be emitted in. This affects whether we use
374375
/// LLVM to assemble an archive or fall back to the system linker, and
375376
/// currently only "gnu" is used to fall into LLVM. Unknown strings cause
@@ -457,7 +458,7 @@ impl Default for TargetOptions {
457458
has_rpath: false,
458459
no_default_libraries: true,
459460
position_independent_executables: false,
460-
full_relro: false,
461+
relro_level: RelroLevel::Off,
461462
pre_link_objects_exe: Vec::new(),
462463
pre_link_objects_dll: Vec::new(),
463464
post_link_objects: Vec::new(),
@@ -584,6 +585,20 @@ impl Target {
584585
Some(Ok(()))
585586
})).unwrap_or(Ok(()))
586587
} );
588+
($key_name:ident, RelroLevel) => ( {
589+
let name = (stringify!($key_name)).replace("_", "-");
590+
obj.find(&name[..]).and_then(|o| o.as_string().and_then(|s| {
591+
match s {
592+
"full" => base.options.$key_name = RelroLevel::Full,
593+
"partial" => base.options.$key_name = RelroLevel::Partial,
594+
"off" => base.options.$key_name = RelroLevel::Off,
595+
_ => return Some(Err(format!("'{}' is not a valid value for \
596+
relro-level. Use 'full', 'partial, or 'off'.",
597+
s))),
598+
}
599+
Some(Ok(()))
600+
})).unwrap_or(Ok(()))
601+
} );
587602
($key_name:ident, list) => ( {
588603
let name = (stringify!($key_name)).replace("_", "-");
589604
obj.find(&name[..]).map(|o| o.as_array()
@@ -687,7 +702,7 @@ impl Target {
687702
key!(has_rpath, bool);
688703
key!(no_default_libraries, bool);
689704
key!(position_independent_executables, bool);
690-
key!(full_relro, bool);
705+
try!(key!(relro_level, RelroLevel));
691706
key!(archive_format);
692707
key!(allow_asm, bool);
693708
key!(custom_unwind_resume, bool);
@@ -875,7 +890,7 @@ impl ToJson for Target {
875890
target_option_val!(has_rpath);
876891
target_option_val!(no_default_libraries);
877892
target_option_val!(position_independent_executables);
878-
target_option_val!(full_relro);
893+
target_option_val!(relro_level);
879894
target_option_val!(archive_format);
880895
target_option_val!(allow_asm);
881896
target_option_val!(custom_unwind_resume);

src/librustc_back/target/netbsd_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use LinkerFlavor;
12-
use target::{LinkArgs, TargetOptions};
12+
use target::{LinkArgs, TargetOptions, RelroLevel};
1313
use std::default::Default;
1414

1515
pub fn opts() -> TargetOptions {
@@ -33,7 +33,7 @@ pub fn opts() -> TargetOptions {
3333
has_rpath: true,
3434
pre_link_args: args,
3535
position_independent_executables: true,
36-
full_relro: true,
36+
relro_level: RelroLevel::Full,
3737
.. Default::default()
3838
}
3939
}

src/librustc_back/target/openbsd_base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use LinkerFlavor;
12-
use target::{LinkArgs, TargetOptions};
12+
use target::{LinkArgs, TargetOptions, RelroLevel};
1313
use std::default::Default;
1414

1515
pub fn opts() -> TargetOptions {
@@ -34,7 +34,7 @@ pub fn opts() -> TargetOptions {
3434
is_like_openbsd: true,
3535
pre_link_args: args,
3636
position_independent_executables: true,
37-
full_relro: true,
37+
relro_level: RelroLevel::Full,
3838
.. Default::default()
3939
}
4040
}

0 commit comments

Comments
 (0)