unshare icon indicating copy to clipboard operation
unshare copied to clipboard

Configure uid/gid maps from child and not parent

Open pr2502 opened this issue 3 years ago • 3 comments

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

pr2502 avatar Apr 02 '21 23:04 pr2502

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?

tailhook avatar Apr 05 '21 10:04 tailhook

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.

pr2502 avatar Apr 05 '21 10:04 pr2502

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.

fogti avatar Dec 02 '21 22:12 fogti