linux/update-hardened.py: reformat

$ isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --use-parentheses …
$ black --line-length=80 …

(per the black documentation)
This commit is contained in:
Emily 2020-04-26 19:28:24 +01:00
parent 4cad49dc1a
commit 83c4ac2eb3
1 changed files with 80 additions and 58 deletions

View File

@ -3,60 +3,68 @@
# This is automatically called by ./update.sh. # This is automatically called by ./update.sh.
import re
import json import json
import sys
import os.path import os.path
from glob import glob import re
import subprocess import subprocess
import sys
from glob import glob
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
from github import Github from github import Github
HERE = os.path.dirname(os.path.realpath(__file__)) HERE = os.path.dirname(os.path.realpath(__file__))
HARDENED_GITHUB_REPO = 'anthraxx/linux-hardened' HARDENED_GITHUB_REPO = "anthraxx/linux-hardened"
HARDENED_TRUSTED_KEY = os.path.join(HERE, 'anthraxx.asc') HARDENED_TRUSTED_KEY = os.path.join(HERE, "anthraxx.asc")
HARDENED_PATCHES_PATH = os.path.join(HERE, 'hardened-patches.json') HARDENED_PATCHES_PATH = os.path.join(HERE, "hardened-patches.json")
MIN_KERNEL_VERSION = [4, 14] MIN_KERNEL_VERSION = [4, 14]
def run(*args, **kwargs): def run(*args, **kwargs):
try: try:
return subprocess.run( return subprocess.run(
args, **kwargs, args,
check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs,
check=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
) )
except subprocess.CalledProcessError as err: except subprocess.CalledProcessError as err:
print( print(
f'error: `{err.cmd}` failed unexpectedly\n' f"error: `{err.cmd}` failed unexpectedly\n"
f'status code: {err.returncode}\n' f"status code: {err.returncode}\n"
f'stdout:\n{err.stdout.decode("utf-8").strip()}\n' f'stdout:\n{err.stdout.decode("utf-8").strip()}\n'
f'stderr:\n{err.stderr.decode("utf-8").strip()}', f'stderr:\n{err.stderr.decode("utf-8").strip()}',
file=sys.stderr, file=sys.stderr,
) )
sys.exit(1) sys.exit(1)
def nix_prefetch_url(url): def nix_prefetch_url(url):
output = run('nix-prefetch-url', '--print-path', url).stdout output = run("nix-prefetch-url", "--print-path", url).stdout
return output.decode('utf-8').strip().split('\n') return output.decode("utf-8").strip().split("\n")
def verify_openpgp_signature(*, name, trusted_key, sig_path, data_path): def verify_openpgp_signature(*, name, trusted_key, sig_path, data_path):
with TemporaryDirectory(suffix='.nixpkgs-gnupg-home') as gnupg_home: with TemporaryDirectory(suffix=".nixpkgs-gnupg-home") as gnupg_home:
run('gpg', '--homedir', gnupg_home, '--import', trusted_key) run("gpg", "--homedir", gnupg_home, "--import", trusted_key)
keyring = os.path.join(gnupg_home, 'pubring.kbx') keyring = os.path.join(gnupg_home, "pubring.kbx")
try: try:
subprocess.run( subprocess.run(
('gpgv', '--keyring', keyring, sig_path, data_path), ("gpgv", "--keyring", keyring, sig_path, data_path),
check=True, stderr=subprocess.PIPE, check=True,
stderr=subprocess.PIPE,
) )
return True return True
except subprocess.CalledProcessError as err: except subprocess.CalledProcessError as err:
print( print(
f'error: signature for {name} failed to verify!', f"error: signature for {name} failed to verify!",
file=sys.stderr, file=sys.stderr,
) )
print(err.stderr.decode('utf-8'), file=sys.stderr, end='') print(err.stderr.decode("utf-8"), file=sys.stderr, end="")
return False return False
def fetch_patch(*, name, release): def fetch_patch(*, name, release):
def find_asset(filename): def find_asset(filename):
try: try:
@ -68,12 +76,12 @@ def fetch_patch(*, name, release):
except StopIteration: except StopIteration:
raise KeyError(filename) raise KeyError(filename)
patch_filename = f'{name}.patch' patch_filename = f"{name}.patch"
try: try:
patch_url = find_asset(patch_filename) patch_url = find_asset(patch_filename)
sig_url = find_asset(patch_filename + '.sig') sig_url = find_asset(patch_filename + ".sig")
except KeyError: except KeyError:
print(f'error: {patch_filename}{{,.sig}} not present', file=sys.stderr) print(f"error: {patch_filename}{{,.sig}} not present", file=sys.stderr)
return None return None
sha256, patch_path = nix_prefetch_url(patch_url) sha256, patch_path = nix_prefetch_url(patch_url)
@ -88,59 +96,71 @@ def fetch_patch(*, name, release):
return None return None
return { return {
'name': patch_filename, "name": patch_filename,
'url': patch_url, "url": patch_url,
'sha256': sha256, "sha256": sha256,
} }
def parse_version(version_str): def parse_version(version_str):
version = [] version = []
for component in version_str.split('.'): for component in version_str.split("."):
try: try:
version.append(int(component)) version.append(int(component))
except ValueError: except ValueError:
version.append(component) version.append(component)
return version return version
def version_string(version): def version_string(version):
return '.'.join(str(component) for component in version) return ".".join(str(component) for component in version)
def major_kernel_version_key(kernel_version): def major_kernel_version_key(kernel_version):
return version_string(kernel_version[:-1]) return version_string(kernel_version[:-1])
def commit_patches(*, kernel_key, message): def commit_patches(*, kernel_key, message):
with open(HARDENED_PATCHES_PATH + '.new', 'w') as new_patches_file: with open(HARDENED_PATCHES_PATH + ".new", "w") as new_patches_file:
json.dump(patches, new_patches_file, indent=4, sort_keys=True) json.dump(patches, new_patches_file, indent=4, sort_keys=True)
new_patches_file.write('\n') new_patches_file.write("\n")
os.rename(HARDENED_PATCHES_PATH + '.new', HARDENED_PATCHES_PATH) os.rename(HARDENED_PATCHES_PATH + ".new", HARDENED_PATCHES_PATH)
message = f'linux/hardened-patches/{kernel_key}: {message}' message = f"linux/hardened-patches/{kernel_key}: {message}"
print(message) print(message)
if os.environ.get('COMMIT'): if os.environ.get("COMMIT"):
run( run(
'git', '-C', HERE, 'commit', f'--message={message}', "git",
'hardened-patches.json', "-C",
HERE,
"commit",
f"--message={message}",
"hardened-patches.json",
) )
# Load the existing patches. # Load the existing patches.
with open(HARDENED_PATCHES_PATH) as patches_file: with open(HARDENED_PATCHES_PATH) as patches_file:
patches = json.load(patches_file) patches = json.load(patches_file)
NIX_VERSION_RE = re.compile(r''' NIX_VERSION_RE = re.compile(
r"""
\s* version \s* = \s* version \s* =
\s* " (?P<version> [^"]*) " \s* " (?P<version> [^"]*) "
\s* ; \s* \n \s* ; \s* \n
''', re.VERBOSE) """,
re.VERBOSE,
)
# Get the set of currently packaged kernel versions. # Get the set of currently packaged kernel versions.
kernel_versions = {} kernel_versions = {}
for filename in os.listdir(HERE): for filename in os.listdir(HERE):
filename_match = re.fullmatch(r'linux-(\d+)\.(\d+)\.nix', filename) filename_match = re.fullmatch(r"linux-(\d+)\.(\d+)\.nix", filename)
if filename_match: if filename_match:
with open(os.path.join(HERE, filename)) as nix_file: with open(os.path.join(HERE, filename)) as nix_file:
for nix_line in nix_file: for nix_line in nix_file:
match = NIX_VERSION_RE.fullmatch(nix_line) match = NIX_VERSION_RE.fullmatch(nix_line)
if match: if match:
kernel_version = parse_version(match.group('version')) kernel_version = parse_version(match.group("version"))
if kernel_version < MIN_KERNEL_VERSION: if kernel_version < MIN_KERNEL_VERSION:
continue continue
kernel_key = major_kernel_version_key(kernel_version) kernel_key = major_kernel_version_key(kernel_version)
@ -148,9 +168,9 @@ for filename in os.listdir(HERE):
# Remove patches for unpackaged kernel versions. # Remove patches for unpackaged kernel versions.
for kernel_key in sorted(patches.keys() - kernel_versions.keys()): for kernel_key in sorted(patches.keys() - kernel_versions.keys()):
commit_patches(kernel_key=kernel_key, message='remove') commit_patches(kernel_key=kernel_key, message="remove")
g = Github(os.environ.get('GITHUB_TOKEN')) g = Github(os.environ.get("GITHUB_TOKEN"))
repo = g.get_repo(HARDENED_GITHUB_REPO) repo = g.get_repo(HARDENED_GITHUB_REPO)
failures = False failures = False
@ -171,8 +191,8 @@ for release in repo.get_releases():
continue continue
release_info = { release_info = {
'version': version, "version": version,
'release': release, "release": release,
} }
if kernel_version == packaged_kernel_version: if kernel_version == packaged_kernel_version:
@ -182,22 +202,24 @@ for release in repo.get_releases():
# skipping patches for kernels newer than the packaged one. # skipping patches for kernels newer than the packaged one.
if kernel_version > packaged_kernel_version: if kernel_version > packaged_kernel_version:
continue continue
elif (kernel_key not in releases or elif (
releases[kernel_key]['version'] < version): kernel_key not in releases
or releases[kernel_key]["version"] < version
):
releases[kernel_key] = release_info releases[kernel_key] = release_info
# Update hardened-patches.json for each release. # Update hardened-patches.json for each release.
for kernel_key, release_info in releases.items(): for kernel_key, release_info in releases.items():
release = release_info['release'] release = release_info["release"]
version = release_info['version'] version = release_info["version"]
version_str = release.tag_name version_str = release.tag_name
name = f'linux-hardened-{version_str}' name = f"linux-hardened-{version_str}"
try: try:
old_filename = patches[kernel_key]['name'] old_filename = patches[kernel_key]["name"]
old_version_str = (old_filename old_version_str = old_filename.replace("linux-hardened-", "").replace(
.replace('linux-hardened-', '') ".patch", ""
.replace('.patch', '')) )
old_version = parse_version(old_version_str) old_version = parse_version(old_version_str)
update = old_version < version update = old_version < version
except KeyError: except KeyError:
@ -211,17 +233,17 @@ for kernel_key, release_info in releases.items():
else: else:
patches[kernel_key] = patch patches[kernel_key] = patch
if old_version: if old_version:
message = f'{old_version_str} -> {version_str}' message = f"{old_version_str} -> {version_str}"
else: else:
message = f'init at {version_str}' message = f"init at {version_str}"
commit_patches(kernel_key=kernel_key, message=message) commit_patches(kernel_key=kernel_key, message=message)
missing_kernel_versions = kernel_versions.keys() - patches.keys() missing_kernel_versions = kernel_versions.keys() - patches.keys()
if missing_kernel_versions: if missing_kernel_versions:
print( print(
f'warning: no patches for kernel versions ' + f"warning: no patches for kernel versions "
', '.join(missing_kernel_versions), + ", ".join(missing_kernel_versions),
file=sys.stderr, file=sys.stderr,
) )