Merge pull request #85880 from emilazy/linux-hardened-update-resilience
This commit is contained in:
commit
16e4b9ca69
4 changed files with 109 additions and 87 deletions
|
@ -1,27 +1,27 @@
|
|||
{
|
||||
"4.14.176": {
|
||||
"4.14": {
|
||||
"name": "linux-hardened-4.14.176.a.patch",
|
||||
"sha256": "0pr3m2j63mc746fcbzg1hlwv85im9f87qkl6r4033gwnpa9brcgk",
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.176.a/linux-hardened-4.14.176.a.patch",
|
||||
"version_suffix": "a"
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.176.a/linux-hardened-4.14.176.a.patch"
|
||||
},
|
||||
"4.19.117": {
|
||||
"4.19": {
|
||||
"name": "linux-hardened-4.19.117.a.patch",
|
||||
"sha256": "0c8dvh49nzypxwvsls10i896smvpdrk40x8ybljb3qk3r8j7niaw",
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.117.a/linux-hardened-4.19.117.a.patch",
|
||||
"version_suffix": "a"
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.117.a/linux-hardened-4.19.117.a.patch"
|
||||
},
|
||||
"5.4.35": {
|
||||
"5.4": {
|
||||
"name": "linux-hardened-5.4.34.a.patch",
|
||||
"sha256": "1xwpqr9nzpjg837b3wnzb8fmrl2g9rz8gz5yb55vnnllbzbz36v6",
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.34.a/linux-hardened-5.4.34.a.patch",
|
||||
"version_suffix": "a"
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.34.a/linux-hardened-5.4.34.a.patch"
|
||||
},
|
||||
"5.5.19": {
|
||||
"5.5": {
|
||||
"name": "linux-hardened-5.5.19.a.patch",
|
||||
"sha256": "1ya5nsfhr3nwz6qiz4pdhvm6k9mx1kr0prhdvhx3p40f1vk281sc",
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/5.5.19.a/linux-hardened-5.5.19.a.patch",
|
||||
"version_suffix": "a"
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/5.5.19.a/linux-hardened-5.5.19.a.patch"
|
||||
},
|
||||
"5.6.7": {
|
||||
"5.6": {
|
||||
"name": "linux-hardened-5.6.6.a.patch",
|
||||
"sha256": "0jiqh0frxirjbccgfdk007fca6r6n36n0pkqq4jszkckn59ayl7r",
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/5.6.6.a/linux-hardened-5.6.6.a.patch",
|
||||
"version_suffix": "a"
|
||||
"url": "https://github.com/anthraxx/linux-hardened/releases/download/5.6.6.a/linux-hardened-5.6.6.a.patch"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,16 +39,9 @@
|
|||
};
|
||||
|
||||
hardened = let
|
||||
mkPatch = kernelVersion: patch: let
|
||||
fullVersion = "${kernelVersion}.${patch.version_suffix}";
|
||||
name = "linux-hardened-${fullVersion}";
|
||||
in {
|
||||
inherit name;
|
||||
patch = fetchurl {
|
||||
name = "${name}.patch";
|
||||
inherit (patch) url sha256;
|
||||
meta.maintainers = with lib.maintainers; [ emily ];
|
||||
};
|
||||
mkPatch = kernelVersion: src: {
|
||||
name = lib.removeSuffix ".patch" src.name;
|
||||
patch = fetchurl src;
|
||||
};
|
||||
patches = builtins.fromJSON (builtins.readFile ./hardened-patches.json);
|
||||
in lib.mapAttrs mkPatch patches;
|
||||
|
|
|
@ -17,17 +17,7 @@ HERE = os.path.dirname(os.path.realpath(__file__))
|
|||
HARDENED_GITHUB_REPO = 'anthraxx/linux-hardened'
|
||||
HARDENED_TRUSTED_KEY = os.path.join(HERE, 'anthraxx.asc')
|
||||
HARDENED_PATCHES_PATH = os.path.join(HERE, 'hardened-patches.json')
|
||||
MIN_KERNEL = (4, 14)
|
||||
|
||||
HARDENED_VERSION_RE = re.compile(r'''
|
||||
(?P<kernel_version> [\d.]+) \.
|
||||
(?P<version_suffix> [a-z]+)
|
||||
''', re.VERBOSE)
|
||||
|
||||
def parse_version(version):
|
||||
match = HARDENED_VERSION_RE.fullmatch(version)
|
||||
if match:
|
||||
return match.groups()
|
||||
MIN_KERNEL_VERSION = [4, 14]
|
||||
|
||||
def run(*args, **kwargs):
|
||||
try:
|
||||
|
@ -78,11 +68,12 @@ def fetch_patch(*, name, release):
|
|||
except StopIteration:
|
||||
raise KeyError(filename)
|
||||
|
||||
patch_filename = f'{name}.patch'
|
||||
try:
|
||||
patch_url = find_asset(f'{name}.patch')
|
||||
sig_url = find_asset(f'{name}.patch.sig')
|
||||
patch_url = find_asset(patch_filename)
|
||||
sig_url = find_asset(patch_filename + '.sig')
|
||||
except KeyError:
|
||||
print(f'error: {name}.patch{{,sig}} not present', file=sys.stderr)
|
||||
print(f'error: {patch_filename}{{,.sig}} not present', file=sys.stderr)
|
||||
return None
|
||||
|
||||
sha256, patch_path = nix_prefetch_url(patch_url)
|
||||
|
@ -97,16 +88,32 @@ def fetch_patch(*, name, release):
|
|||
return None
|
||||
|
||||
return {
|
||||
'name': patch_filename,
|
||||
'url': patch_url,
|
||||
'sha256': sha256,
|
||||
}
|
||||
|
||||
def commit_patches(*, kernel_version, message):
|
||||
def parse_version(version_str):
|
||||
version = []
|
||||
for component in version_str.split('.'):
|
||||
try:
|
||||
version.append(int(component))
|
||||
except ValueError:
|
||||
version.append(component)
|
||||
return version
|
||||
|
||||
def version_string(version):
|
||||
return '.'.join(str(component) for component in version)
|
||||
|
||||
def major_kernel_version_key(kernel_version):
|
||||
return version_string(kernel_version[:-1])
|
||||
|
||||
def commit_patches(*, kernel_key, message):
|
||||
with open(HARDENED_PATCHES_PATH + '.new', 'w') as new_patches_file:
|
||||
json.dump(patches, new_patches_file, indent=4, sort_keys=True)
|
||||
new_patches_file.write('\n')
|
||||
os.rename(HARDENED_PATCHES_PATH + '.new', HARDENED_PATCHES_PATH)
|
||||
message = f'linux/hardened-patches/{kernel_version}: {message}'
|
||||
message = f'linux/hardened-patches/{kernel_key}: {message}'
|
||||
print(message)
|
||||
if os.environ.get('COMMIT'):
|
||||
run(
|
||||
|
@ -125,74 +132,96 @@ NIX_VERSION_RE = re.compile(r'''
|
|||
''', re.VERBOSE)
|
||||
|
||||
# Get the set of currently packaged kernel versions.
|
||||
kernel_versions = set()
|
||||
kernel_versions = {}
|
||||
for filename in os.listdir(HERE):
|
||||
filename_match = re.fullmatch(r'linux-(\d+)\.(\d+)\.nix', filename)
|
||||
if filename_match:
|
||||
if tuple(int(v) for v in filename_match.groups()) < MIN_KERNEL:
|
||||
continue
|
||||
with open(os.path.join(HERE, filename)) as nix_file:
|
||||
for nix_line in nix_file:
|
||||
match = NIX_VERSION_RE.fullmatch(nix_line)
|
||||
if match:
|
||||
kernel_versions.add(match.group('version'))
|
||||
kernel_version = parse_version(match.group('version'))
|
||||
if kernel_version < MIN_KERNEL_VERSION:
|
||||
continue
|
||||
kernel_key = major_kernel_version_key(kernel_version)
|
||||
kernel_versions[kernel_key] = kernel_version
|
||||
|
||||
# Remove patches for old kernel versions.
|
||||
for kernel_version in patches.keys() - kernel_versions:
|
||||
del patches[kernel_version]
|
||||
commit_patches(kernel_version=kernel_version, message='remove')
|
||||
# Remove patches for unpackaged kernel versions.
|
||||
for kernel_key in sorted(patches.keys() - kernel_versions.keys()):
|
||||
commit_patches(kernel_key=kernel_key, message='remove')
|
||||
|
||||
g = Github(os.environ.get('GITHUB_TOKEN'))
|
||||
repo = g.get_repo(HARDENED_GITHUB_REPO)
|
||||
releases = repo.get_releases()
|
||||
|
||||
found_kernel_versions = set()
|
||||
failures = False
|
||||
|
||||
for release in releases:
|
||||
remaining_kernel_versions = kernel_versions - found_kernel_versions
|
||||
|
||||
if not remaining_kernel_versions:
|
||||
break
|
||||
|
||||
version = release.tag_name
|
||||
name = f'linux-hardened-{version}'
|
||||
version_info = parse_version(version)
|
||||
if not version_info:
|
||||
# Match each kernel version with the best patch version.
|
||||
releases = {}
|
||||
for release in repo.get_releases():
|
||||
version = parse_version(release.tag_name)
|
||||
# needs to look like e.g. 5.6.3.a
|
||||
if len(version) < 4:
|
||||
continue
|
||||
kernel_version, version_suffix = version_info
|
||||
|
||||
if kernel_version in remaining_kernel_versions:
|
||||
found_kernel_versions.add(kernel_version)
|
||||
try:
|
||||
old_version_suffix = patches[kernel_version]['version_suffix']
|
||||
old_version = f'{kernel_version}.{old_version_suffix}'
|
||||
update = old_version_suffix < version_suffix
|
||||
except KeyError:
|
||||
update = True
|
||||
old_version = None
|
||||
kernel_version = version[:-1]
|
||||
kernel_key = major_kernel_version_key(kernel_version)
|
||||
try:
|
||||
packaged_kernel_version = kernel_versions[kernel_key]
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
if update:
|
||||
patch = fetch_patch(name=name, release=release)
|
||||
if patch is None:
|
||||
failures = True
|
||||
release_info = {
|
||||
'version': version,
|
||||
'release': release,
|
||||
}
|
||||
|
||||
if kernel_version == packaged_kernel_version:
|
||||
releases[kernel_key] = release_info
|
||||
else:
|
||||
# Fall back to the latest patch for this major kernel version,
|
||||
# skipping patches for kernels newer than the packaged one.
|
||||
if kernel_version > packaged_kernel_version:
|
||||
continue
|
||||
elif (kernel_key not in releases or
|
||||
releases[kernel_key]['version'] < version):
|
||||
releases[kernel_key] = release_info
|
||||
|
||||
# Update hardened-patches.json for each release.
|
||||
for kernel_key, release_info in releases.items():
|
||||
release = release_info['release']
|
||||
version = release_info['version']
|
||||
version_str = release.tag_name
|
||||
name = f'linux-hardened-{version_str}'
|
||||
|
||||
try:
|
||||
old_filename = patches[kernel_key]['name']
|
||||
old_version_str = (old_filename
|
||||
.replace('linux-hardened-', '')
|
||||
.replace('.patch', ''))
|
||||
old_version = parse_version(old_version_str)
|
||||
update = old_version < version
|
||||
except KeyError:
|
||||
update = True
|
||||
old_version = None
|
||||
|
||||
if update:
|
||||
patch = fetch_patch(name=name, release=release)
|
||||
if patch is None:
|
||||
failures = True
|
||||
else:
|
||||
patches[kernel_key] = patch
|
||||
if old_version:
|
||||
message = f'{old_version_str} -> {version_str}'
|
||||
else:
|
||||
patch['version_suffix'] = version_suffix
|
||||
patches[kernel_version] = patch
|
||||
if old_version:
|
||||
message = f'{old_version} -> {version}'
|
||||
else:
|
||||
message = f'init at {version}'
|
||||
commit_patches(kernel_version=kernel_version, message=message)
|
||||
message = f'init at {version_str}'
|
||||
commit_patches(kernel_key=kernel_key, message=message)
|
||||
|
||||
missing_kernel_versions = kernel_versions - patches.keys()
|
||||
missing_kernel_versions = kernel_versions.keys() - patches.keys()
|
||||
|
||||
if missing_kernel_versions:
|
||||
print(
|
||||
f'warning: no patches for kernel versions ' +
|
||||
', '.join(missing_kernel_versions) +
|
||||
'\nwarning: consider manually backporting older patches (bump '
|
||||
'JSON key, set version_suffix to "NixOS-a")',
|
||||
', '.join(missing_kernel_versions),
|
||||
file=sys.stderr,
|
||||
)
|
||||
|
||||
|
|
|
@ -17051,7 +17051,7 @@ in
|
|||
};
|
||||
kernelPatches = kernel.kernelPatches ++ [
|
||||
kernelPatches.tag_hardened
|
||||
kernelPatches.hardened.${kernel.version}
|
||||
kernelPatches.hardened.${kernel.meta.branch}
|
||||
];
|
||||
modDirVersionArg = kernel.modDirVersion + "-hardened";
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue