Skip to content

Programs that manipulate ptys break under nix-user-chroot #74

Closed
@rrbutani

Description

@rrbutani

First off I just wanted to say thanks for this project; it's made it really easy to use nix as an unprivileged user and is an invaluable part of my setup.


This issue doesn't really detail a bug in nix-user-chroot so much as a use case it doesn't support. I don't really think there's anything nix-user-chroot can do about this but I'm also not very familiar with user namespaces; I'm posting this issue here in case I missed something/in case anyone has any other ideas. If this is deemed out of scope for nix-user-chroot by the maintainers, please feel free to close this issue.


While using nix-user-chroot I realized that I am unable to run applications that manipulate PTYs (I was trying to use the VSCode Remote Server but I'm fairly certain this affects anything that interacts with /dev/pts; i.e. running nix-user-chroot ~/.nix screen also fails for me). Poking around a bit with strace and friends revealed that calls to forkpty in glibc ultimately try to chgrp the pts that's created to the tty group which fails inside the chroot.

This is because there is no tty group inside the namespace that nix-user-chroot sets up, only the user's UID and GID are mapped in. As far as I can tell there is no way to map in additional groups without special permissions (we're locked out of calling setgroups and mapping in gids other than the users' requires the parent process of the namespace to have CAP_SETGID, I think).

Other approaches (including mounting in a new devpts in the namespace and patching glibc to not attempt the chgrp in this case) all either don't work or seem too intrusive.

Ultimately, I ended up writing a nix overlay that "wraps" binaries in a shell script that enters the chroot if called from outside of it. This, plus a little bit of glue to make it so that all the wrappers land in the same single directory so there's something symlink-free to add to $PATH, satisfies my particular use case (instead of running the remote server inside the chroot, I just have the binaries that it calls enter the chroot themselves as needed) but feels very unsatisfying.

Does anyone know if there's a more proper way to get around this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions