about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJörg Thalheim <Mic92@users.noreply.github.com>2020-05-11 10:40:42 +0100
committerGitHub <noreply@github.com>2020-05-11 10:40:42 +0100
commit885f65fbff4fa98ce6ba5620f6fc59f39be3141f (patch)
treeef56ceb725b40474bdd7826ba0a2564e02d30d29
parent3a9543b778f9c2f16a1ff145163d76cb730652a2 (diff)
parent5a5a2d0342ee6610f14a7024c6b01ab6261749f9 (diff)
downloadnixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.tar
nixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.tar.gz
nixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.tar.bz2
nixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.tar.lz
nixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.tar.xz
nixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.tar.zst
nixlib-885f65fbff4fa98ce6ba5620f6fc59f39be3141f.zip
Merge pull request #86074 from emilazy/refactor-linux-hardened-update-script
-rw-r--r--lib/kernel.nix2
-rw-r--r--pkgs/development/python-modules/pyGithub/default.nix4
-rw-r--r--pkgs/os-specific/linux/kernel/hardened/anthraxx.asc (renamed from pkgs/os-specific/linux/kernel/anthraxx.asc)0
-rw-r--r--pkgs/os-specific/linux/kernel/hardened/config.nix (renamed from pkgs/os-specific/linux/kernel/hardened-config.nix)0
-rw-r--r--pkgs/os-specific/linux/kernel/hardened/patches.json (renamed from pkgs/os-specific/linux/kernel/hardened-patches.json)0
-rw-r--r--pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch (renamed from pkgs/os-specific/linux/kernel/tag-hardened.patch)0
-rwxr-xr-xpkgs/os-specific/linux/kernel/hardened/update.py277
-rw-r--r--pkgs/os-specific/linux/kernel/patches.nix4
-rwxr-xr-xpkgs/os-specific/linux/kernel/update-hardened.py229
-rwxr-xr-xpkgs/os-specific/linux/kernel/update.sh2
-rw-r--r--pkgs/top-level/all-packages.nix2
11 files changed, 284 insertions, 236 deletions
diff --git a/lib/kernel.nix b/lib/kernel.nix
index 2ce19f8cb68c..8045a228d05e 100644
--- a/lib/kernel.nix
+++ b/lib/kernel.nix
@@ -14,7 +14,7 @@ with lib;
   freeform = x: { freeform = x; };
 
   /*
-    Common patterns/legacy used in common-config/hardened-config.nix
+    Common patterns/legacy used in common-config/hardened/config.nix
    */
   whenHelpers = version: {
     whenAtLeast = ver: mkIf (versionAtLeast version ver);
diff --git a/pkgs/development/python-modules/pyGithub/default.nix b/pkgs/development/python-modules/pyGithub/default.nix
index 2102554faceb..cf0784024f17 100644
--- a/pkgs/development/python-modules/pyGithub/default.nix
+++ b/pkgs/development/python-modules/pyGithub/default.nix
@@ -12,14 +12,14 @@
 
 buildPythonPackage rec {
   pname = "PyGithub";
-  version = "1.47";
+  version = "1.51";
   disabled = !isPy3k;
 
   src = fetchFromGitHub {
     owner = "PyGithub";
     repo = "PyGithub";
     rev = "v${version}";
-    sha256 = "0zvp1gib2lryw698vxkbdv40n3lsmdlhwp7vdcg41dqqa5nfryhn";
+    hash = "sha256-8uQCFiw1ByPOX8ZRUlSLYPIibjmd19r/JtTnmQdz5cM=";
   };
 
   checkInputs = [ httpretty parameterized pytestCheckHook ];
diff --git a/pkgs/os-specific/linux/kernel/anthraxx.asc b/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc
index 101ccfbf0f2b..101ccfbf0f2b 100644
--- a/pkgs/os-specific/linux/kernel/anthraxx.asc
+++ b/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc
diff --git a/pkgs/os-specific/linux/kernel/hardened-config.nix b/pkgs/os-specific/linux/kernel/hardened/config.nix
index 95510fe218e3..95510fe218e3 100644
--- a/pkgs/os-specific/linux/kernel/hardened-config.nix
+++ b/pkgs/os-specific/linux/kernel/hardened/config.nix
diff --git a/pkgs/os-specific/linux/kernel/hardened-patches.json b/pkgs/os-specific/linux/kernel/hardened/patches.json
index 118998a605b2..118998a605b2 100644
--- a/pkgs/os-specific/linux/kernel/hardened-patches.json
+++ b/pkgs/os-specific/linux/kernel/hardened/patches.json
diff --git a/pkgs/os-specific/linux/kernel/tag-hardened.patch b/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch
index ff8a3a127973..ff8a3a127973 100644
--- a/pkgs/os-specific/linux/kernel/tag-hardened.patch
+++ b/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch
diff --git a/pkgs/os-specific/linux/kernel/hardened/update.py b/pkgs/os-specific/linux/kernel/hardened/update.py
new file mode 100755
index 000000000000..3958c85fe206
--- /dev/null
+++ b/pkgs/os-specific/linux/kernel/hardened/update.py
@@ -0,0 +1,277 @@
+#! /usr/bin/env nix-shell
+#! nix-shell -i python -p "python38.withPackages (ps: [ps.PyGithub])" git gnupg
+
+# This is automatically called by ../update.sh.
+
+from __future__ import annotations
+
+import json
+import os
+import re
+import subprocess
+import sys
+from dataclasses import dataclass
+from pathlib import Path
+from tempfile import TemporaryDirectory
+from typing import (
+    Dict,
+    Iterator,
+    List,
+    Optional,
+    Sequence,
+    Tuple,
+    TypedDict,
+    Union,
+)
+
+from github import Github
+from github.GitRelease import GitRelease
+
+VersionComponent = Union[int, str]
+Version = List[VersionComponent]
+
+
+Patch = TypedDict("Patch", {"name": str, "url": str, "sha256": str})
+
+
+@dataclass
+class ReleaseInfo:
+    version: Version
+    release: GitRelease
+
+
+HERE = Path(__file__).resolve().parent
+NIXPKGS_KERNEL_PATH = HERE.parent
+NIXPKGS_PATH = HERE.parents[4]
+HARDENED_GITHUB_REPO = "anthraxx/linux-hardened"
+HARDENED_TRUSTED_KEY = HERE / "anthraxx.asc"
+HARDENED_PATCHES_PATH = HERE / "patches.json"
+MIN_KERNEL_VERSION: Version = [4, 14]
+
+
+def run(*args: Union[str, Path]) -> subprocess.CompletedProcess[bytes]:
+    try:
+        return subprocess.run(
+            args,
+            check=True,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            encoding="utf-8",
+        )
+    except subprocess.CalledProcessError as err:
+        print(
+            f"error: `{err.cmd}` failed unexpectedly\n"
+            f"status code: {err.returncode}\n"
+            f"stdout:\n{err.stdout.strip()}\n"
+            f"stderr:\n{err.stderr.strip()}",
+            file=sys.stderr,
+        )
+        sys.exit(1)
+
+
+def nix_prefetch_url(url: str) -> Tuple[str, Path]:
+    output = run("nix-prefetch-url", "--print-path", url).stdout
+    sha256, path = output.strip().split("\n")
+    return sha256, Path(path)
+
+
+def verify_openpgp_signature(
+    *, name: str, trusted_key: Path, sig_path: Path, data_path: Path,
+) -> bool:
+    with TemporaryDirectory(suffix=".nixpkgs-gnupg-home") as gnupg_home_str:
+        gnupg_home = Path(gnupg_home_str)
+        run("gpg", "--homedir", gnupg_home, "--import", trusted_key)
+        keyring = gnupg_home / "pubring.kbx"
+        try:
+            subprocess.run(
+                ("gpgv", "--keyring", keyring, sig_path, data_path),
+                check=True,
+                stderr=subprocess.PIPE,
+                encoding="utf-8",
+            )
+            return True
+        except subprocess.CalledProcessError as err:
+            print(
+                f"error: signature for {name} failed to verify!",
+                file=sys.stderr,
+            )
+            print(err.stderr, file=sys.stderr, end="")
+            return False
+
+
+def fetch_patch(*, name: str, release: GitRelease) -> Optional[Patch]:
+    def find_asset(filename: str) -> str:
+        try:
+            it: Iterator[str] = (
+                asset.browser_download_url
+                for asset in release.get_assets()
+                if asset.name == filename
+            )
+            return next(it)
+        except StopIteration:
+            raise KeyError(filename)
+
+    patch_filename = f"{name}.patch"
+    try:
+        patch_url = find_asset(patch_filename)
+        sig_url = find_asset(patch_filename + ".sig")
+    except KeyError:
+        print(f"error: {patch_filename}{{,.sig}} not present", file=sys.stderr)
+        return None
+
+    sha256, patch_path = nix_prefetch_url(patch_url)
+    _, sig_path = nix_prefetch_url(sig_url)
+    sig_ok = verify_openpgp_signature(
+        name=name,
+        trusted_key=HARDENED_TRUSTED_KEY,
+        sig_path=sig_path,
+        data_path=patch_path,
+    )
+    if not sig_ok:
+        return None
+
+    return Patch(name=patch_filename, url=patch_url, sha256=sha256)
+
+
+def parse_version(version_str: str) -> Version:
+    version: Version = []
+    for component in version_str.split("."):
+        try:
+            version.append(int(component))
+        except ValueError:
+            version.append(component)
+    return version
+
+
+def version_string(version: Version) -> str:
+    return ".".join(str(component) for component in version)
+
+
+def major_kernel_version_key(kernel_version: Version) -> str:
+    return version_string(kernel_version[:-1])
+
+
+def commit_patches(*, kernel_key: str, message: str) -> None:
+    new_patches_path = HARDENED_PATCHES_PATH.with_suffix(".new")
+    with open(new_patches_path, "w") as new_patches_file:
+        json.dump(patches, new_patches_file, indent=4, sort_keys=True)
+        new_patches_file.write("\n")
+    os.rename(new_patches_path, HARDENED_PATCHES_PATH)
+    message = f"linux/hardened/patches/{kernel_key}: {message}"
+    print(message)
+    if os.environ.get("COMMIT"):
+        run(
+            "git",
+            "-C",
+            NIXPKGS_PATH,
+            "commit",
+            f"--message={message}",
+            HARDENED_PATCHES_PATH,
+        )
+
+
+# Load the existing patches.
+patches: Dict[str, Patch]
+with open(HARDENED_PATCHES_PATH) as patches_file:
+    patches = json.load(patches_file)
+
+# Get the set of currently packaged kernel versions.
+kernel_versions = {}
+for filename in os.listdir(NIXPKGS_KERNEL_PATH):
+    filename_match = re.fullmatch(r"linux-(\d+)\.(\d+)\.nix", filename)
+    if filename_match:
+        nix_version_expr = f"""
+            with import {NIXPKGS_PATH} {{}};
+            (callPackage {NIXPKGS_KERNEL_PATH / filename} {{}}).version
+        """
+        kernel_version = parse_version(
+            run(
+                "nix", "eval", "--impure", "--raw", "--expr", nix_version_expr,
+            ).stdout
+        )
+        if kernel_version < MIN_KERNEL_VERSION:
+            continue
+        kernel_key = major_kernel_version_key(kernel_version)
+        kernel_versions[kernel_key] = kernel_version
+
+# 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)
+failures = False
+
+# 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[:-1]
+    kernel_key = major_kernel_version_key(kernel_version)
+    try:
+        packaged_kernel_version = kernel_versions[kernel_key]
+    except KeyError:
+        continue
+
+    release_info = ReleaseInfo(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 in sorted(releases.keys()):
+    release_info = releases[kernel_key]
+    release = release_info.release
+    version = release_info.version
+    version_str = release.tag_name
+    name = f"linux-hardened-{version_str}"
+
+    old_version: Optional[Version] = None
+    old_version_str: Optional[str] = None
+    update: bool
+    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
+
+    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:
+                message = f"init at {version_str}"
+            commit_patches(kernel_key=kernel_key, message=message)
+
+missing_kernel_versions = kernel_versions.keys() - patches.keys()
+
+if missing_kernel_versions:
+    print(
+        f"warning: no patches for kernel versions "
+        + ", ".join(missing_kernel_versions),
+        file=sys.stderr,
+    )
+
+if failures:
+    sys.exit(1)
diff --git a/pkgs/os-specific/linux/kernel/patches.nix b/pkgs/os-specific/linux/kernel/patches.nix
index 1c4af8c32a6f..8ce1ac2b587c 100644
--- a/pkgs/os-specific/linux/kernel/patches.nix
+++ b/pkgs/os-specific/linux/kernel/patches.nix
@@ -35,7 +35,7 @@
 
   tag_hardened = {
     name = "tag-hardened";
-    patch = ./tag-hardened.patch;
+    patch = ./hardened/tag-hardened.patch;
   };
 
   hardened = let
@@ -43,7 +43,7 @@
       name = lib.removeSuffix ".patch" src.name;
       patch = fetchurl src;
     };
-    patches = builtins.fromJSON (builtins.readFile ./hardened-patches.json);
+    patches = builtins.fromJSON (builtins.readFile ./hardened/patches.json);
   in lib.mapAttrs mkPatch patches;
 
   # https://bugzilla.kernel.org/show_bug.cgi?id=197591#c6
diff --git a/pkgs/os-specific/linux/kernel/update-hardened.py b/pkgs/os-specific/linux/kernel/update-hardened.py
deleted file mode 100755
index 7f6949653afc..000000000000
--- a/pkgs/os-specific/linux/kernel/update-hardened.py
+++ /dev/null
@@ -1,229 +0,0 @@
-#! /usr/bin/env nix-shell
-#! nix-shell -i python -p "python3.withPackages (ps: [ps.PyGithub])" git gnupg
-
-# This is automatically called by ./update.sh.
-
-import re
-import json
-import sys
-import os.path
-from glob import glob
-import subprocess
-from tempfile import TemporaryDirectory
-
-from github import Github
-
-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_VERSION = [4, 14]
-
-def run(*args, **kwargs):
-    try:
-        return subprocess.run(
-            args, **kwargs,
-            check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
-        )
-    except subprocess.CalledProcessError as err:
-        print(
-            f'error: `{err.cmd}` failed unexpectedly\n'
-            f'status code: {err.returncode}\n'
-            f'stdout:\n{err.stdout.decode("utf-8").strip()}\n'
-            f'stderr:\n{err.stderr.decode("utf-8").strip()}',
-            file=sys.stderr,
-        )
-        sys.exit(1)
-
-def nix_prefetch_url(url):
-    output = run('nix-prefetch-url', '--print-path', url).stdout
-    return output.decode('utf-8').strip().split('\n')
-
-def verify_openpgp_signature(*, name, trusted_key, sig_path, data_path):
-    with TemporaryDirectory(suffix='.nixpkgs-gnupg-home') as gnupg_home:
-        run('gpg', '--homedir', gnupg_home, '--import', trusted_key)
-        keyring = os.path.join(gnupg_home, 'pubring.kbx')
-        try:
-            subprocess.run(
-                ('gpgv', '--keyring', keyring, sig_path, data_path),
-                check=True, stderr=subprocess.PIPE,
-            )
-            return True
-        except subprocess.CalledProcessError as err:
-            print(
-                f'error: signature for {name} failed to verify!',
-                file=sys.stderr,
-            )
-            print(err.stderr.decode('utf-8'), file=sys.stderr, end='')
-            return False
-
-def fetch_patch(*, name, release):
-    def find_asset(filename):
-        try:
-            return next(
-                asset.browser_download_url
-                for asset in release.get_assets()
-                if asset.name == filename
-            )
-        except StopIteration:
-            raise KeyError(filename)
-
-    patch_filename = f'{name}.patch'
-    try:
-        patch_url = find_asset(patch_filename)
-        sig_url = find_asset(patch_filename + '.sig')
-    except KeyError:
-        print(f'error: {patch_filename}{{,.sig}} not present', file=sys.stderr)
-        return None
-
-    sha256, patch_path = nix_prefetch_url(patch_url)
-    _, sig_path = nix_prefetch_url(sig_url)
-    sig_ok = verify_openpgp_signature(
-        name=name,
-        trusted_key=HARDENED_TRUSTED_KEY,
-        sig_path=sig_path,
-        data_path=patch_path,
-    )
-    if not sig_ok:
-        return None
-
-    return {
-        'name': patch_filename,
-        'url': patch_url,
-        'sha256': sha256,
-    }
-
-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_key}: {message}'
-    print(message)
-    if os.environ.get('COMMIT'):
-        run(
-            'git', '-C', HERE, 'commit', f'--message={message}',
-            'hardened-patches.json',
-        )
-
-# Load the existing patches.
-with open(HARDENED_PATCHES_PATH) as patches_file:
-    patches = json.load(patches_file)
-
-NIX_VERSION_RE = re.compile(r'''
-    \s* version \s* =
-    \s* " (?P<version> [^"]*) "
-    \s* ; \s* \n
-''', re.VERBOSE)
-
-# Get the set of currently packaged kernel versions.
-kernel_versions = {}
-for filename in os.listdir(HERE):
-    filename_match = re.fullmatch(r'linux-(\d+)\.(\d+)\.nix', filename)
-    if filename_match:
-        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_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 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)
-
-failures = False
-
-# 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[:-1]
-    kernel_key = major_kernel_version_key(kernel_version)
-    try:
-        packaged_kernel_version = kernel_versions[kernel_key]
-    except KeyError:
-        continue
-
-    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:
-                message = f'init at {version_str}'
-            commit_patches(kernel_key=kernel_key, message=message)
-
-missing_kernel_versions = kernel_versions.keys() - patches.keys()
-
-if missing_kernel_versions:
-    print(
-        f'warning: no patches for kernel versions ' +
-        ', '.join(missing_kernel_versions),
-        file=sys.stderr,
-    )
-
-if failures:
-    sys.exit(1)
diff --git a/pkgs/os-specific/linux/kernel/update.sh b/pkgs/os-specific/linux/kernel/update.sh
index c483661b6f5d..55fdce06c973 100755
--- a/pkgs/os-specific/linux/kernel/update.sh
+++ b/pkgs/os-specific/linux/kernel/update.sh
@@ -62,4 +62,4 @@ done
 COMMIT=1 $NIXPKGS/pkgs/os-specific/linux/kernel/update-libre.sh
 
 # Update linux-hardened
-COMMIT=1 $NIXPKGS/pkgs/os-specific/linux/kernel/update-hardened.py
+COMMIT=1 $NIXPKGS/pkgs/os-specific/linux/kernel/hardened/update.py
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index cea991531538..17aabe58daa8 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -17065,7 +17065,7 @@ in
 
   # Hardened linux
   hardenedLinuxPackagesFor = kernel: linuxPackagesFor (kernel.override {
-    structuredExtraConfig = import ../os-specific/linux/kernel/hardened-config.nix {
+    structuredExtraConfig = import ../os-specific/linux/kernel/hardened/config.nix {
       inherit stdenv;
       inherit (kernel) version;
     };