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:
parent
4cad49dc1a
commit
83c4ac2eb3
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue