aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/pkgs/os-specific/linux/kernel/hardened
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/os-specific/linux/kernel/hardened')
-rw-r--r--nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc325
-rw-r--r--nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix85
-rw-r--r--nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json27
-rw-r--r--nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch7
-rwxr-xr-xnixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py276
5 files changed, 720 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc
new file mode 100644
index 00000000000..101ccfbf0f2
--- /dev/null
+++ b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/anthraxx.asc
@@ -0,0 +1,325 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v2
+
+mQINBE64OEUBEADPS1v+zoCdKA6zyfUtVIaBoIwMhCibqurXi30tVoC9LgM6W1ve
+HwPFukWq7DAS0mZUPE3mSV63JFLaTy0bY/6GO1D4wLdWZx4ppH7XKNCvKCbsi70k
+UozFykNVf+83WEskuF1oYzXlF3aB5suz2IWJl7ey1EXgIpehwQaTJUA5JIWYFp9A
+566LRNJefYMzUR33xc4dRKj6Etg0xdLVq7/vZoo8HpLCBGNWiP0AKqFWEwTg0xQL
+7nsJA5tfJJdwAJvrzjpFsvb63PKG6waAtdHhON4q7E2Udak9fz2tRjxA5l9l2zXk
+aqsysUzkxPhNjwMENoQ04KZg4aT+ZhhBzTowSWLp3KV2uaZ66kdPUO3s+/1bPp5/
+N/IlykaUwyL773iYOZ5dOY/9hIuX/zssihcrGEMW6yIyZR5uKhzYdaM9ExTXP637
+UccgNS9/pskPGPx/xK23NDCfeHzL9YHS5KokA2wb/b9hqpwvLaeblbMl2pt79F1R
+ac+rZlrRyX3NvlTQP4hqM9Ei2YBAU7QFDJEjH8pVIceL7grxi1Ju1iD5QiSK+je5
+Jj5EAikfwSeAttSzsqNvaXJHfABrv5mkkVt1z3icP3HIHTYnG+uj+t8kvW+o9/1i
+pD6e6LUh4w5v1aY9kaK/M3+eBH59yNYI99crPUKUBVfW4gv4DBUJAQTWRQARAQAB
+tDVMZXZlbnRlIFBvbHlhayAoYW50aHJheHgpIDxsZXZlbnRlQGxldmVudGVwb2x5
+YWsubmV0PokCQQQTAQIAKwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4ACGQEF
+AlSXU9QFCQfATw8ACgkQ/BtUfI2BcsjPbxAAs+UR/bJz/HeYTpPy+HnKwDJgI9GP
+AZlNvp+QSIhOTtKCYkQ/Iu+5scY5J0Qyv0pcJW5Rxjx+l7KGovw84jzVznnYsJoy
+UQ5H3Ev9T2xW1nrZT3abJ7j6ZIck+Q+WFHu5Plsq6doSXOXmJNoehvT3BVolvc6w
+S1+CAoyA5Wm1yfocZgVOvWPWQaa1T4XA7OwxFWrvNWEZwAzTSjkGHkwmji+DxdBd
+RPam9+qm/rcN1IJTu6xJPr38a9LydWonsUpTR2Qn7Bo4EJp8yHJLaiLEMV/Nmgrr
+1orBYw/OzDzhbdMl+2zzwEBLUMPABdgnPM6ZCZ5PWyWnCU4jsBGyVd0IC5xEu3Eg
+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
+a6MNZO/+vKN4UTlgjpjxZon+/yK8bsmT/VNie5hzqZim6tfztl3rpJ9jPUeLgr5x
+oGePYV02inapzNHdWFHk0L9zR/3KKfJ3IRJwUXp00Eya28hEepIvdxgLYcN1UqVn
+VuFuMY8zYSl/VXtPxySCLENJHxvdtClMZXZlbnRlIFBvbHlhayA8bGV2ZW50ZUBs
+ZXZlbnRlcG9seWFrLmRlPokCPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoLBBYCAwEC
+HgECF4AFAlSXU9oFCQfATw8ACgkQ/BtUfI2BcsiPxw//X2xUctIrd1O7UOk7LHBX
+/xI7xXoWQcA7l/1XMuZhM8yC8yIoAgvFrWBP1a29I0P3/yigkQXs+eTDTdvb0QP2
+q72q7Azt852v5u8+dHzoOXDpbo+4lfX+0OBDWimwJuChD8LQH7b7jO0oqWIV0AzM
+vegFJVp3cDbyqw08lBz3xZ79A9JtBeewf6PLpXKjEVS8bEAZjZKjsjAY+5ShtJAf
+PsD8r353dmkaHgC5Aji74ijZeY3PUCvGVVCGeN9isLnRpTEn7qUvN2DfHJU4w6aw
+sXu7m7zidISo6dQLUzo54dHKWPGFy6INNkzXPOgrlbYnjt7v0Ou21/R6HrhdmsSw
+lt7GALJcgAUxrcT/ljB3SZhSB0BdH0DXPcUziEdfhgMhhrXYpMjwH2XFBD1MLusW
+GaVDbpPrSoEnmPVePcDUonDHePcuLjfOl13mOER1Kf6WFapOCa+4HCLakfKcPnGY
+eyfD7Dbz3/046MmfQ8/Iyf8ipFXN6tI2WkRKj8uq9IFYrX3yoCBxZJN837DM3Grq
+h48/T3pYU1f9LiekxbsgXmcHoGNdXX5+EsuO+QILZPttlG5QLuqFdJHei77uvW+B
+4u8mgzi1Zhh0hRLm4K6UaJ/fBJ87BZSHShPKI9PI073U1O/CcYXnb8cdPLu3UgSQ
+FM/bxT70TSYKI01Dt4KXRfWIRgQQEQIABgUCTrg/KAAKCRC+dA9BPyK7GT9FAJ47
+X5+0dQaOFkfy3WnMgX3AmIXJYQCfR4XL47rZ9a66jWaD0IbcXMK4oE2JAj4EEwEC
+ACgFAk64PJ4CGwMFCQIchwAGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJEPwb
+VHyNgXLI2U8QAJGKPv1gWLn7P1KeHVsKkfRf+zgdsoY4mF3bUjX/03z1h1OKp+S7
+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
+kekzzVjVTZxOgZE=
+=yRuG
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix
new file mode 100644
index 00000000000..95510fe218e
--- /dev/null
+++ b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/config.nix
@@ -0,0 +1,85 @@
+# Based on recommendations from:
+# http://kernsec.org/wiki/index.php/Kernel_Self_Protection_Project#Recommended_settings
+# https://wiki.gentoo.org/wiki/Hardened/Hardened_Kernel_Project
+#
+# Dangerous features that can be permanently (for the boot session) disabled at
+# boot via sysctl or kernel cmdline are left enabled here, for improved
+# flexibility.
+#
+# See also <nixos/modules/profiles/hardened.nix>
+
+{ stdenv, version }:
+
+with stdenv.lib;
+with stdenv.lib.kernel;
+with (stdenv.lib.kernel.whenHelpers version);
+
+assert (versionAtLeast version "4.9");
+
+{
+ # Report BUG() conditions and kill the offending process.
+ BUG = yes;
+
+ # Safer page access permissions (wrt. code injection). Default on >=4.11.
+ DEBUG_RODATA = whenOlder "4.11" yes;
+ DEBUG_SET_MODULE_RONX = whenOlder "4.11" yes;
+
+ # Mark LSM hooks read-only after init. SECURITY_WRITABLE_HOOKS n
+ # conflicts with SECURITY_SELINUX_DISABLE y; disabling the latter
+ # implicitly marks LSM hooks read-only after init.
+ #
+ # SELinux can only be disabled at boot via selinux=0
+ #
+ # We set SECURITY_WRITABLE_HOOKS n primarily for documentation purposes; the
+ # config builder fails to detect that it has indeed been unset.
+ SECURITY_SELINUX_DISABLE = whenAtLeast "4.12" no;
+ SECURITY_WRITABLE_HOOKS = whenAtLeast "4.12" (option no);
+
+ STRICT_KERNEL_RWX = whenAtLeast "4.11" yes;
+
+ # Perform additional validation of commonly targeted structures.
+ DEBUG_CREDENTIALS = yes;
+ DEBUG_NOTIFIERS = yes;
+ DEBUG_PI_LIST = yes; # doesn't BUG()
+ DEBUG_SG = yes;
+ SCHED_STACK_END_CHECK = yes;
+
+ REFCOUNT_FULL = whenAtLeast "4.13" yes;
+
+ # Randomize page allocator when page_alloc.shuffle=1
+ SHUFFLE_PAGE_ALLOCATOR = whenAtLeast "5.2" yes;
+
+ # Allow enabling slub/slab free poisoning with slub_debug=P
+ SLUB_DEBUG = yes;
+
+ # Wipe higher-level memory allocations on free() with page_poison=1
+ PAGE_POISONING = yes;
+ PAGE_POISONING_NO_SANITY = yes;
+ PAGE_POISONING_ZERO = yes;
+
+ # Enable the SafeSetId LSM
+ SECURITY_SAFESETID = whenAtLeast "5.1" yes;
+
+ # Reboot devices immediately if kernel experiences an Oops.
+ PANIC_TIMEOUT = freeform "-1";
+
+ GCC_PLUGINS = yes; # Enable gcc plugin options
+ # Gather additional entropy at boot time for systems that may = no;ot have appropriate entropy sources.
+ GCC_PLUGIN_LATENT_ENTROPY = yes;
+
+ GCC_PLUGIN_STRUCTLEAK = whenAtLeast "4.11" yes; # A port of the PaX structleak plugin
+ GCC_PLUGIN_STRUCTLEAK_BYREF_ALL = whenAtLeast "4.14" yes; # Also cover structs passed by address
+ GCC_PLUGIN_STACKLEAK = whenAtLeast "4.20" yes; # A port of the PaX stackleak plugin
+ GCC_PLUGIN_RANDSTRUCT = whenAtLeast "4.13" yes; # A port of the PaX randstruct plugin
+ GCC_PLUGIN_RANDSTRUCT_PERFORMANCE = whenAtLeast "4.13" yes;
+
+ # Disable various dangerous settings
+ ACPI_CUSTOM_METHOD = no; # Allows writing directly to physical memory
+ PROC_KCORE = no; # Exposes kernel text image layout
+ INET_DIAG = no; # Has been used for heap based attacks in the past
+
+ # Use -fstack-protector-strong (gcc 4.9+) for best stack canary coverage.
+ CC_STACKPROTECTOR_REGULAR = whenOlder "4.18" no;
+ CC_STACKPROTECTOR_STRONG = whenOlder "4.18" yes;
+
+}
diff --git a/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json
new file mode 100644
index 00000000000..19517fd9ea3
--- /dev/null
+++ b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/patches.json
@@ -0,0 +1,27 @@
+{
+ "4.14": {
+ "name": "linux-hardened-4.14.180.a.patch",
+ "sha256": "0rpk5lq947i4v48d6jv75rgwpncayr4agc3f2iich3hlkh5p72p3",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.180.a/linux-hardened-4.14.180.a.patch"
+ },
+ "4.19": {
+ "name": "linux-hardened-4.19.123.a.patch",
+ "sha256": "12z4f0nph23110dpk0c8av9bjr8q9qhmyzzj2chrscfwybmld76h",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.123.a/linux-hardened-4.19.123.a.patch"
+ },
+ "5.4": {
+ "name": "linux-hardened-5.4.41.a.patch",
+ "sha256": "0rbp0radqcs2bqapp9k0hvafxn3wlzkc50wnw1145w76mkvpc91y",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.41.a/linux-hardened-5.4.41.a.patch"
+ },
+ "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"
+ },
+ "5.6": {
+ "name": "linux-hardened-5.6.13.a.patch",
+ "sha256": "1z1f15h0wpajkiaqagnx8r25vmabkpc69rzn2h0p3k6z72l6iri5",
+ "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.6.13.a/linux-hardened-5.6.13.a.patch"
+ }
+}
diff --git a/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch
new file mode 100644
index 00000000000..ff8a3a12797
--- /dev/null
+++ b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/tag-hardened.patch
@@ -0,0 +1,7 @@
+diff --git a/localversion-hardened b/localversion-hardened
+new file mode 100644
+index 0000000000..e578045860
+--- /dev/null
++++ b/localversion-hardened
+@@ -0,0 +1 @@
++-hardened
diff --git a/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py
new file mode 100755
index 00000000000..d6443d2e751
--- /dev/null
+++ b/nixpkgs/pkgs/os-specific/linux/kernel/hardened/update.py
@@ -0,0 +1,276 @@
+#! /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_json = run(
+ "nix-instantiate", "--eval", "--json", "--expr", nix_version_expr,
+ ).stdout
+ kernel_version = parse_version(json.loads(kernel_version_json))
+ 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)