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

Configure uid/gid maps from child and not parent #23

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

pr2502
Copy link

@pr2502 pr2502 commented Apr 2, 2021

Hello, I've been trying to implement a tool based on this library which shares some functionality with the unshare utility from util-linux and noticed a problem where mapping UIDs and GIDs requires root permission with this library but not with the unshare utility.

In this PR I've changed the UID/GID mapping logic to mimick the unshare utility, I tried to do it in a way which affects the rest of the library the least but it may break some invariants I'm just not aware of. Do you think this a viable approach? Thank you

@tailhook
Copy link
Owner

tailhook commented Apr 5, 2021

Hm.. I've always thought that you have either have root permissions or use newuidmap/newgidmap (which are setuid binaries) to adjust mappings. So I have to investigate whether something changed in the recent kernels or I'm missing something else. If this actually works in all desired scenarios, surely we can apply PR.

But I'm not even sure how does it work logically. Do you say that unprivileged user can adjust their uid/gid mappings freely? Do you create a new user namespace in this call, or spawning a process in the same one?

@pr2502
Copy link
Author

pr2502 commented Apr 5, 2021

This might help, the manpage for unshare the section about --setgroups says:

--setgroups allow|deny

Allow or deny the setgroups(2) system call in a user namespace.

To be able to call setgroups(2), the calling process must at least have CAP_SETGID. But since Linux 3.19 a further restriction applies: the kernel gives permission to call setgroups(2) only after the GID map (/proc/pid/gid_map) has been set. The GID map is writable by root when setgroups(2) is enabled (i.e., allow, the default), and the GID map becomes writable by unprivileged processes when setgroups(2) is permanently disabled (with deny).

One problem I've come across is that using this I was unable remove the list of auxiliary groups. I've tried creating a trivial chroot environment with nothing else but static busybox at $CHROOT/bin/id and then running strace unshare -r -R $CHROOT /bin/id, what I've implemented here is just mimicking it's behaviour. The id command prints uid=0 gid=0 groups=65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,65534,0,65534,65534 so it masks the auxiliary groups to some nonsense but matches the number on the host system. Using the groups method in combination with this setgroups returns invalid argument error, which makes sense. It'd be great if some reordering of the operations could fix that but I haven't managed that yet.

@fogti
Copy link

fogti commented Dec 2, 2021

masks the auxiliary groups to some nonsense

to be clear (as I already know this behavoir from the nix sandbox), it masks the auxiliary groups to nogroup with the kernel-hardcoded gid 65534.
The simple way to prevent it is by making sure that the user which opens the sandbox isn't in any groups.

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

Successfully merging this pull request may close these issues.

3 participants