Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findEnabled can cause infinite recursion #392

Closed
scottbot95 opened this issue Oct 2, 2023 · 1 comment
Closed

findEnabled can cause infinite recursion #392

scottbot95 opened this issue Oct 2, 2023 · 1 comment

Comments

@scottbot95
Copy link
Contributor

scottbot95 commented Oct 2, 2023

Description

findEnabled will attempt to recurse through all attributes in the provided tree until it finds an attribute set that contains { enabled = true; } in each of the branches. This works in the "normal" case when it it used on a configuration like:

services.ethereum.geth.sepolia = {
    enable = true;
    ...
  };

  services.ethereum.geth.goerli = {
    enable = true;
    ...
  };

However if you disable any of the "top level" services, things start to break down. Since all services contain a package option, findEnabled will attempt to recurse into the derivation itself which will result in an infinite recursion as derivations always contain a reference to themselves (out). Additionally, since findEnabled is now searching deeper than it was actually intended for, it may now come across submodules that are enabled (such as geth.<name>.args.http.enable or even geth.<name>.backup.enable) despite the fact that they won't actually do anything since the outer module is disabled. This can result in additional evaluation errors as bad data is being fed into the backup/restore modules.

Steps to reproduce

  1. Attempt to evaluate a module containing:
services.ethereum.geth.sepolia = {
    enable = false;
    backup = {
      enable = false; # not respected since findEnabled gets confused by get service being disabled
      restic.passwordFile = ""; # needed since backup/restore modules think backup/restore is enabled
    };
    restore = {
      enable = false; # not respected since findEnabled gets confused by get service being disabled
      restic.passwordFile = ""; # needed since backup/restore modules think backup/restore is enabled
      snapshot = ""; # needed since backup/restore modules think backup/restore is enabled
    };
};
  1. Observe infinite recursion

Proposed solution

Modify findEnabled so that it only recurses if the current attribute set does not contain the enabled attribute regardless of its value. We still only add to sum if enabled == true, however for the case when enabled is present but false, we will consider that branch done and stop recursing. This will avoid us searching deeper than was intended which resulted in the bugs highlighted above.

scottbot95 added a commit to scottbot95/ethereum.nix that referenced this issue Oct 2, 2023
scottbot95 added a commit to scottbot95/ethereum.nix that referenced this issue Oct 2, 2023
@scottbot95 scottbot95 mentioned this issue Oct 2, 2023
@aldoborrero
Copy link
Collaborator

@scottbot95 good find. Also, we could add additional safeguards and only recurse if is not a derivation to avoid issues like you described before (with builtins.isDerivation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants