UBUNTU: [Packaging] Move checker scripts to debian/scripts/checks
Tidy up the scripts directory and move all checker scripts to a new subdirectory. Signed-off-by: Juerg Haefliger <juerg.haefliger@canonical.com> Signed-off-by: Andrea Righi <andrea.righi@canonical.com>
This commit is contained in:
committed by
Paolo Pisati
parent
f5b739c7d5
commit
78021e8a72
+139
@@ -0,0 +1,139 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Check ABI changes
|
||||
#
|
||||
# To skip the ABI checks, add a file
|
||||
# debian.<foo>/abi/<arch>/ignore.abi
|
||||
# or
|
||||
# debian.<foo>/abi/<arch>/<flavor>.ignore.abi
|
||||
#
|
||||
# To ignore a list of symbols, add the symbols to the file
|
||||
# debian.<foo>/abi/abi.ignore
|
||||
#
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
def decode_symline(line):
|
||||
comps = re.sub(r'\s+', ' ', line).split(' ')
|
||||
if comps[0].startswith('EXPORT_SYMBOL'):
|
||||
stype, sloc, shash, sname = comps
|
||||
else:
|
||||
stype, shash, sname, sloc = comps[1:]
|
||||
return sname, {'type': stype, 'loc': sloc, 'hash': shash}
|
||||
|
||||
if len(sys.argv) < 4 or len(sys.argv) > 5:
|
||||
print('Usage: abi-check <flavor> <prev_abidir> <abidir> [<skipabi>]')
|
||||
sys.exit(2)
|
||||
|
||||
flavor, prev_abidir, abidir = sys.argv[1:4] # pylint: disable=W0632
|
||||
if len(sys.argv) > 4:
|
||||
skipabi = sys.argv[4].lower() in ['1', 'true', 'yes']
|
||||
else:
|
||||
skipabi = False
|
||||
|
||||
print('II: Checking ABI for {}...'.format(flavor), end='')
|
||||
|
||||
if ((os.path.exists('{}/ignore.abi'.format(prev_abidir)) or
|
||||
os.path.exists('{}/{}.ignore.abi'.format(prev_abidir, flavor)))):
|
||||
print('WW: Explicitly ignoring ABI')
|
||||
print('II: Done')
|
||||
sys.exit(0)
|
||||
|
||||
curr_abi = '{}/{}'.format(abidir, flavor)
|
||||
prev_abi = '{}/{}'.format(prev_abidir, flavor)
|
||||
if not os.path.exists(curr_abi) or not os.path.exists(prev_abi):
|
||||
print('II: Previous or current ABI file missing!')
|
||||
print(' {}'.format(curr_abi))
|
||||
print(' {}'.format(prev_abi))
|
||||
if skipabi:
|
||||
print('WW: Explicitly asked to ignore failures')
|
||||
print('II: Done')
|
||||
sys.exit(0)
|
||||
print('EE: Missing ABI file')
|
||||
sys.exit(1)
|
||||
|
||||
print()
|
||||
|
||||
symbols = {}
|
||||
symbols_ignore = {}
|
||||
|
||||
# See if we have any ignores
|
||||
print(' Reading symbols to ignore...', end='')
|
||||
ignore = 0
|
||||
prev_abi_ignore = '{}/../abi.ignore'.format(prev_abidir)
|
||||
if os.path.exists(prev_abi_ignore):
|
||||
with open(prev_abi_ignore) as fh:
|
||||
for sym in fh:
|
||||
sym = sym.strip()
|
||||
if sym.startswith('#'):
|
||||
continue
|
||||
symbols_ignore[sym] = 1
|
||||
ignore += 1
|
||||
print('read {} symbols.'.format(ignore))
|
||||
|
||||
# Read new symbols first
|
||||
print(' Reading new symbols...', end='')
|
||||
new_count = 0
|
||||
with open('{}/{}'.format(abidir, flavor)) as fh:
|
||||
for line in fh:
|
||||
sym, vals = decode_symline(line.strip())
|
||||
symbols[sym] = vals
|
||||
new_count += 1
|
||||
print('read {} symbols.'.format(new_count))
|
||||
|
||||
# Now the old symbols
|
||||
print(' Reading old symbols...', end='')
|
||||
old_count = 0
|
||||
with open('{}/{}'.format(prev_abidir, flavor)) as fh:
|
||||
for line in fh:
|
||||
sym, vals = decode_symline(line.strip())
|
||||
if sym not in symbols:
|
||||
symbols[sym] = {}
|
||||
symbols[sym]['old'] = vals
|
||||
old_count += 1
|
||||
print('read {} symbols.'.format(old_count))
|
||||
|
||||
print('II: Checking for ABI changes...')
|
||||
changed_loc = 0
|
||||
changed_type = 0
|
||||
error = False
|
||||
for sym, vals in symbols.items():
|
||||
# Ignore new symbols
|
||||
if 'old' not in vals:
|
||||
continue
|
||||
|
||||
# Changes in location don't hurt us, but log it anyway
|
||||
if vals['loc'] != vals['old']['loc']:
|
||||
changed_loc += 1
|
||||
print(' MOVE : {:40} : {} => {}'.format(sym, vals['old']['loc'],
|
||||
vals['loc']))
|
||||
|
||||
# Changes from GPL to non-GPL are bad
|
||||
if ((vals['old']['type'] == 'EXPORT_SYMBOL_GPL' and
|
||||
vals['type'] != 'EXPORT_SYMBOL_GPL')):
|
||||
changed_type += 1
|
||||
if sym in symbols_ignore or vals['loc'] in symbols_ignore:
|
||||
ignored = ' (ignore)'
|
||||
else:
|
||||
ignored = ''
|
||||
error = True
|
||||
print(' TYPE : {:40} : {} => {}{}'.format(sym, vals['old']['type'],
|
||||
vals['type'], ignored))
|
||||
|
||||
if changed_loc > 0:
|
||||
print('II: {} symbols changed location'.format(changed_loc))
|
||||
|
||||
if changed_type > 0:
|
||||
print('II: {} symbols changed export type'.format(changed_type))
|
||||
|
||||
if error:
|
||||
if skipabi:
|
||||
print('WW: Explicitly asked to ignore failures')
|
||||
else:
|
||||
print('EE: Symbol types changed')
|
||||
sys.exit(1)
|
||||
|
||||
print('II: Done')
|
||||
sys.exit(0)
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/perl
|
||||
#
|
||||
# check-config -- check the current config for issues
|
||||
#
|
||||
use strict;
|
||||
use File::Basename;
|
||||
use File::Spec;
|
||||
|
||||
my $P = 'check-config';
|
||||
|
||||
my $test = -1;
|
||||
if ($ARGV[0] eq '--test') {
|
||||
$test = $ARGV[1] + 0;
|
||||
} elsif ($#ARGV != 5) {
|
||||
die "Usage: $P <config> <arch> <flavour> <commonconfig> <warn-only> <enforce-all>\n";
|
||||
}
|
||||
|
||||
my ($configfile, $arch, $flavour, $commonconfig, $warn_only, $enforce_all) = @ARGV;
|
||||
|
||||
my %values = ();
|
||||
|
||||
# If we are in overridden then still perform the checks and emit the messages
|
||||
# but do not return failure. Those items marked FATAL will alway trigger
|
||||
# failure.
|
||||
my $fail_exit = 1;
|
||||
$fail_exit = 0 if ($warn_only eq 'true' || $warn_only eq '1');
|
||||
my $exit_val = 0;
|
||||
|
||||
$enforce_all = 0 if $enforce_all eq "no" or $enforce_all eq "false";
|
||||
|
||||
# Load up the current configuration values -- FATAL if this fails
|
||||
print "$P: $configfile: loading config\n";
|
||||
open(CONFIG, "<$configfile") || die "$P: $configfile: open failed -- $! -- aborting\n";
|
||||
while (<CONFIG>) {
|
||||
# Pull out values.
|
||||
/^#*\s*(CONFIG_\w+)[\s=](.*)$/ or next;
|
||||
if ($2 eq 'is not set') {
|
||||
$values{$1} = 'n';
|
||||
} else {
|
||||
$values{$1} = $2;
|
||||
}
|
||||
}
|
||||
close(CONFIG);
|
||||
|
||||
sub read_annotations {
|
||||
my ($filename) = @_;
|
||||
my %annot;
|
||||
my $form = 1;
|
||||
my ($config, $value, $options);
|
||||
|
||||
# Keep track of the configs that shouldn't be appended because
|
||||
# they were include_annot from another annotations file.
|
||||
# That's a hash of undefs, aka a set.
|
||||
my %noappend;
|
||||
|
||||
print "$P: $filename loading annotations\n";
|
||||
open(my $fd, "<$filename") ||
|
||||
die "$P: $filename: open failed -- $! -- aborting\n";
|
||||
while (<$fd>) {
|
||||
if (/^# FORMAT: (\S+)/) {
|
||||
die "$P: $1: unknown annotations format\n" if ($1 != 2 && $1 != 3 && $1 != 4);
|
||||
$form = $1;
|
||||
}
|
||||
|
||||
# Format #3 adds the include directive on top of format #2:
|
||||
if ($form == 3 && /^\s*include(\s|$)/) {
|
||||
# Include quoted or unquoted files:
|
||||
if (/^\s*include\s+"(.*)"\s*$/ || /^\s*include\s+(.*)$/) {
|
||||
# The include is relative to the current file
|
||||
my $include_filename = File::Spec->join(dirname($filename), $1);
|
||||
# Append the include files
|
||||
my %include_annot = read_annotations($include_filename);
|
||||
%annot = ( %annot, %include_annot );
|
||||
# And marked them to not be appended:
|
||||
my %included_noappend;
|
||||
# Discard the values and keep only the keys
|
||||
@included_noappend{keys %include_annot} = ();
|
||||
%noappend = ( %noappend, %included_noappend );
|
||||
next;
|
||||
} else {
|
||||
die "$P: Invalid include: $_";
|
||||
}
|
||||
}
|
||||
|
||||
/^#/ && next;
|
||||
chomp;
|
||||
/^$/ && next;
|
||||
/^CONFIG_/ || next;
|
||||
|
||||
if ($form == 1) {
|
||||
($config, $value, $options) = split(' ', $_, 3);
|
||||
} elsif ($form >= 2) {
|
||||
($config, $options) = split(' ', $_, 2);
|
||||
}
|
||||
|
||||
if (exists $noappend{$config}) {
|
||||
delete $annot{$config};
|
||||
delete $noappend{$config};
|
||||
}
|
||||
$annot{$config} = $annot{$config} . ' ' . $options;
|
||||
}
|
||||
close($fd);
|
||||
return %annot;
|
||||
}
|
||||
|
||||
# ANNOTATIONS: check any annotations marked for enforcement
|
||||
my $annotations = "$commonconfig/annotations";
|
||||
my %annot = read_annotations($annotations);
|
||||
|
||||
my $pass = 0;
|
||||
my $total = 0;
|
||||
my ($config, $value, $options, $option, $check, $policy);
|
||||
for $config (keys %annot) {
|
||||
$check = $enforce_all;
|
||||
$options = $annot{$config};
|
||||
|
||||
$policy = undef;
|
||||
while ($options =~ /\s*([^\s<]+)<(.*?)?>/g) {
|
||||
($option, $value) = ($1, $2);
|
||||
|
||||
if ($option eq 'mark' && $value eq 'ENFORCED') {
|
||||
$check = 1;
|
||||
|
||||
} elsif ($option eq 'policy') {
|
||||
if ($value =~ /^{/) {
|
||||
$value =~ s/:/=>/g;
|
||||
$policy = eval($value);
|
||||
warn "$config: $@" if ($@);
|
||||
} else {
|
||||
$policy = undef;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($check == 1 && !defined($policy)) {
|
||||
print "$P: INVALID POLICY (use policy<{...}>) $config$options\n";
|
||||
$total++;
|
||||
$check = 0;
|
||||
}
|
||||
if ($check) {
|
||||
# CONFIG_VERSION_SIGNATURE is dynamically set during the build
|
||||
next if ($config eq "CONFIG_VERSION_SIGNATURE");
|
||||
my $is = '-';
|
||||
$is = $values{$config} if (defined $values{$config});
|
||||
|
||||
my $value = '-';
|
||||
for my $which ("$arch-$flavour", "$arch-*", "*-$flavour", "$arch", "*") {
|
||||
if (defined $policy->{$which}) {
|
||||
$value = $policy->{$which};
|
||||
last;
|
||||
}
|
||||
}
|
||||
if ($is eq $value) {
|
||||
$pass++;
|
||||
} else {
|
||||
print "$P: FAIL ($is != $value): $config$options\n";
|
||||
$exit_val = $fail_exit;
|
||||
}
|
||||
$total++;
|
||||
}
|
||||
}
|
||||
|
||||
print "$P: $pass/$total checks passed -- exit $exit_val\n";
|
||||
exit $exit_val;
|
||||
+131
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/python3
|
||||
#
|
||||
# Check modules changes
|
||||
#
|
||||
# To skip the modules check, add a file
|
||||
# debian.<foo>/abi/<arch>/ignore.modules
|
||||
# or
|
||||
# debian.<foo>/abi/<arch>/<flavor>.ignore.modules
|
||||
#
|
||||
# To ignore a list of modules, add the modules to the file
|
||||
# debian.<foo>/abi/modules.ignore
|
||||
#
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if len(sys.argv) < 4 or len(sys.argv) > 5:
|
||||
print('Usage: module-check <flavor> <prev_abidir> <abidir> [<skipmodule>]')
|
||||
sys.exit(2)
|
||||
|
||||
flavor, prev_abidir, abidir = sys.argv[1:4] # pylint: disable=W0632
|
||||
if len(sys.argv) > 4:
|
||||
skipmodule = sys.argv[4].lower() in ['1', 'true', 'yes']
|
||||
else:
|
||||
skipmodule = False
|
||||
|
||||
print('II: Checking modules for {}...'.format(flavor), end='')
|
||||
|
||||
if ((os.path.exists('{}/ignore.modules'.format(prev_abidir)) or
|
||||
os.path.exists('{}/{}.ignore.modules'.format(prev_abidir, flavor)))):
|
||||
print('WW: Explicitly ignoring modules')
|
||||
print('II: Done')
|
||||
sys.exit(0)
|
||||
|
||||
curr_modules = '{}/{}.modules'.format(abidir, flavor)
|
||||
prev_modules = '{}/{}.modules'.format(prev_abidir, flavor)
|
||||
if not os.path.exists(curr_modules) or not os.path.exists(prev_modules):
|
||||
print('II: Previous or current modules file missing!')
|
||||
print(' {}'.format(curr_modules))
|
||||
print(' {}'.format(prev_modules))
|
||||
if skipmodule:
|
||||
print('WW: Explicitly asked to ignore failures')
|
||||
print('II: Done')
|
||||
sys.exit(0)
|
||||
print('EE: Missing modules file')
|
||||
sys.exit(1)
|
||||
|
||||
print()
|
||||
|
||||
modules = {}
|
||||
modules_ignore = {}
|
||||
|
||||
# See if we have any ignores
|
||||
print(' Reading modules to ignore...', end='')
|
||||
ignore = 0
|
||||
prev_modules_ignore = '{}/../modules.ignore'.format(prev_abidir)
|
||||
if os.path.exists(prev_modules_ignore):
|
||||
with open(prev_modules_ignore) as fh:
|
||||
for mod in fh:
|
||||
mod = mod.strip()
|
||||
if mod.startswith('#'):
|
||||
continue
|
||||
modules_ignore[mod] = 1
|
||||
ignore += 1
|
||||
print('read {} modules.'.format(ignore))
|
||||
|
||||
# Read new modules first
|
||||
print(' Reading new modules...', end='')
|
||||
new_count = 0
|
||||
for f in (curr_modules, curr_modules + '.builtin'):
|
||||
if not os.path.exists(f):
|
||||
continue
|
||||
with open(f) as fh:
|
||||
for mod in fh:
|
||||
mod = mod.strip()
|
||||
modules[mod] = {'new': 1}
|
||||
new_count += 1
|
||||
print('read {} modules.'.format(new_count))
|
||||
|
||||
# Now the old modules
|
||||
print(' Reading old modules...', end='')
|
||||
old_count = 0
|
||||
for f in (prev_modules, prev_modules + '.builtin'):
|
||||
if not os.path.exists(f):
|
||||
continue
|
||||
with open(f) as fh:
|
||||
for mod in fh:
|
||||
mod = mod.strip()
|
||||
if mod not in modules:
|
||||
modules[mod] = {}
|
||||
modules[mod]['old'] = 1
|
||||
old_count += 1
|
||||
print('read {} modules.'.format(old_count))
|
||||
|
||||
print('II: Checking for modules changes...')
|
||||
new = 0
|
||||
missing = 0
|
||||
missing_ignored = 0
|
||||
error = False
|
||||
for mod, vals in modules.items():
|
||||
# New modules
|
||||
if 'old' not in vals:
|
||||
print(' NEW: {}'.format(mod))
|
||||
new += 1
|
||||
|
||||
# Missing modules
|
||||
if 'new' not in vals:
|
||||
missing += 0
|
||||
if mod in modules_ignore:
|
||||
ignored = ' (ignored)'
|
||||
missing_ignored += 1
|
||||
else:
|
||||
ignored = ''
|
||||
error = True
|
||||
print(' MISS : {}{}'.format(mod, ignored))
|
||||
|
||||
if new > 0:
|
||||
print('II: {} new modules'.format(new))
|
||||
|
||||
if missing > 0:
|
||||
print('II: {} missing modules ({} ignored)'.format(missing, missing_ignored))
|
||||
|
||||
if error:
|
||||
if skipmodule:
|
||||
print('WW: Explicitly asked to ignore failures')
|
||||
else:
|
||||
print('EE: Missing modules')
|
||||
sys.exit(1)
|
||||
|
||||
print('II: Done')
|
||||
sys.exit(0)
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
flavor="${1}"
|
||||
mods_dir="${2}"
|
||||
mods_extra_dir="${3}"
|
||||
|
||||
echo "II: Checking signature of staging modules for ${flavor}..."
|
||||
|
||||
root=$(dirname "$(realpath -e "${0}")")/../../..
|
||||
. "${root}"/debian/debian.env
|
||||
|
||||
# Collect the signature-inclusion files
|
||||
sig_incs=()
|
||||
for d in debian "${DEBIAN}" ; do
|
||||
if [ -f "${root}"/"${d}"/signature-inclusion ] ; then
|
||||
sig_incs+=("${root}"/"${d}"/signature-inclusion)
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${#sig_incs[@]}" -gt 0 ] ; then
|
||||
echo "II: Use signature inclusion file(s):"
|
||||
printf " %s\n" "${sig_incs[@]}"
|
||||
sig_all=0
|
||||
else
|
||||
echo "WW: Signature inclusion file(s) missing"
|
||||
echo "II: All modules must be signed"
|
||||
sig_all=1
|
||||
fi
|
||||
|
||||
if ! [ -d "${mods_dir}" ] ; then
|
||||
echo "EE: Modules directory missing:"
|
||||
echo " ${mods_dir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "II: Checking modules directory:"
|
||||
echo " ${mods_dir}"
|
||||
mods_dirs=("${mods_dir}")
|
||||
|
||||
if [ -d "${mods_extra_dir}" ] ; then
|
||||
echo " ${mods_extra_dir}"
|
||||
mods_dirs+=("${mods_extra_dir}")
|
||||
fi
|
||||
|
||||
pass=0
|
||||
fail=0
|
||||
while IFS= read -r mod ; do
|
||||
is=0
|
||||
if /sbin/modinfo "${mod}" | grep -q "^signature:" ; then
|
||||
# Module is signed
|
||||
is=1
|
||||
fi
|
||||
|
||||
must=0
|
||||
if [ ${sig_all} -eq 1 ] || grep -qFx "${mod##*/}" "${sig_incs[@]}" ; then
|
||||
# Module must be signed
|
||||
must=1
|
||||
fi
|
||||
|
||||
case "${is}${must}" in
|
||||
00) echo " PASS (unsigned) : ${mod##*/}" ; pass=$((pass + 1)) ;;
|
||||
01) echo " FAIL (unsigned) : ${mod##*/}" ; fail=$((fail + 1)) ;;
|
||||
10) echo " FAIL (signed) : ${mod##*/}" ; fail=$((fail + 1)) ;;
|
||||
11) echo " PASS (signed) : ${mod##*/}" ; pass=$((pass + 1)) ;;
|
||||
esac
|
||||
done < <(find "${mods_dirs[@]}" -path '*/drivers/staging/*.ko' | sort)
|
||||
|
||||
echo "II: Checked $((pass + fail)) modules : ${pass} PASS, ${fail} FAIL"
|
||||
|
||||
if [ ${fail} -eq 0 ] ; then
|
||||
echo "II: Done"
|
||||
exit 0
|
||||
else
|
||||
echo "EE: Modules signature failures"
|
||||
exit 1
|
||||
fi
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
#!/bin/bash
|
||||
|
||||
flavour="$1"
|
||||
prev_abidir="$2"
|
||||
curr_abidir="$3"
|
||||
skipretpoline="$4"
|
||||
|
||||
echo "II: Checking retpoline indirections for $flavour...";
|
||||
|
||||
if [ "$skipretpoline" = 'true' ]; then
|
||||
echo "manual request ignoring retpoline delta"
|
||||
fi
|
||||
|
||||
if [ -f "$prev_abidir/ignore.retpoline" -o \
|
||||
-f "$prev_abidir/$flavour.ignore.retpoline" ]; then
|
||||
echo "explicitly ignoring retpoline delta"
|
||||
skipretpoline='true'
|
||||
fi
|
||||
|
||||
prev="$prev_abidir/$flavour.retpoline"
|
||||
curr="$curr_abidir/$flavour.retpoline"
|
||||
if [ ! -f "$prev" ]; then
|
||||
echo "previous retpoline file missing!"
|
||||
echo " $prev"
|
||||
prev="/dev/null"
|
||||
fi
|
||||
if [ ! -f "$curr" ]; then
|
||||
echo "current retpoline file missing!"
|
||||
echo " $curr"
|
||||
curr="/dev/null"
|
||||
fi
|
||||
|
||||
echo "II: retpoline delta in this package..."
|
||||
rc=0
|
||||
diff -u "$prev" "$curr" || true
|
||||
count=$( diff -u "$prev" "$curr" | grep '^+[^+]' | wc -l )
|
||||
if [ "$count" != 0 ]; then
|
||||
rc=1
|
||||
echo "WW: $count new retpoline sequences detected"
|
||||
fi
|
||||
|
||||
echo "II: Done";
|
||||
if [ "$skipretpoline" = 'true' -a "$rc" -ne 0 ]; then
|
||||
echo "II: ignoring errors"
|
||||
exit 0
|
||||
fi
|
||||
exit "$rc"
|
||||
Reference in New Issue
Block a user