Skip to content

Commit 79beddf

Browse files
authored
propagate stack protector to Linux C compilers (#1550)
1 parent fafa9fc commit 79beddf

File tree

2 files changed

+55
-3
lines changed

2 files changed

+55
-3
lines changed

src/flags.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub(crate) struct RustcCodegenFlags<'a> {
1919
no_redzone: Option<bool>,
2020
soft_float: Option<bool>,
2121
dwarf_version: Option<u32>,
22+
stack_protector: Option<&'a str>,
2223
}
2324

2425
impl<'this> RustcCodegenFlags<'this> {
@@ -161,6 +162,12 @@ impl<'this> RustcCodegenFlags<'this> {
161162
"-Zdwarf-version must have a value",
162163
))?);
163164
}
165+
// https://github.com/rust-lang/rust/issues/114903
166+
// FIXME: Drop the -Z variant and update the doc link once the option is stabilized
167+
"-Zstack-protector" | "-Cstack-protector" => {
168+
self.stack_protector =
169+
Some(flag_ok_or(value, "-Zstack-protector must have a value")?);
170+
}
164171
_ => {}
165172
}
166173
Ok(())
@@ -267,6 +274,23 @@ impl<'this> RustcCodegenFlags<'this> {
267274
if let Some(value) = self.dwarf_version {
268275
push_if_supported(format!("-gdwarf-{value}").into());
269276
}
277+
// https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fstack-protector
278+
// https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#index-fstack-protector
279+
if let Some(value) = self.stack_protector {
280+
// don't need to propagate stack-protector on MSVC since /GS is already the default
281+
// https://learn.microsoft.com/en-us/cpp/build/reference/gs-buffer-security-check?view=msvc-170
282+
//
283+
// Do NOT `stack-protector=none` since it weakens security for C code,
284+
// and `-Zstack-protector=basic` is deprecated and will be removed soon.
285+
let cc_flag = match value {
286+
"strong" => Some("-fstack-protector-strong"),
287+
"all" => Some("-fstack-protector-all"),
288+
_ => None,
289+
};
290+
if let Some(cc_flag) = cc_flag {
291+
push_if_supported(cc_flag.into());
292+
}
293+
}
270294
}
271295

272296
// Compiler-exclusive flags
@@ -379,6 +403,16 @@ mod tests {
379403
check("-L\u{1f}-Clto", &expected);
380404
}
381405

406+
#[test]
407+
fn stack_protector() {
408+
let expected = RustcCodegenFlags {
409+
stack_protector: Some("strong"),
410+
..RustcCodegenFlags::default()
411+
};
412+
check("-Zstack-protector=strong", &expected);
413+
check("-Cstack-protector=strong", &expected);
414+
}
415+
382416
#[test]
383417
fn three_valid_prefixes() {
384418
let expected = RustcCodegenFlags {
@@ -408,6 +442,7 @@ mod tests {
408442
"-Csoft-float=yes",
409443
"-Zbranch-protection=bti,pac-ret,leaf",
410444
"-Zdwarf-version=5",
445+
"-Zstack-protector=strong",
411446
// Set flags we don't recognise but rustc supports next
412447
// rustc flags
413448
"--cfg",
@@ -515,6 +550,7 @@ mod tests {
515550
soft_float: Some(true),
516551
branch_protection: Some("bti,pac-ret,leaf"),
517552
dwarf_version: Some(5),
553+
stack_protector: Some("strong"),
518554
},
519555
);
520556
}

tests/rustflags.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,34 @@ fn inherits_rustflags() {
1414
test.cmd(0)
1515
.must_not_have("-fno-omit-frame-pointer")
1616
.must_not_have("-mcmodel=small")
17-
.must_not_have("-msoft-float");
17+
.must_not_have("-msoft-float")
18+
.must_not_have("-fstack-protector-strong");
1819

1920
// Correctly inherits flags from rustc
2021
std::env::set_var(
2122
"CARGO_ENCODED_RUSTFLAGS",
22-
"-Cforce-frame-pointers=true\u{1f}-Ccode-model=small\u{1f}-Csoft-float\u{1f}-Cdwarf-version=5",
23+
"-Cforce-frame-pointers=true\u{1f}-Ccode-model=small\u{1f}-Csoft-float\u{1f}-Cdwarf-version=5\u{1f}-Zstack-protector=strong",
2324
);
2425
let test = Test::gnu();
2526
test.gcc().file("foo.c").compile("foo");
2627
test.cmd(0)
2728
.must_have("-fno-omit-frame-pointer")
2829
.must_have("-mcmodel=small")
2930
.must_have("-msoft-float")
30-
.must_have("-gdwarf-5");
31+
.must_have("-gdwarf-5")
32+
.must_have("-fstack-protector-strong");
33+
34+
// Do *not* propagate -Zstack-protector=none
35+
std::env::set_var(
36+
"CARGO_ENCODED_RUSTFLAGS",
37+
"-Cforce-frame-pointers=true\u{1f}-Ccode-model=small\u{1f}-Csoft-float\u{1f}-Cdwarf-version=5\u{1f}-Zstack-protector=none",
38+
);
39+
let test = Test::gnu();
40+
test.gcc().file("foo.c").compile("foo");
41+
test.cmd(0)
42+
.must_have("-fno-omit-frame-pointer")
43+
.must_have("-mcmodel=small")
44+
.must_have("-msoft-float")
45+
.must_have("-gdwarf-5")
46+
.must_not_have("-fno-stack-protector");
3147
}

0 commit comments

Comments
 (0)