0

Which command (available in distro repositories) should I use start a shell with specified numeric uid, gid and groups? Typically su is used to change from root to other user, but it tries to look up groups by names, which may not exist when external filesystems, namespaces and Docker containers are in use.

I expect it to be a simple app that just does setgroups(2), setgid(2), setuid(2) and execve(2), without any /etc/passwd or nsswitch. It is easy to implement such a program in C, but maybe something standard and distro-available is used for this use case?

Vi.
  • 5,528
  • 7
  • 34
  • 68
  • Since you tagged this with [tag:sudo], note that `sudo` can handle numeric UIDs and GIDs, just prefix them with a `#`, e.g. `sudo -u \#1000 -g #1001`. Unfortunately it can't set secondary groups (they're set to whatever the target user has, I guess) – muru May 03 '22 at 23:07
  • @muru, `sudo: unknown user: #12345` - it is not `/etc/passwd`-independent. `[sudo]` is included because of `sudo` is also a tool that is related to switching users. – Vi. May 04 '22 at 06:42
  • What language. I was about to answer for `C`, but then you said that is easy. If it for shell? – ctrl-alt-delor May 04 '22 at 09:06

3 Answers3

1

As an alternative:

setpriv

cd /; setpriv --reuid=1000 --regid=1000 --init-groups --reset-env bash

Clean and simple

0

chroot

chroot --userspec=1000:1000 --groups=1001,1002 / /bin/bash

Chroot has --userspec and --groups option and is typically available in distros. Setting target directory to / renders the main purpose of chroot nil, but uid/gid/groups overriding effect is still in place.

Vi.
  • 5,528
  • 7
  • 34
  • 68
0

If you have Perl, and only care about the UIDs and GIDs it's relatively simple to do this:

# perl -e '$( = 456; $) = "456 1111 2222"; $< = $> = 123; exec("id")'
uid=123 gid=456 groups=456,1111,2222

$( and $) are the real and effective GID; and $< and $> the real and effective UID (in this order). $) can take a string representing multiple numbers, it'll set the supplementary groups too. (To clear the list of those, set the primary GID twice, e.g. $) = "456 456")

Or, in English:

# perl -MEnglish -e '$GID = 456; $EGID = "456 1111 2222"; $EUID = $UID = 123; exec("id")'
uid=123 gid=456 groups=456,1111,2222

You could also use POSIX::set[gu]uid() and of course you should check $! after modifications to the special variables to check for errors. The above would silently fail if you don't have the rights to change your groups or UID.

ilkkachu
  • 133,243
  • 15
  • 236
  • 397