Skip to content

Commit

Permalink
linker: Use data execution prevention options by default when linker …
Browse files Browse the repository at this point in the history
…supports them
  • Loading branch information
petrochenkov committed Mar 28, 2021
1 parent 4a20eb6 commit cc5392e
Show file tree
Hide file tree
Showing 11 changed files with 23 additions and 73 deletions.
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Expand Up @@ -1651,6 +1651,10 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
cmd.add_eh_frame_header();
}

// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
// Make the binary compatible with data execution prevention schemes.
cmd.add_no_exec();

// NO-OPT-OUT, OBJECT-FILES-NO
// Avoid linking to dynamic libraries unless they satisfy some undefined symbols
// at the point at which they are specified on the command line.
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Expand Up @@ -130,6 +130,7 @@ pub trait Linker {
fn group_end(&mut self);
fn linker_plugin_lto(&mut self);
fn add_eh_frame_header(&mut self) {}
fn add_no_exec(&mut self) {}
fn add_as_needed(&mut self) {}
fn finalize(&mut self);
}
Expand Down Expand Up @@ -643,6 +644,14 @@ impl<'a> Linker for GccLinker<'a> {
self.linker_arg("--eh-frame-hdr");
}

fn add_no_exec(&mut self) {
if self.sess.target.is_like_windows {
self.linker_arg("--nxcompat");
} else if self.sess.target.linker_is_gnu {
self.linker_arg("-znoexecstack");
}
}

