Unverified Commit 7ceda3c5 authored by Janne Heß's avatar Janne Heß Committed by GitHub
Browse files

Merge pull request #306790 from...

Merge pull request #306790 from roberth/fix-nixos-kernelPackages-kernel-version-kernelPatches-recursion

kernel: Fix infinite recursion between version and patches
parents e6c5e246 debe5277
Loading
Loading
Loading
Loading
+47 −5
Original line number Diff line number Diff line
@@ -12,9 +12,13 @@
, rustc
, rustPlatform
, rust-bindgen
# testing
, emptyFile
, nixos
, nixosTests
}@args':

let overridableKernel =
lib.makeOverridable ({ # The kernel source tarball.
  src

@@ -211,11 +215,15 @@ let
  }; # end of configfile derivation

  kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) (basicArgs // {
    inherit kernelPatches randstructSeed extraMakeFlags extraMeta configfile;
    inherit kernelPatches randstructSeed extraMakeFlags extraMeta configfile modDirVersion;
    pos = builtins.unsafeGetAttrPos "version" args;

    config = { CONFIG_MODULES = "y"; CONFIG_FW_LOADER = "m"; } // lib.optionalAttrs withRust { CONFIG_RUST = "y"; };
  } // lib.optionalAttrs (modDirVersion != null) { inherit modDirVersion; });
    config = {
      CONFIG_MODULES = "y";
      CONFIG_FW_LOADER = "m";
      CONFIG_RUST = lib.mkIf withRust "y";
    };
  });

in
kernel.overrideAttrs (finalAttrs: previousAttrs: {
@@ -241,7 +249,41 @@ kernel.overrideAttrs (finalAttrs: previousAttrs: {
            + toString (lib.attrNames (lib.toFunction args { }))
          ) overridableKernel;
      };
    in [ (nixosTests.kernel-generic.passthru.testsForKernel overridableKernel) ] ++ kernelTests;
      /* Certain arguments must be evaluated lazily; so that only the output(s) depend on them.
         Original reproducer / simplified use case:
       */
      versionDoesNotDependOnPatchesEtcNixOS =
        builtins.seq
          (nixos ({ config, pkgs, ... }: {
              boot.kernelPatches = [
                (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; })
              ];
          })).config.boot.kernelPackages.kernel.outPath
          emptyFile;
      versionDoesNotDependOnPatchesEtc =
        builtins.seq
          (import ./generic.nix args' (args // (
          let explain = attrName:
            ''
              The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion.
              That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument.
              The fact that this exception is raised shows that such a dependency does exist.
              This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS.
              Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked.
            '';
          in {
            kernelPatches = throw (explain "kernelPatches");
            structuredExtraConfig = throw (explain "structuredExtraConfig");
            modDirVersion = throw (explain "modDirVersion");
          }))).version
          emptyFile;
    in [
      (nixosTests.kernel-generic.passthru.testsForKernel overridableKernel)
      versionDoesNotDependOnPatchesEtc
      # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace.
      # versionDoesNotDependOnPatchesEtcNixOS
    ] ++ kernelTests;
  };

}))
}));
in overridableKernel
+8 −1
Original line number Diff line number Diff line
@@ -26,7 +26,7 @@ in lib.makeOverridable ({
  extraMakeFlags ? [],
  # The name of the kernel module directory
  # Needs to be X.Y.Z[-extra], so pad with zeros if needed.
  modDirVersion ? lib.versions.pad 3 version,
  modDirVersion ? null /* derive from version */,
  # The kernel source (tarball, git checkout, etc.)
  src,
  # a list of { name=..., patch=..., extraConfig=...} patches
@@ -54,6 +54,13 @@ in lib.makeOverridable ({
}:

let
  # Provide defaults. Note that we support `null` so that callers don't need to use optionalAttrs,
  # which can lead to unnecessary strictness and infinite recursions.
  modDirVersion_ = if modDirVersion == null then lib.versions.pad 3 version else modDirVersion;
in
let
  # Shadow the un-defaulted parameter; don't want null.
  modDirVersion = modDirVersion_;
  inherit (lib)
    hasAttr getAttr optional optionals optionalString optionalAttrs maintainers platforms;