Accepting request 178980 from home:michal-m:branches:Base:System

- Put debuginfo packages to %_topdir/OTHER (bnc#824971).

- Version 10
- Add modsign-repackage tool to repackage RPMs outside the buildservice

OBS-URL: https://build.opensuse.org/request/show/178980
OBS-URL: https://build.opensuse.org/package/show/Base:System/pesign-obs-integration?expand=0&rev=18
This commit is contained in:
Marcus Meissner 2013-06-14 21:59:33 +00:00 committed by Git OBS Bridge
parent 0952d005e5
commit c9543f88db
6 changed files with 255 additions and 27 deletions

View File

@ -68,6 +68,23 @@ sub read_file($)
return $contents;
}
sub openssl_pipe($$) {
my ($input, $cmd) = @_;
my ($pid, $res);
$pid = open2(*read_from, *write_to, $cmd) || die $cmd;
binmode write_to;
print write_to $input || die "pipe to $cmd";
close(write_to) || die "pipe to $cmd";
binmode read_from;
read(read_from, $res, 4096) || die "pipe from $cmd";
close(read_from) || die "pipe from $cmd";
waitpid($pid, 0) || die;
die "$cmd died: $?" if ($? >> 8);
return $res;
}
###############################################################################
#
# First of all, we have to parse the X.509 certificate to find certain details
@ -358,6 +375,26 @@ if ($dgst eq "sha1") {
die "Unknown hash algorithm: $dgst\n";
}
my $unsigned_module = read_file($module);
my $magic_number = $sign_fw ?
"~Linux firmware signature~\n" :
"~Module signature appended~\n";
my $magic_len = length($magic_number);
my $info_len = 12;
# Truncate existing signarure, if any
if (!$sign_fw && substr($unsigned_module, -$magic_len) eq $magic_number) {
my $info = substr($unsigned_module, -$magic_len - $info_len, $info_len);
my ($name_len, $key_len, $sig_len) = unpack("xxxCCxxxN", $info);
my $subtract = $name_len + $key_len + $sig_len + $info_len + $magic_len;
if ($subtract > length($unsigned_module)) {
die "$module: Existing signature is malformed\n";
}
$unsigned_module = substr($unsigned_module, 0,
length($unsigned_module) - $subtract);
}
my $signature;
if ($signature_file) {
$signature = read_file($signature_file);
@ -365,43 +402,30 @@ if ($signature_file) {
#
# Generate the digest and read from openssl's stdout
#
my $digest;
$digest = readpipe("openssl dgst -$dgst -binary $module") || die "openssl dgst";
my $digest = openssl_pipe($unsigned_module,
"openssl dgst -$dgst -binary");
#
# Generate the binary signature, which will be just the integer that
# comprises the signature with no metadata attached.
#
my $pid;
$pid = open2(*read_from, *write_to,
"openssl rsautl -sign -inkey $private_key -keyform PEM") ||
die "openssl rsautl";
binmode write_to;
print write_to $prologue . $digest || die "pipe to openssl rsautl";
close(write_to) || die "pipe to openssl rsautl";
binmode read_from;
read(read_from, $signature, 4096) || die "pipe from openssl rsautl";
close(read_from) || die "pipe from openssl rsautl";
waitpid($pid, 0) || die;
die "openssl rsautl died: $?" if ($? >> 8);
$signature = openssl_pipe($prologue . $digest,
"openssl rsautl -sign -inkey $private_key -keyform PEM");
}
$signature = pack("n", length($signature)) . $signature,
#
# Build the signed binary
#
my $unsigned_module = read_file($module);
my $magic_number = $sign_fw ?
"~Linux firmware signature~\n" :
"~Module signature appended~\n";
my $info = pack("CCCCCxxxN",
$algo, $hash, $id_type,
length($signers_name),
length($key_identifier),
length($signature));
# Make sure that $info_len value used above matches reality
if (length($info) != $info_len) {
die "Signature info size changed ($info_len -> @{[length($info)]}";
}
if ($verbose) {
print "Size of unsigned $mode_name: ", length($unsigned_module), "\n";

142
modsign-repackage Normal file
View File

@ -0,0 +1,142 @@
#!/bin/bash
# Script to sign kernel modules and create new RPM packages with these
# modules. Uses pesign-gen-repackage-spec for the repackaging.
#
# Copyright (c) 2013 SUSE Linux Products GmbH, Nuernberg, Germany.
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
USAGE="$0 --key <private key> --certificate <x509 cert> rpm ..."
options=`getopt -o hk:c: --long help,key:,certificate: -- "$@"`
if test $? -ne 0; then
echo "$USAGE" >&2
exit 1
fi
eval set -- "$options"
key=
cert=
while :; do
case "$1" in
-k|--key)
key=$2
shift 2
;;
-c|--certificate)
cert=$2
shift 2
;;
-h|--help)
echo "$USAGE"
exit
;;
--)
shift
break
esac
done
if test -z "$key" -o -z "$cert"; then
echo "$0: The --key and --certificate options are mandatory" >&2
echo "$USAGE" >&2
exit 1
fi
if test "$#" -eq 0; then
echo "$0: No packages specified" >&2
echo "$USAGE" >&2
exit 1
fi
workdir="$PWD/rpm-files.$$"
buildroot="$workdir/buildroot"
rpmdir=RPMS
srpmdir=SRPMS
disturl=
rpms=()
rm -rf "$workdir"
mkdir "$workdir" || exit
mkdir -p "$rpmdir" "$srpmdir" || exit
mkdir "$buildroot"
echo "Unpacking original RPMs..."
for rpm; do
# XXX: Use a common script in pesign-repackage.spec.in and here
case "$rpm" in
*.src.rpm | *.nosrc.rpm)
cp "$rpm" "$srpmdir/"
continue
;;
# Do not repackage debuginfo packages (bnc#806637)
*-debuginfo-*.rpm | *-debugsource-*.rpm)
dir="$rpmdir/$(rpm -qp --qf '%{arch}' "$rpm")"
mkdir -p "$dir"
cp "$rpm" "$dir"
continue
;;
esac
# do not repackage baselibs packages
# FIXME: needs more generic test (if architecture has different
# bitness => skip)
case "$(rpm -qp --qf '%{name}/%{arch}' "$rpm")" in
*-32bit/x86_64 | *-32bit/s390x | *-32bit/ppc64 | \
*-64bit/ppc | *-x86/ia64)
mkdir -p "$rpmdir/$(rpm -qp --qf '%{arch}')/"
cp "$rpm" "$_"
continue
esac
rpm2cpio "$rpm" | (cd "$buildroot"; cpio -idm --quiet) || exit
d=$(rpm -qp --qf '%{disturl}' "$rpm")
if test -z "$disturl"; then
disturl=$d
fi
if test "$disturl" != "$d"; then
echo "Error: packages have different disturl: $d vs $disturl"
exit 1
fi
rpms=("${rpms[@]}" "$rpm")
done
set -e
echo "Signing kernel modules..."
for module in $(find "$buildroot" -type f -name '*.ko'); do
/usr/lib/rpm/pesign/kernel-sign-file \
sha256 "$key" "$cert" "$module"
done
# Add the certificate
mkdir -p "$buildroot/etc/uefi/certs"
h=$(openssl x509 -inform DER -fingerprint -noout -in "$cert")
filename=/etc/uefi/certs/$(echo "$h" | \
sed -rn 's/^SHA1 Fingerprint=//; T; s/://g; s/(.{8}).*/\1/p').crt
cp "$cert" "$buildroot/$filename"
echo "Generating new specfile..."
if ! test -e /usr/lib/rpm/kernel-cert-subpackage; then
echo "/usr/lib/rpm/kernel-cert-subpackage missing" >&2
echo "please install the kernel-source package" >&2
exit 1
fi
/usr/lib/rpm/pesign/pesign-gen-repackage-spec \
--cert-subpackage=/usr/lib/rpm/kernel-cert-subpackage \
--directory="$buildroot" --output="$workdir" "${rpms[@]}"
echo "Running rpmbuild..."
rpmbuild --define "buildroot $buildroot" --define "disturl $disturl" \
--define "_builddir $workdir" \
--define "_suse_insert_debug_package %{nil}" \
--define "_rpmdir $rpmdir" \
-bb "$workdir/repackage.spec" >"$workdir/log" 2>&1
grep 'RPMS/.*\.rpm$' "$workdir/log"
echo "Cleaning up $workdir..."
rm -r "$workdir"
echo "Done."
exit 0

