diff --git a/tests/Sanity/static-pie/main.fmf b/tests/Sanity/static-pie/main.fmf new file mode 100644 index 0000000..0ce8081 --- /dev/null +++ b/tests/Sanity/static-pie/main.fmf @@ -0,0 +1,33 @@ +summary: Test ASLR on static linked binaries +require+: + - clang + - gcc + # glibc-static is in CRB + - glibc-static +duration: 5m +tier: 1 +tag: + - CI-Tier-1 +adjust+: + - when: arch != x86_64 + enabled: false + continue: false + because: static-pie is relevant to x86_64 only + + - when: distro < rhel-8 + enabled: false + continue: false + + - when: distro == rhel-8 and distro < rhel-8.7 + enabled: false + continue: false + because: Feature added in Rust 1.60 + + - when: distro == rhel-9 and distro < rhel-9.1 + enabled: false + continue: false + because: Feature added in Rust 1.60 +extra-nitrate: TC#0615613 +extra-summary: /tools/rust/Sanity/static-pie +extra-task: /tools/rust/Sanity/static-pie +id: 8849f11b-074d-40d0-88e9-68e288f15495 diff --git a/tests/Sanity/static-pie/runtest.sh b/tests/Sanity/static-pie/runtest.sh new file mode 100755 index 0000000..65753f3 --- /dev/null +++ b/tests/Sanity/static-pie/runtest.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGE="$(rpm -qf $(which rustc))" +PACKAGES=${PACKAGES:-$PACKAGE} + +# This test is extracted from rust's testsuite: +# https://github.com/rust-lang/rust/tree/23405bb123681399c912552fa1c09264c0d4930d/tests/run-make/static-pie +COMPILERS=(clang gcc) + +rlJournalStart + rlPhaseStartSetup + rlAssertRpm --all + rlRun "tmp=\$(mktemp -d)" 0 "Create tmp directory" + rlRun "cp test-aslr.rs $tmp" + rlRun "pushd $tmp" + rlRun "set -o pipefail" + rlPhaseEnd + +for compiler in "${COMPILERS[@]}"; do + rlPhaseStartTest "test with $compiler" + rlRun "rustc -Clinker=$compiler -Clinker-flavor=gcc --target $(uname -m)-unknown-linux-gnu -C target-feature=+crt-static test-aslr.rs" + rlRun "readelf -l test-aslr > headers.out" + rlAssertNotGrep INTERP headers.out + rlAssertGrep DYNAMIC headers.out + rlRun "./test-aslr --test-aslr" + rlPhaseEnd +done + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r $tmp" 0 "Remove tmp directory" + rlPhaseEnd +rlJournalEnd diff --git a/tests/Sanity/static-pie/test-aslr.rs b/tests/Sanity/static-pie/test-aslr.rs new file mode 100644 index 0000000..96b17af --- /dev/null +++ b/tests/Sanity/static-pie/test-aslr.rs @@ -0,0 +1,43 @@ +const NUM_RUNS: usize = 10; + +fn run_self(exe: &str) -> usize { + use std::process::Command; + let mut set = std::collections::HashSet::new(); + + let mut cmd = Command::new(exe); + cmd.arg("--report"); + (0..NUM_RUNS).for_each(|_| { + set.insert(cmd.output().expect("failed to execute process").stdout); + }); + set.len() +} + +fn main() { + let mut args = std::env::args(); + let arg0 = args.next().unwrap(); + match args.next() { + Some(s) if s.eq("--report") => { + println!("main = {:#?}", &main as *const _); + } + Some(s) if s.eq("--test-no-aslr") => { + let cnt = run_self(&arg0); + if cnt != 1 { + eprintln!("FAIL: {} most likely ASLR", arg0); + std::process::exit(1); + } + println!("PASS: {} does no ASLR", arg0); + } + Some(s) if s.eq("--test-aslr") => { + let cnt = run_self(&arg0); + if cnt == 1 { + eprintln!("FAIL: {} most likely no ASLR", arg0); + std::process::exit(1); + } + println!("PASS: {} does ASLR", arg0); + } + Some(_) | None => { + println!("Usage: {} --test-no-aslr | --test-aslr", arg0); + std::process::exit(1); + } + } +}