diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/plans/gating.fmf b/plans/gating.fmf new file mode 100644 index 0000000..022ad79 --- /dev/null +++ b/plans/gating.fmf @@ -0,0 +1,9 @@ +summary: Run s390utils gating tests + +discover: + how: fmf + test: + - "^/tests/sanity" + +execute: + how: tmt diff --git a/plans/main.fmf b/plans/main.fmf new file mode 100644 index 0000000..2ce1fa7 --- /dev/null +++ b/plans/main.fmf @@ -0,0 +1,4 @@ +adjust: + - when: arch != s390x + enabled: false + because: The s390utils package is s390x only. diff --git a/tests/sanity/extract-module-sig.pl b/tests/sanity/extract-module-sig.pl new file mode 100755 index 0000000..36a2f59 --- /dev/null +++ b/tests/sanity/extract-module-sig.pl @@ -0,0 +1,138 @@ +#!/usr/bin/env perl +# SPDX-License-Identifier: GPL-2.0 +# +# extract-mod-sig +# +# Reads the module file and writes out some or all of the signature +# section to stdout. Part is the bit to be written and is one of: +# +# -0: The unsigned module, no signature data at all +# -a: All of the signature data, including magic number +# -d: Just the descriptor values as a sequence of numbers +# -n: Just the signer's name +# -k: Just the key ID +# -s: Just the crypto signature or PKCS#7 message +# +use warnings; +use strict; + +die "Format: $0 -[0adnks] module-file >out\n" + if ($#ARGV != 1); + +my $part = $ARGV[0]; +my $modfile = $ARGV[1]; + +my $magic_number = "~Module signature appended~\n"; + +# +# Read the module contents +# +open FD, "<$modfile" || die $modfile; +binmode(FD); +my @st = stat(FD); +die "$modfile" unless (@st); +my $buf = ""; +my $len = sysread(FD, $buf, $st[7]); +die "$modfile" unless (defined($len)); +die "Short read on $modfile\n" unless ($len == $st[7]); +close(FD) || die $modfile; + +print STDERR "Read ", $len, " bytes from module file\n"; + +die "The file is too short to have a sig magic number and descriptor\n" + if ($len < 12 + length($magic_number)); + +# +# Check for the magic number and extract the information block +# +my $p = $len - length($magic_number); +my $raw_magic = substr($buf, $p); + +die "Magic number not found at $len\n" + if ($raw_magic ne $magic_number); +print STDERR "Found magic number at $len\n"; + +$p -= 12; +my $raw_info = substr($buf, $p, 12); + +my @info = unpack("CCCCCxxxN", $raw_info); +my ($algo, $hash, $id_type, $name_len, $kid_len, $sig_len) = @info; + +if ($id_type == 0) { + print STDERR "Found PGP key identifier\n"; +} elsif ($id_type == 1) { + print STDERR "Found X.509 cert identifier\n"; +} elsif ($id_type == 2) { + print STDERR "Found PKCS#7/CMS encapsulation\n"; +} else { + print STDERR "Found unsupported identifier type $id_type\n"; +} + +# +# Extract the three pieces of info data +# +die "Insufficient name+kid+sig data in file\n" + unless ($p >= $name_len + $kid_len + $sig_len); + +$p -= $sig_len; +my $raw_sig = substr($buf, $p, $sig_len); +$p -= $kid_len; +my $raw_kid = substr($buf, $p, $kid_len); +$p -= $name_len; +my $raw_name = substr($buf, $p, $name_len); + +my $module_len = $p; + +if ($sig_len > 0) { + print STDERR "Found $sig_len bytes of signature ["; + my $n = $sig_len > 16 ? 16 : $sig_len; + foreach my $i (unpack("C" x $n, substr($raw_sig, 0, $n))) { + printf STDERR "%02x", $i; + } + print STDERR "]\n"; +} + +if ($kid_len > 0) { + print STDERR "Found $kid_len bytes of key identifier ["; + my $n = $kid_len > 16 ? 16 : $kid_len; + foreach my $i (unpack("C" x $n, substr($raw_kid, 0, $n))) { + printf STDERR "%02x", $i; + } + print STDERR "]\n"; +} + +if ($name_len > 0) { + print STDERR "Found $name_len bytes of signer's name [$raw_name]\n"; +} + +# +# Produce the requested output +# +if ($part eq "-0") { + # The unsigned module, no signature data at all + binmode(STDOUT); + print substr($buf, 0, $module_len); +} elsif ($part eq "-a") { + # All of the signature data, including magic number + binmode(STDOUT); + print substr($buf, $module_len); +} elsif ($part eq "-d") { + # Just the descriptor values as a sequence of numbers + print join(" ", @info), "\n"; +} elsif ($part eq "-n") { + # Just the signer's name + print STDERR "No signer's name for PKCS#7 message type sig\n" + if ($id_type == 2); + binmode(STDOUT); + print $raw_name; +} elsif ($part eq "-k") { + # Just the key identifier + print STDERR "No key ID for PKCS#7 message type sig\n" + if ($id_type == 2); + binmode(STDOUT); + print $raw_kid; +} elsif ($part eq "-s") { + # Just the crypto signature or PKCS#7 message + binmode(STDOUT); + print $raw_sig; +} diff --git a/tests/sanity/main.fmf b/tests/sanity/main.fmf new file mode 100644 index 0000000..5cec1d7 --- /dev/null +++ b/tests/sanity/main.fmf @@ -0,0 +1,16 @@ +summary: sanity +description: | + Basic test for s390utils +contact: Daniel Horak +component: + - s390utils +test: ./runtest.sh +framework: beakerlib +require: + - s390utils-base +duration: 5m +enabled: true +adjust: + - when: arch != s390x + enabled: false + because: This this package is s390x only diff --git a/tests/sanity/runtest.sh b/tests/sanity/runtest.sh new file mode 100755 index 0000000..fb37b64 --- /dev/null +++ b/tests/sanity/runtest.sh @@ -0,0 +1,157 @@ +#!/bin/bash +# vim: dict+=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# runtest.sh of /CoreOS/s390utils/Sanity/smoke-functionality +# Description: Smoke, Sanity and function tests +# Author: Dan HorĂ¡k +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# Copyright (c) 2019 Red Hat, Inc. +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation, either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be +# useful, but WITHOUT ANY WARRANTY; without even the implied +# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +# PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see http://www.gnu.org/licenses/. +# +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Include Beaker environment +. /usr/share/beakerlib/beakerlib.sh || exit 1 + +PACKAGE="s390utils-base" + +EXTRACT="$PWD/extract-module-sig.pl" + +rlJournalStart + rlPhaseStartSetup + rlAssertRpm $PACKAGE + rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" + rlRun "pushd $TmpDir" + rlPhaseEnd + + rlPhaseStartTest "General tests" + rlRun "chccwdev --version" + rlRun "chchp --version" + rlRun "chcpumf --version" + rlRun "chreipl --version" + rlRun "chshut --version" + rlRun "chzcrypt --version" + rlRun "chzdev --version" + rlRun "cio_ignore --version" + rlRun "dasdfmt --version" + rlRun "dasdinfo --version" + rlRun "dasdstat --version" + rlRun "dasdview --version" + rlRun "fdasd --version" + rlRun "hyptop --version" + rlRun "lschp --version" + rlRun "lscpumf --version" + rlRun "lscss --version" + rlRun "lsdasd --version" + rlRun "lsqeth --version" + rlRun "lsluns --version" + rlRun "lsreipl --version" + rlRun "lsscm --version" + rlRun "lsshut --version" + rlRun "lstape --version" + rlRun "lszcrypt --version" + rlRun "lszdev --version" + rlRun "lszfcp --version" + rlRun "qetharp --version" + rlRun "qethconf --version" + rlRun "qethqoat --version" + rlRun "tape390_crypt --version" + rlRun "tape390_display --version" + rlRun "ttyrun --version" + rlRun "tunedasd --version" + rlRun "vmcp --version" + rlRun "vmur --version" + rlRun "zcryptctl --version" + rlRun "zcryptstats --version" + rlRun "zfcpdbf --version" + rlRun "zgetdump --version" + rlRun "zipl --version" + rlRun "znetconf --version" + rlRun "zpcictl --version" + rlRun "zkey --version" + rlRun "zkey-cryptsetup --version" + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.15.1+ - RHEL 8.4+ and RHEL 9" + rlRun "hsci --version" + rlRun "lsstp --version" + + # check for perl-free s390utils-core + rlRun "rpm -q --requires s390utils-core | grep -q perl" 1 "Checking Perl deps in s390utils-core" + + # check kernel installation, must not create /boot/ + if [ $UID -eq 0 ]; then + if rlCheckRpm kernel-core; then + rlRun "dnf -y reinstall kernel-core" 0 "Reinstalling the kernel to verify BLS scripts function" + rlAssertNotExists /boot/`cat /etc/machine-id` + else + rlLog "Skipping kernel reinstallation / BLS test, kernel-core not installed, probably running in a container" + fi + else + rlLog "Skipping kernel reinstallation / BLS test, needs root permissions" + fi + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.16.0+ - RHEL 8.5+ and RHEL 9" + rlRun "lshwc --version" + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.19.0+ - RHEL 8.6+ and RHEL 9" + rlRun "hsavmcore --version" + rlRun "sclpdbf --version" + rlRun "zipl-editenv --version" + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.22.0+ - RHEL 8.7+ and RHEL 9.1+" + rlRun "pai --version" + rlRun "pvattest --version" + rlRun "pvextract-hdr -h" + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.25.0+ - RHEL 8.8+ and RHEL 9.2+" + # no new tools + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.27.0+ - RHEL 8.9+ and RHEL 9.3+" + # no new tools + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.29.0+ - RHEL 8.10+ and RHEL 9.4+" + rlRun "pvsecret --version" + rlPhaseEnd + + rlPhaseStartTest "s390utils 2.33.1+ - RHEL 9.5+ and RHEL 10" + rlRun "chpstat --version" + rlRun "lspai --version" + rlPhaseEnd + + rlPhaseStartTest "Bootloader signature" + # only RHEL has signed bootloader + if rlIsRHEL '>=8'; then + rlRun "$EXTRACT -s /usr/lib/s390-tools/stage3.bin > stage3.bin.sig" 0 "Check bootloader signature" + else + rlLog "Skipping bootloader signature check, not on RHEL" + fi + rlPhaseEnd + + rlPhaseStartCleanup + rlRun "popd" + rlRun "rm -r $TmpDir" 0 "Removing tmp directory" + rlPhaseEnd +rlJournalPrintText +rlJournalEnd