From b5cdf98158932b245db302dc0fd3c82dee437f7b Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 25 Jan 2017 04:24:09 +0000 Subject: [PATCH] [rt] genpatch.py: Verify tag and tarball signatures --- debian/bin/git-tag-gpg-wrapper | 2 +- debian/changelog | 1 + debian/patches/features/all/rt/genpatch.py | 41 ++++++++++++++++++--- debian/source/include-binaries | 1 + debian/upstream/rt-signing-key.pgp | Bin 0 -> 13892 bytes 5 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 debian/upstream/rt-signing-key.pgp diff --git a/debian/bin/git-tag-gpg-wrapper b/debian/bin/git-tag-gpg-wrapper index 58e1750ee..9982b0140 100755 --- a/debian/bin/git-tag-gpg-wrapper +++ b/debian/bin/git-tag-gpg-wrapper @@ -30,4 +30,4 @@ while true; do esac done -exec gpgv "${gpgv_opts[@]}" --keyring "$debian_dir/upstream/signing-key.pgp" -- "$@" +exec gpgv "${gpgv_opts[@]}" --keyring "$debian_dir/upstream/${DEBIAN_KERNEL_KEYRING:-signing-key.pgp}" -- "$@" diff --git a/debian/changelog b/debian/changelog index feb3850fb..153220295 100644 --- a/debian/changelog +++ b/debian/changelog @@ -363,6 +363,7 @@ linux (4.9.5-1) UNRELEASED; urgency=medium * [arm64] video/fbdev: Change FB from module to built-in * [arm64,armhf] video/fbdev: Enable FB_EFI (Closes: #851778) * fs: Disable LOGFS, as it is unmaintained and will be removed in 4.10 + * [rt] genpatch.py: Verify tag and tarball signatures [ Salvatore Bonaccorso ] * tmpfs: clear S_ISGID when setting posix ACLs (CVE-2017-5551) diff --git a/debian/patches/features/all/rt/genpatch.py b/debian/patches/features/all/rt/genpatch.py index 6253a4ece..eb3792d35 100755 --- a/debian/patches/features/all/rt/genpatch.py +++ b/debian/patches/features/all/rt/genpatch.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -import errno, io, os, os.path, re, shutil, subprocess, sys, tempfile +import codecs, errno, io, os, os.path, re, shutil, subprocess, sys, tempfile def main(source, version=None): patch_dir = 'debian/patches' @@ -44,13 +44,25 @@ def main(source, version=None): if os.path.isdir(os.path.join(source, '.git')): # Export rebased branch from stable-rt git as patch series up_ver = re.sub(r'-rt\d+$', '', version) - args = ['git', 'format-patch', 'v%s..v%s-rebase' % (up_ver, version)] env = os.environ.copy() env['GIT_DIR'] = os.path.join(source, '.git') - child = subprocess.Popen(args, - cwd=os.path.join(patch_dir, rt_patch_dir), - env=env, stdout=subprocess.PIPE) - with io.open(child.stdout.fileno(), encoding='utf-8') as pipe: + env['DEBIAN_KERNEL_KEYRING'] = 'rt-signing-key.pgp' + + # Validate tag signature + gpg_wrapper = os.path.join(os.getcwd(), + "debian/bin/git-tag-gpg-wrapper") + verify_proc = subprocess.Popen(['git', + '-c', 'gpg.program=%s' % gpg_wrapper, + 'tag', '-v', 'v%s-rebase' % version], + env=env) + if verify_proc.wait(): + raise RuntimeError("GPG tag verification failed") + + args = ['git', 'format-patch', 'v%s..v%s-rebase' % (up_ver, version)] + format_proc = subprocess.Popen(args, + cwd=os.path.join(patch_dir, rt_patch_dir), + env=env, stdout=subprocess.PIPE) + with io.open(format_proc.stdout.fileno(), encoding='utf-8') as pipe: for line in pipe: name = line.strip('\n') with open(os.path.join(patch_dir, rt_patch_dir, name)) as \ @@ -60,6 +72,7 @@ def main(source, version=None): assert match origin = 'https://git.kernel.org/cgit/linux/kernel/git/rt/linux-stable-rt.git/commit?id=%s' % match.group(1) add_patch(name, source_patch, origin) + else: # Get version and upstream version if version is None: @@ -70,6 +83,22 @@ def main(source, version=None): assert match, 'could not parse version string' up_ver = match.group(1) + # Expect an accompanying signature, and validate it + source_sig = re.sub(r'.[gx]z$', '.sign', source) + unxz_proc = subprocess.Popen(['xzcat', source], + stdout=subprocess.PIPE) + verify_output = subprocess.check_output( + ['gpgv', '--status-fd', '1', + '--keyring', 'debian/upstream/rt-signing-key.pgp', + '--ignore-time-conflict', source_sig, '-'], + stdin=unxz_proc.stdout) + if unxz_proc.wait() or \ + not re.search(r'^\[GNUPG:\]\s+VALIDSIG\s', + codecs.decode(verify_output), + re.MULTILINE): + os.write(2, verify_output) # bytes not str! + raise RuntimeError("GPG signature verification failed") + temp_dir = tempfile.mkdtemp(prefix='rt-genpatch', dir='debian') try: # Unpack tarball diff --git a/debian/source/include-binaries b/debian/source/include-binaries index a61050820..f9b965374 100644 --- a/debian/source/include-binaries +++ b/debian/source/include-binaries @@ -1 +1,2 @@ +debian/upstream/rt-signing-key.pgp debian/upstream/signing-key.pgp diff --git a/debian/upstream/rt-signing-key.pgp b/debian/upstream/rt-signing-key.pgp new file mode 100644 index 0000000000000000000000000000000000000000..f55b064cf1efb2bc315c35a988844c9958ed5653 GIT binary patch literal 13892 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 d>44lK5W6xNBeH_AVFOhA^D-^Ekb@?V{1;EH$2