fn add_as_needed(&mut self) {
if self.sess.target.linker_is_gnu {
self.linker_arg("--as-needed");
Expand Down Expand Up @@ -885,6 +894,10 @@ impl<'a> Linker for MsvcLinker<'a> {
fn linker_plugin_lto(&mut self) {
// Do nothing
}

fn add_no_exec(&mut self) {
self.cmd.arg("/NXCOMPAT");
}
}

pub struct EmLinker<'a> {
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_target/src/spec/dragonfly_base.rs
@@ -1,23 +1,13 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use crate::spec::{RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
args.insert(
LinkerFlavor::Gcc,
vec![
// Always enable NX protection when it is available
"-Wl,-z,noexecstack".to_string(),
],
);

TargetOptions {
os: "dragonfly".to_string(),
dynamic_linking: true,
executables: true,
os_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
pre_link_args: args,
position_independent_executables: true,
relro_level: RelroLevel::Full,
dwarf_version: Some(2),
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_target/src/spec/freebsd_base.rs
@@ -1,23 +1,13 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use crate::spec::{RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
args.insert(
LinkerFlavor::Gcc,
vec![
// Always enable NX protection when it is available
"-Wl,-z,noexecstack".to_string(),
],
);

TargetOptions {
os: "freebsd".to_string(),
dynamic_linking: true,
executables: true,
os_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
pre_link_args: args,
position_independent_executables: true,
eliminate_frame_pointer: false, // FIXME 43575
relro_level: RelroLevel::Full,
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_target/src/spec/linux_base.rs
@@ -1,23 +1,13 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use crate::spec::{RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
args.insert(
LinkerFlavor::Gcc,
vec![
// Always enable NX protection when it is available
"-Wl,-z,noexecstack".to_string(),
],
);

TargetOptions {
os: "linux".to_string(),
dynamic_linking: true,
executables: true,
os_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
pre_link_args: args,
position_independent_executables: true,
relro_level: RelroLevel::Full,
has_elf_tls: true,
Expand Down
8 changes: 1 addition & 7 deletions compiler/rustc_target/src/spec/linux_kernel_base.rs
@@ -1,11 +1,6 @@
use crate::spec::{
LinkArgs, LinkerFlavor, PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions,
};
use crate::spec::{PanicStrategy, RelocModel, RelroLevel, StackProbeType, TargetOptions};

pub fn opts() -> TargetOptions {
let mut pre_link_args = LinkArgs::new();
pre_link_args.insert(LinkerFlavor::Gcc, vec!["-Wl,-z,noexecstack".to_string()]);

TargetOptions {
env: "gnu".to_string(),
disable_redzone: true,
Expand All @@ -17,7 +12,6 @@ pub fn opts() -> TargetOptions {
needs_plt: true,
relro_level: RelroLevel::Full,
relocation_model: RelocModel::Static,
pre_link_args,

..Default::default()
}
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_target/src/spec/msvc_base.rs
Expand Up @@ -5,13 +5,6 @@ pub fn opts() -> TargetOptions {
// Suppress the verbose logo and authorship debugging output, which would needlessly
// clog any log files.
"/NOLOGO".to_string(),
// Tell the compiler that non-code sections can be marked as non-executable,
// including stack pages.
// UEFI is fully compatible to non-executable data pages.
// In fact, firmware might enforce this, so we better let the linker know about this,
// so it will fail if the compiler ever tries placing code on the stack
// (e.g., trampoline constructs and alike).
"/NXCOMPAT".to_string(),
];
let mut pre_link_args = LinkArgs::new();
pre_link_args.insert(LinkerFlavor::Msvc, pre_link_args_msvc.clone());
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_target/src/spec/openbsd_base.rs
@@ -1,15 +1,6 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use crate::spec::{RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
args.insert(
LinkerFlavor::Gcc,
vec![
// Always enable NX protection when it is available
"-Wl,-z,noexecstack".to_string(),
],
);

TargetOptions {
os: "openbsd".to_string(),
dynamic_linking: true,
Expand All @@ -18,7 +9,6 @@ pub fn opts() -> TargetOptions {
linker_is_gnu: true,
has_rpath: true,
abi_return_struct_as_int: true,
pre_link_args: args,
position_independent_executables: true,
eliminate_frame_pointer: false, // FIXME 43575
relro_level: RelroLevel::Full,
Expand Down
12 changes: 1 addition & 11 deletions compiler/rustc_target/src/spec/redox_base.rs
@@ -1,15 +1,6 @@
use crate::spec::{LinkArgs, LinkerFlavor, RelroLevel, TargetOptions};
use crate::spec::{RelroLevel, TargetOptions};

pub fn opts() -> TargetOptions {
let mut args = LinkArgs::new();
args.insert(
LinkerFlavor::Gcc,
vec![
// Always enable NX protection when it is available
"-Wl,-z,noexecstack".to_string(),
],
);

TargetOptions {
os: "redox".to_string(),
env: "relibc".to_string(),
Expand All @@ -18,7 +9,6 @@ pub fn opts() -> TargetOptions {
os_family: Some("unix".to_string()),
linker_is_gnu: true,
has_rpath: true,
pre_link_args: args,
position_independent_executables: true,
relro_level: RelroLevel::Full,
has_elf_tls: true,
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_target/src/spec/windows_gnu_base.rs
Expand Up @@ -9,8 +9,6 @@ pub fn opts() -> TargetOptions {
// Tell GCC to avoid linker plugins, because we are not bundling
// them with Windows installer, and Rust does its own LTO anyways.
"-fno-use-linker-plugin".to_string(),
// Always enable DEP (NX bit) when it is available
"-Wl,--nxcompat".to_string(),
// Enable ASLR
"-Wl,--dynamicbase".to_string(),
// ASLR will rebase it anyway so leaving that option enabled only leads to confusion
Expand Down
2 changes: 0 additions & 2 deletions compiler/rustc_target/src/spec/x86_64_fortanix_unknown_sgx.rs
Expand Up @@ -4,8 +4,6 @@ use super::{LinkerFlavor, LldFlavor, PanicStrategy, Target, TargetOptions};

pub fn target() -> Target {
const PRE_LINK_ARGS: &[&str] = &[
"-z",
"noexecstack",
"-e",
"elf_entry",
"-Bstatic",
Expand Down

0 comments on commit cc5392e

Please sign in to comment.