View File

@ -28,6 +28,8 @@ use Fcntl qw(:mode :seek);
my $directory;
my $output = ".";
my $cert_subpackage;
my $kmp_basename;
my @rpms;
$ENV{LC_ALL} = "en_US.UTF-8";
@ -36,6 +38,7 @@ GetOptions(
"help|h" => sub { print $USAGE; exit; },
"directory|d=s" => \$directory,
"output|o=s" => \$output,
"cert-subpackage|c=s" => \$cert_subpackage,
) or die $USAGE;
@rpms = @ARGV;
if (!@rpms) {
@ -155,7 +158,7 @@ sub load_package {
my @files;
my @list = query_array($rpm, qw(filenames fileflags filemodes fileusername filegroupname filesizes filemtimes filelinktos));
for my $file (@list) {
push(@files, {
my $new = {
name => $file->[0],
flags => $file->[1],
mode => $file->[2],
@ -164,7 +167,11 @@ sub load_package {
size => $file->[5],
mtime => $file->[6],
target => $file->[7],
});
};
push(@files, $new);
if ($new->{name} =~ /\.ko$/ && S_ISREG($new->{mode})) {
$res{is_kmp} = 1;
}
}
$res{files} = \@files;
while (my ($dep, $tag) = each(%dep2tag)) {
@ -264,6 +271,9 @@ sub print_package {
for my $dep (keys(%dep2tag)) {
print_deps($dep, $p->{$dep});
}
if ($cert_subpackage && $p->{is_kmp}) {
print SPEC "Requires: $kmp_basename-ueficert\n";
}
print SPEC "\%description -n $p->{name}\n";
print SPEC quote($p->{description}) . "\n\n";
@ -424,12 +434,50 @@ if (!exists($packages{$main_name})) {
}
$packages{$main_name}->{nosource} = $nosrc ? 1 : 0;
# Find out the basename of <name>-kmp-<flavor>, falling back to the
# main package name
for my $p (values(%packages)) {
next unless $p->{is_kmp};
(my $n = $p->{name}) =~ s/-kmp-.*//;
$kmp_basename = $n unless $kmp_basename;
if ($n ne $kmp_basename) {
$kmp_basename = undef;
last;
}
}
$kmp_basename = $main_name unless $kmp_basename;
open(SPEC, '>', "$output/repackage.spec") or die "$output/repackage.spec: $!\n";
print_package($packages{$main_name}, 1);
for my $p (values(%packages)) {
next if $p->{name} eq $main_name;
print_package($p, 0);
}
if ($cert_subpackage) {
my $certdir = "/etc/uefi/certs";
my $certs = "";
if (-d "$directory/$certdir") {
opendir(my $dh, "$directory/$certdir") or die "$directory/$certdir";
while (my $cert = readdir($dh)) {
next if $cert =~ /^\.\.?$/;
if ($cert !~ /\.crt$/) {
print STDERR "warning: Ignoring $directory/$certdir/$cert (no .crt suffix)\n";
next;
}
$certs .= " $certdir/$cert";
}
}
if (!$certs) {
print STDERR "warning: --cert-subpackage specified, but no certs found in $directory/$certdir\n";
}
local $/ = undef;
open(my $fh, '<', $cert_subpackage) or die "$cert_subpackage: $!\n";
my $template = <$fh>;
close($fh);
$template =~ s/\%{-n\*}/$kmp_basename/g;
$template =~ s/\@CERTS\@/$certs/g;
print SPEC $template;
}
print SPEC "\%changelog\n";
print SPEC quote($packages{$main_name}->{changelog});
close(SPEC);

View File

@ -1,3 +1,14 @@
-------------------------------------------------------------------
Fri Jun 14 12:19:47 UTC 2013 - mmarek@suse.cz
- Put debuginfo packages to %_topdir/OTHER (bnc#824971).
-------------------------------------------------------------------
Thu Mar 28 15:55:10 UTC 2013 - mmarek@suse.cz
- Version 10
- Add modsign-repackage tool to repackage RPMs outside the buildservice
-------------------------------------------------------------------
Tue Mar 26 06:19:45 UTC 2013 - glin@suse.com

View File

@ -22,7 +22,7 @@ Name: pesign-obs-integration
Summary: Macros and scripts to sign the kernel and bootloader
License: GPL-2.0
Group: Development/Tools/Other
Version: 9.0
Version: 10.0
Release: 0.<RELEASE15>
Requires: mozilla-nss-tools
Requires: openssl
@ -37,6 +37,7 @@ Source4: brp-99-pesign
Source5: COPYING
Source6: README
Source7: kernel-sign-file
Source8: modsign-repackage
BuildRoot: %{_tmppath}/%{name}-%{version}-build
%description
@ -56,6 +57,8 @@ cd %_sourcedir
install pesign-gen-repackage-spec kernel-sign-file %buildroot/usr/lib/rpm/pesign
install brp-99-pesign %buildroot/usr/lib/rpm/brp-suse.d
install -m644 pesign-repackage.spec.in %buildroot/usr/lib/rpm/pesign
mkdir -p %buildroot/usr/bin
install modsign-repackage %buildroot/usr/bin/
if test -e _projectcert.crt; then
openssl x509 -inform PEM -in _projectcert.crt \
-outform DER -out %buildroot/usr/lib/rpm/pesign/pesign-cert.x509
@ -66,6 +69,7 @@ fi
%files
%defattr(-,root,root)
%doc COPYING README
/usr/bin/modsign-repackage
/usr/lib/rpm/*
%changelog

View File

@ -54,9 +54,8 @@ for rpm in %_sourcedir/*.rpm; do
;;
# Do not repackage debuginfo packages (bnc#806637)
*-debuginfo-*.rpm | *-debugsource-*.rpm)
dir=%_rpmdir/$(rpm -qp --qf '%%{arch}' "$rpm")
mkdir -p "$dir"
cp "$rpm" "$dir"
mkdir -p "%_topdir/OTHER"
cp "$rpm" "$_"
continue
;;
esac