linux: build hardened kernel with matching releases

Until now we merged kernel updates even if no hardened versions were
available yet. On one hand we don't want to delay patch-level updates,
on the other hand users of hardened kernels have frequent breakage now[1].

This change aims to provide a solution this issue:

* The hardened patchset now references the kernel version it's released
for (including a sha256 hash for the fixed-output path of the source
tarball).
* The `hardenedKernelFor`-function doesn't just append hardened patches
now, but also overrides version & src to match the kernel version the
patch was built & tested for.

Refs #140281

[1] https://hydra.nixos.org/job/nixos/trunk-combined/nixpkgs.linuxPackages_hardened.kernel.x86_64-linux/all

+74 -28
+40 -20
pkgs/os-specific/linux/kernel/hardened/patches.json
··· 1 1 { 2 2 "4.14": { 3 - "extra": "-hardened1", 4 - "name": "linux-hardened-4.14.251-hardened1.patch", 5 - "sha256": "1yv4b10w1psaj4m4r9jicf6c3wkyvb040p7gbdf1455nrcxnxr06", 6 - "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.251-hardened1/linux-hardened-4.14.251-hardened1.patch" 3 + "patch": { 4 + "extra": "-hardened1", 5 + "name": "linux-hardened-4.14.252-hardened1.patch", 6 + "sha256": "1isqlqg4diz0i3f77rigvb07fs2p1v9w2h5165l0rnkb6h26i1gn", 7 + "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.14.252-hardened1/linux-hardened-4.14.252-hardened1.patch" 8 + }, 9 + "sha256": "022rw51s8fzz6wcxa9xq6h60fglfx0hq7bmqgs5dlrci6plv4fwk", 10 + "version": "4.14.252" 7 11 }, 8 12 "4.19": { 9 - "extra": "-hardened1", 10 - "name": "linux-hardened-4.19.212-hardened1.patch", 11 - "sha256": "1ildbzxzvkaziqiqlvw92pjmkd64hxdd9sn3fdq88q1pdw5x2jb3", 12 - "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.212-hardened1/linux-hardened-4.19.212-hardened1.patch" 13 + "patch": { 14 + "extra": "-hardened1", 15 + "name": "linux-hardened-4.19.213-hardened1.patch", 16 + "sha256": "03lk4m6sm3545s0xxx0w4sqgrsvrxqm8qg7swn05s36jj20viprm", 17 + "url": "https://github.com/anthraxx/linux-hardened/releases/download/4.19.213-hardened1/linux-hardened-4.19.213-hardened1.patch" 18 + }, 19 + "sha256": "162f5y3jplql3ca5xy889mq6izjinryx2kx16zp582yvsqf8rwiq", 20 + "version": "4.19.213" 13 21 }, 14 22 "5.10": { 15 - "extra": "-hardened1", 16 - "name": "linux-hardened-5.10.74-hardened1.patch", 17 - "sha256": "0prcrifz1zmjxv492dgd78h8bdsx4bh92dsbnp01nn1wmwbajp8p", 18 - "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.10.74-hardened1/linux-hardened-5.10.74-hardened1.patch" 23 + "patch": { 24 + "extra": "-hardened1", 25 + "name": "linux-hardened-5.10.75-hardened1.patch", 26 + "sha256": "17gm50aislxihfnmr4vi0p0gpg13m2pbldjpi81clnx93a7rrfw2", 27 + "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.10.75-hardened1/linux-hardened-5.10.75-hardened1.patch" 28 + }, 29 + "sha256": "0jrhhk89587caw54nhnwms93kq33qdm75x5f18cp61xrxxgjyaqa", 30 + "version": "5.10.75" 19 31 }, 20 32 "5.14": { 21 - "extra": "-hardened1", 22 - "name": "linux-hardened-5.14.13-hardened1.patch", 23 - "sha256": "01kxjn1sndby3fjfq3g7z0ydrk8nv62bvpvprddqqc3bypk9q7m2", 24 - "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.14.13-hardened1/linux-hardened-5.14.13-hardened1.patch" 33 + "patch": { 34 + "extra": "-hardened1", 35 + "name": "linux-hardened-5.14.14-hardened1.patch", 36 + "sha256": "1hx5yal8jqnxr9c9ikvc6d0xp99kqjarj67720v9d4wvlmgsfabj", 37 + "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.14.14-hardened1/linux-hardened-5.14.14-hardened1.patch" 38 + }, 39 + "sha256": "0snh17ah49wmfmazy6x42rhvl484h657y0iq4l09a885sjb4xzsd", 40 + "version": "5.14.14" 25 41 }, 26 42 "5.4": { 27 - "extra": "-hardened1", 28 - "name": "linux-hardened-5.4.154-hardened1.patch", 29 - "sha256": "0d7w27n3wq9jaq0wbf3iv2f0jb1y2v4k0c87rb6sakivwajxn1aw", 30 - "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.154-hardened1/linux-hardened-5.4.154-hardened1.patch" 43 + "patch": { 44 + "extra": "-hardened1", 45 + "name": "linux-hardened-5.4.155-hardened1.patch", 46 + "sha256": "0l8h9i6asiypgbxl90370kzfsyyc3f4vwl2r191arvrsgw863bid", 47 + "url": "https://github.com/anthraxx/linux-hardened/releases/download/5.4.155-hardened1/linux-hardened-5.4.155-hardened1.patch" 48 + }, 49 + "sha256": "0f2hfz76rnhmv99zhbh7n1z48316ilxrxrnh4b5m3lj84y80y36c", 50 + "version": "5.4.155" 31 51 } 32 52 }
+16 -3
pkgs/os-specific/linux/kernel/hardened/update.py
··· 31 31 Version = List[VersionComponent] 32 32 33 33 34 - Patch = TypedDict("Patch", {"name": str, "url": str, "sha256": str, "extra": str}) 34 + PatchData = TypedDict("PatchData", {"name": str, "url": str, "sha256": str, "extra": str}) 35 + Patch = TypedDict("Patch", { 36 + "patch": PatchData, 37 + "version": str, 38 + "sha256": str, 39 + }) 35 40 36 41 37 42 @dataclass ··· 133 138 if not sig_ok: 134 139 return None 135 140 136 - return Patch(name=patch_filename, url=patch_url, sha256=sha256, extra=extra) 141 + kernel_ver = release_info.release.tag_name.replace("-hardened1", "") 142 + major = kernel_ver.split('.')[0] 143 + sha256_kernel, _ = nix_prefetch_url(f"mirror://kernel/linux/kernel/v{major}.x/linux-{kernel_ver}.tar.xz") 144 + 145 + return Patch( 146 + patch=PatchData(name=patch_filename, url=patch_url, sha256=sha256, extra=extra), 147 + version=kernel_ver, 148 + sha256=sha256_kernel 149 + ) 137 150 138 151 139 152 def parse_version(version_str: str) -> Version: ··· 249 262 old_version_str: Optional[str] = None 250 263 update: bool 251 264 try: 252 - old_filename = patches[kernel_key]["name"] 265 + old_filename = patches[kernel_key]["patch"]["name"] 253 266 old_version_str = old_filename.replace("linux-hardened-", "").replace( 254 267 ".patch", "" 255 268 )
+2 -1
pkgs/os-specific/linux/kernel/patches.nix
··· 47 47 cpu-cgroup-v2 = import ./cpu-cgroup-v2-patches; 48 48 49 49 hardened = let 50 - mkPatch = kernelVersion: src: { 50 + mkPatch = kernelVersion: { version, sha256, patch }: let src = patch; in { 51 51 name = lib.removeSuffix ".patch" src.name; 52 52 patch = fetchurl (lib.filterAttrs (k: v: k != "extra") src); 53 53 extra = src.extra; 54 + inherit version sha256; 54 55 }; 55 56 patches = builtins.fromJSON (builtins.readFile ./hardened/patches.json); 56 57 in lib.mapAttrs mkPatch patches;
+16 -4
pkgs/top-level/linux-kernels.nix
··· 10 10 , stdenvNoCC 11 11 , newScope 12 12 , lib 13 + , fetchurl 13 14 }: 14 15 15 16 # When adding a kernel: ··· 26 27 27 28 # Hardened Linux 28 29 hardenedKernelFor = kernel': overrides: 29 - let kernel = kernel'.override overrides; 30 + let 31 + kernel = kernel'.override overrides; 32 + version = kernelPatches.hardened.${kernel.meta.branch}.version; 33 + major = lib.versions.major version; 34 + sha256 = kernelPatches.hardened.${kernel.meta.branch}.sha256; 35 + modDirVersion' = builtins.replaceStrings [ kernel.version ] [ version ] kernel.modDirVersion; 30 36 in kernel.override { 31 37 structuredExtraConfig = import ../os-specific/linux/kernel/hardened/config.nix { 32 - inherit lib; 33 - inherit (kernel) version; 38 + inherit lib version; 39 + }; 40 + argsOverride = { 41 + inherit version; 42 + src = fetchurl { 43 + url = "mirror://kernel/linux/kernel/v${major}.x/linux-${version}.tar.xz"; 44 + inherit sha256; 45 + }; 34 46 }; 35 47 kernelPatches = kernel.kernelPatches ++ [ 36 48 kernelPatches.hardened.${kernel.meta.branch} 37 49 ]; 38 - modDirVersionArg = kernel.modDirVersion + (kernelPatches.hardened.${kernel.meta.branch}).extra; 50 + modDirVersionArg = modDirVersion' + (kernelPatches.hardened.${kernel.meta.branch}).extra; 39 51 isHardened = true; 40 52 }; 41 53 in {