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

Accept strings with Nix paths as proper shells #24786

Closed
wants to merge 3 commits into from

Conversation

abbradar
Copy link
Member

@abbradar abbradar commented Apr 9, 2017

Motivation for this change

I have a special user account on a server for the sole purpose of playing NetHack. It's forced (via SSH's ForceCommand and extraUsers.*.shell) to run special script (writeScript) which execs the game, so the only thing one can do after he/she logs in to the account is to play the game. Without this patch you can't use any such custom script as the shell because it detects that it's in Nix store, "reverses" derivation from it and fails to find needed attributes. This makes shellPackage to require a derivation and fixes toShellPath so that such paths are accepted.

Things done
  • Tested using sandboxing
    (nix.useSandbox on NixOS,
    or option build-use-sandbox in nix.conf
    on non-NixOS)
  • Built on platform(s)
    • NixOS
    • macOS
    • Linux
  • Tested compilation of all pkgs that depend on this change using nix-shell -p nox --run "nox-review wip"
  • Tested execution of all binary files (usually in ./result/bin/)
  • Fits CONTRIBUTING.md.

@mention-bot
Copy link

@abbradar, thanks for your PR! By analyzing the history of the files in this pull request, we identified @edolstra, @ericsagnes and @nbp to be potential reviewers.

@abbradar abbradar changed the title Accept strings with Nix paths as proper shells. Accept strings with Nix paths as proper shells Apr 9, 2017
@nbp
Copy link
Member

nbp commented Apr 10, 2017

@abbradar , I am not sure to understand the use case, can you provide an example.

@abbradar
Copy link
Member Author

abbradar commented Apr 10, 2017

@nbp shell = toString (writeScript "foo" "....");. toString is needed because writeScript is not a "shell" derivation (it doesn't have shellPath attribute), so I need to indicate that I know what I'm doing. Without the patch even this is not possible, although type of users.extraUsers.*.shell (either shellPackage path) indicates as if it should be.

More elaborated, it doesn't work now because:

  • shellPackage.check = x: (package.check x) && (hasAttr "shellPath" x) doesn't behave well with strings-paths from Nix store: it gets true from package.check and then throws on hasAttr. Instead I now only allow proper derivations as shellPackages;
  • Similarly, toShellPath won't work because shellPath returns false but package returns true for such string so we get an exception again.

@nbp
Copy link
Member

nbp commented Apr 10, 2017

Would the following work:
shell = writeScriptBin "foo" "...." // { shellPath = "/bin/foo"; };

@abbradar
Copy link
Member Author

It should but either type still feels broken there (one can specify non-Nix store string "path" but not a Nix-store "path").

@nbp
Copy link
Member

nbp commented Apr 10, 2017

I actually have a similar use case in one of my configuration files:

  users.extraUsers.git = {
    uid = config.ids.uids.git;
    group = "git";
    description = "Git User";
    home = "/home/git";
    createHome = true;
    shell = pkgs.git + "/bin/git-shell";
    openssh.authorizedKeys.keyFiles = [ ...
      ./nicolas.computer.pub
    ];
  };

@nbp
Copy link
Member

nbp commented Apr 10, 2017

I think the proper reviewer for these changes should be @zimbatm

@abbradar
Copy link
Member Author

Hm, it's interesting that it works for your configuration without those patches. I'll look into this, maybe there's something deeper going on...

@nbp
Copy link
Member

nbp commented Apr 10, 2017

The shell option has the type

types.either types.shellPackage types.path;

Thus in my case, I get a nix-store path which is validated by the types.path.check function, while without the toString in front of the writeScript function call, this is not a valid path.

I see that multiple locations have the same type with either a shellPackage or a path. 2 things we can do:

  • writeScript should add a shellPath attribute instead.
  • we should include the path.check in the shellPackage.check function, and get rid of all these either cases.

@zimbatm
Copy link
Member

zimbatm commented Apr 10, 2017

the path type was to preserve legacy usage. if you have a better approach I'm all for it

@abbradar
Copy link
Member Author

@nbp Ah, I get it now, isStorePath is false for files/subdirectories in Nix path -- so it works for you with /bin but not for me with a plain path.

I'm for option (2) -- I'll look at implementing it somewhere this week.

@nbp
Copy link
Member

nbp commented Apr 11, 2017

Option (2) is just a clean-up, and not a solution, it would not solve the problem you are facing. Option (1) is from what I understand the proper way to fix this issue.

@abbradar
Copy link
Member Author

Hm, this seems a wrong place to fix the problem to me because I feel that either shellPackage path should, by its definition, allow any path-like string, and instead it just throws an exception in shellPackage.check.

@nbp
Copy link
Member

nbp commented Apr 11, 2017

having a shellPath attribute provided by writeScript makes total sense to me, as you are making a script, having its destination known by the user through the shellPath attribute or any other sounds reasonable.

@abbradar
Copy link
Member Author

@nbp That's okay, what I mean is that either the type should be shellPackage and shellPath should be required everywhere, or (if the type is left as is) arbitrary paths should be allowed, as in the type. And under no circumstances should check throw!

@abbradar
Copy link
Member Author

So, do we agree that shellPackage.check shouldn't throw? I propose fixing it so that it accepts only derivations with shellPath (that's the first patch) and then decide if shell option should accept arbitrary paths.

@nbp
Copy link
Member

nbp commented Apr 14, 2017

do we agree that shellPackage.check shouldn't throw?

Yes the check fucntion should in not throw, because we have other mechanism to report proper error messages on type failures.

@@ -21,8 +21,8 @@ rec {
toShellPath = shell:
if types.shellPackage.check shell then
"/run/current-system/sw${shell.shellPath}"
else if types.package.check shell then
throw "${shell} is not a shell package"
else if isString shell && types.path.check shell then
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need isString when we have types.path.check here? Also, the type of the shell option is either shellPackage path, so we know that both test are correct.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path accepts not only strings, but also derivations. Here we have already filtered derivations with shellPath defined (shellPackage.check shell == true), so now we want to handle strings that are also valid paths (start with /), but not derivations. We'll then throw on them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that I think of it the proper way here might be to refine the type instead so that it accepts only string paths or shellPackages.

@abbradar
Copy link
Member Author

I've made a new version; we now have a separate type stringPath which accepts only strings -- this way the code and my intent is much more clear.

@abbradar
Copy link
Member Author

abbradar commented May 24, 2017

I'm working on a third version of this patch and wonder -- why do we need to install shells globally? What is the downside of using direct Nix store paths?

@zimbatm
Copy link
Member

zimbatm commented May 25, 2017

It comes from /etc/shells (man 5 shells) that is supposed to contain the list of all authorised shells. Historically I think that it was introduced for chsh but it's possible other tools are also depending on it.

@abbradar
Copy link
Member Author

Ah, then it means that using shells which are not installed in system environment is a bad idea anyway! Then this PR is a bad idea as it is too -- let's close it. I'll document that shells need stable paths somewhere in comments later.

@abbradar abbradar closed this May 31, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants