diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:13 +0000 |
commit | 218caa410aa38c29984be31a5229b9fa717560ee (patch) | |
tree | c54bd55eeb6e4c508940a30e94c0032fbd45d677 /src/test/ui/abi/stack-protector.rs | |
parent | Releasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip |
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/abi/stack-protector.rs')
-rw-r--r-- | src/test/ui/abi/stack-protector.rs | 99 |
1 files changed, 0 insertions, 99 deletions
diff --git a/src/test/ui/abi/stack-protector.rs b/src/test/ui/abi/stack-protector.rs deleted file mode 100644 index 24bd2e219..000000000 --- a/src/test/ui/abi/stack-protector.rs +++ /dev/null @@ -1,99 +0,0 @@ -// run-pass -// only-x86_64-unknown-linux-gnu -// revisions: ssp no-ssp -// [ssp] compile-flags: -Z stack-protector=all -// compile-flags: -C opt-level=2 -// compile-flags: -g - -use std::env; -use std::process::{Command, ExitStatus}; - -fn main() { - if env::args().len() == 1 { - // The test is initially run without arguments. Start the process again, - // this time *with* an argument; in this configuration, the test program - // will deliberately smash the stack. - let cur_argv0 = env::current_exe().unwrap(); - let mut child = Command::new(&cur_argv0); - child.arg("stacksmash"); - - if cfg!(ssp) { - assert_stack_smash_prevented(&mut child); - } else { - assert_stack_smashed(&mut child); - } - } else { - vulnerable_function(); - // If we return here the test is broken: it should either have called - // malicious_code() which terminates the process, or be caught by the - // stack check which also terminates the process. - panic!("TEST BUG: stack smash unsuccessful"); - } -} - -// Avoid inlining to make sure the return address is pushed to stack. -#[inline(never)] -fn vulnerable_function() { - let mut x = 5usize; - let stackaddr = &mut x as *mut usize; - let bad_code_ptr = malicious_code as usize; - // Overwrite the on-stack return address with the address of `malicious_code()`, - // thereby jumping to that function when returning from `vulnerable_function()`. - unsafe { fill(stackaddr, bad_code_ptr, 20); } -} - -// Use an uninlined function with its own stack frame to make sure that we don't -// clobber e.g. the counter or address local variable. -#[inline(never)] -unsafe fn fill(addr: *mut usize, val: usize, count: usize) { - let mut addr = addr; - for _ in 0..count { - *addr = val; - addr = addr.add(1); - } -} - -// We jump to malicious_code() having wreaked havoc with the previous stack -// frame and not setting up a new one. This function is therefore constrained, -// e.g. both println!() and std::process::exit() segfaults if called. We -// therefore keep the amount of work to a minimum by calling POSIX functions -// directly. -// The function is un-inlined just to make it possible to set a breakpoint here. -#[inline(never)] -fn malicious_code() { - let msg = [112u8, 119u8, 110u8, 101u8, 100u8, 33u8, 0u8]; // "pwned!\0" ascii - unsafe { - write(1, &msg as *const u8, msg.len()); - _exit(0); - } -} -extern "C" { - fn write(fd: i32, buf: *const u8, count: usize) -> isize; - fn _exit(status: i32) -> !; -} - - -fn assert_stack_smash_prevented(cmd: &mut Command) { - let (status, stdout, stderr) = run(cmd); - assert!(!status.success()); - assert!(stdout.is_empty()); - assert!(stderr.contains("stack smashing detected")); -} - -fn assert_stack_smashed(cmd: &mut Command) { - let (status, stdout, stderr) = run(cmd); - assert!(status.success()); - assert!(stdout.contains("pwned!")); - assert!(stderr.is_empty()); -} - - -fn run(cmd: &mut Command) -> (ExitStatus, String, String) { - let output = cmd.output().unwrap(); - let stdout = String::from_utf8_lossy(&output.stdout); - let stderr = String::from_utf8_lossy(&output.stderr); - println!("status: {}", output.status); - println!("stdout: {}", stdout); - println!("stderr: {}", stderr); - (output.status, stdout.to_string(), stderr.to_string()) -} |