Skip to content

linker: Use data execution prevention options by default when linker supports them #83619

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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