Test some aspects of -fhardened

Mostly focused in UX and integration.

Note: Fails at the moment, see
      https://bugzilla.redhat.com/show_bug.cgi?id=2273610
      for details.
This commit is contained in:
Václav Kadlčík 2024-04-05 13:53:37 +02:00
commit 8a4e19eaff
6 changed files with 188 additions and 0 deletions

View file

@ -0,0 +1,5 @@
#include <stdio.h>
int hello() {
return printf("hello world\n");
}

View file

@ -0,0 +1,6 @@
/^ -fhardened$/ {
do {
print;
getline;
} while ($0 !~ " -f")
}

View file

@ -0,0 +1,6 @@
extern int hello();
int main(void) {
hello();
return 0;
}

View file

@ -0,0 +1,8 @@
#include <iostream>
using namespace std;
int main(void) {
cout << "hello world" << endl;
return 0;
}

View file

@ -0,0 +1,36 @@
summary: Test -fhardened
contact: Vaclav Kadlcik <vkadlcik@redhat.com>
component:
- gcc
enabled: true
test: ${WITH_SCL:-bash} ./runtest.sh
framework: beakerlib
require+:
- gcc
- gcc-c++
- annobin-annocheck
recommend:
- annobin-plugin-gcc
- annobin
duration: 30m
adjust:
- enabled: false
when: arch != x86_64
continue: false
because: Implemented on x86_64 only
- enabled: false
when: distro < fedora-40
continue: false
because: GCC 14+ needed
- enabled: false
when: collection is not defined and distro < rhel-10
continue: false
because: GCC 14+ needed
- enabled: false
when: collection is defined and collection < gcc-toolset-14
continue: false
because: GCC 14+ needed
# TODO extra-nitrate: TC#
extra-summary: /tools/gcc/Sanity/fhardened
extra-task: /tools/gcc/Sanity/fhardened
# TODO id:

127
tests/Sanity/fhardened/runtest.sh Executable file
View file

@ -0,0 +1,127 @@
#!/usr/bin/env bash
# Load libraries
. /usr/share/beakerlib/beakerlib.sh || exit 1
. "${0%/*}"/../../lib/common.sh || exit 1
GCC="${GCC:-$(type -P gcc)}"
GCC_RPM_NAME=$(rpm --qf '%{name}' -qf "$GCC")
PACKAGES="$GCC_RPM_NAME ${GCC_RPM_NAME}-c++"
rlJournalStart
rlPhaseStartSetup
rlLogInfo "PACKAGES=$PACKAGES"
rlLogInfo "COLLECTIONS=$COLLECTIONS"
rlLogInfo "GCC=$GCC"
rlLogInfo "SKIP_COLLECTION_METAPACKAGE_CHECK=$SKIP_COLLECTION_METAPACKAGE_CHECK"
# We optionally need to skip checking for the presence of the metapackage
# because that would pull in all the dependent toolset subrpms. We do not
# always want that, especially in CI.
_COLLECTIONS="$COLLECTIONS"
if ! test -z "$SKIP_COLLECTION_METAPACKAGE_CHECK"; then
for c in $SKIP_COLLECTION_METAPACKAGE_CHECK; do
rlLogInfo "ignoring metapackage check for collection $c"
COLLECTIONS=$(shopt -s extglob && echo "${COLLECTIONS//$c/}"); export COLLECTIONS
done
fi
rlLogInfo "(without skipped) COLLECTIONS=$COLLECTIONS"
rlAssertRpm --all
export COLLECTIONS="$_COLLECTIONS"
rlRun "TmpDir=\$(mktemp --directory)"
# shellcheck disable=SC2154
rlRun "cp files/* $TmpDir"
rlRun "pushd $TmpDir"
rlPhaseEnd
rlPhaseStartTest DOCUMENTATION
rlRun 'MANWIDTH=4096 man gcc >man.out'
rlRun 'awk -f just_the-fhardened_option.awk <man.out >man-fhardened.out'
rlRun 'gcc --help=hardened >help_hardened.out'
rlAssertGrep ' -Whardened$' man.out
rlAssertGrep ' -fhardened$' man.out
# Later, this may need to be split into specifics per "gcc -dumpversion"
for i in \
-D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS \
-ftrivial-auto-var-init=zero -fPIE -pie \
'-Wl,[^ ]*-z,relro' '-Wl,[^ ]*-z,now' \
-fstack-protector-strong -fstack-clash-protection \
-fcf-protection=full
do
rlAssertGrep " ${i}\W" man-fhardened.out -Pzq
rlAssertGrep " ${i}\W" help_hardened.out -Pzq
done
rlPhaseEnd
rlPhaseStartTest SHOULD_NOT_CONFLICT
# Let's check at least some most often used switches
for i in \
-fasynchronous-unwind-tables -fexceptions -ffat-lto-objects \
-fno-omit-frame-pointer -mno-omit-leaf-frame-pointer \
-g -grecord-gcc-switches \
-m64 -march=native -march=x86-64 -march=x86-64-v2 \
-mtune=generic -mtune=native
do
rlRun "gcc -fhardened -O2 $i -o c_hello.exe main.c hello.c &>outerr"
rlAssertNotDiffer outerr /dev/null
done
for i in -O -O1 -O2 -O3 -Os -Ofast -Og -Oz; do
rlRun "gcc -fhardened $i -o c_hello.exe main.c hello.c &>outerr"
rlAssertNotDiffer outerr /dev/null
done
rlPhaseEnd
rlPhaseStartTest NOTICED_BY_ANNOBIN
# When used, built-by should see it
rlRun 'g++ -g -fplugin=annobin -fhardened -O2 -o cxx_hello.exe main.cc'
rlRun 'annocheck --disable-hardened --enable-built-by cxx_hello.exe >annocheck.out'
rlAssertGrep 'built by.*-fhardened' annocheck.out
# And the other way around
rlRun 'gcc -g -fplugin=annobin -o c_hello.exe main.c hello.c'
rlRun 'annocheck --disable-hardened --enable-built-by c_hello.exe >annocheck.out'
rlAssertNotGrep 'fhardened' annocheck.out
rlPhaseEnd
rlPhaseStartTest NOT_ENABLED_BY_DEFAULT
rlRun 'gcc -O2 -o c_hello.exe main.c hello.c &>verbose'
rlAssertNotGrep fhardened verbose
rlPhaseEnd
rlPhaseStartTest WARN_WHEN_LOWERED
# -Whardened should be enabled by default
rlRun 'g++ -fhardened -fstack-protector -O -o cxx_hello.exe main.cc 2>err'
rlAssertGrep '-fstack-protector-strong.*not enabled.*-Whardened' err
# Lowering some of the hardening components should produce a warning
for i in '' -all -explicit; do
rlRun "g++ -fhardened -fstack-protector${i} -Whardened -O2 -o cxx_hello.exe main.cc 2>err"
rlAssertGrep '-fstack-protector-strong.*not enabled.*-Whardened' err
done
for i in branch return check none; do
rlRun "g++ -fhardened -fcf-protection=$i -Whardened -O3 -o cxx_hello.exe main.cc 2>err"
rlAssertGrep '-fcf-protection=full.*not enabled.*-Whardened' err
done
for i in '' -all -explicit; do
for j in branch return check none; do
rlRun "g++ -fhardened -fstack-protector${i} -fcf-protection=$j -Whardened -O3 -o cxx_hello.exe main.cc 2>err"
rlAssertGrep '-fstack-protector-strong.*not enabled.*-Whardened' err
rlAssertGrep '-fcf-protection=full.*not enabled.*-Whardened' err
done
done
# _FORTIFY_SOURCE is not enabled without optimization,
# therefore a warning should come here as well
rlRun 'gcc -fhardened -o c_hello.exe main.c hello.c 2>err'
rlAssertGrep '_FORTIFY_SOURCE.*not enabled.*-Whardened' err
rlPhaseEnd
rlPhaseStartCleanup
rlRun popd
rlRun "rm -r $TmpDir"
rlPhaseEnd
rlJournalPrintText
rlJournalEnd