unshare -pf bash fails with operation not permitted without effective root. If I don't mount proc, mount ns is not needed. Is there any particular reason creating pid ns is not allowed?
This is indeed not allowed because it's a privileged operation:
CLONE_NEWPID(since Linux 3.8)
CAP_SYS_ADMINcapability. For further information, see pid_namespaces(7).
What can be done instead is first to unshare a user namespace (which is not a privileged operation). Then as mentioned in a comment, and documented in user_namespaces(7), unshare-ing an user namespace is enough to gain the
CAP_SYS_ADMIN within it at least until for example the next execve(), so it's not even needed to map to the root user here. Now from this new user namespace, the process can unshare a new pid namespace.
As described in pid_namespaces(7) only "the first child created by a process after a call to unshare(2) using the
CLONE_NEWPID flag" will actually be in the new pid namespace and "has pid 1". So the fork option isn't technically needed, but it's not very useful to not have it, because only the first child process will actually be in/start the new pid namespace (and a process like
bash not used as
bash --norc would fork processes and lose the one chance to run one of one's choice later)
$ unshare -U --map-user=$(id -u) --map-group=$(id -g) -f -p $ echo $$ 1
This requires a recent enough version of
unshare that has the relevant options. See note at the end when using an older version of
unshare lacking these options.
Mounting a new instance of
/proc reflecting the new pid namespace to actually see new pids instead of pids from parent namespace is also something that should be done:
$ ls -l /proc/$$/exe ls: cannot read symbolic link '/proc/1/exe': Permission denied lrwxrwxrwx 1 nobody nogroup 0 Sep 16 16:13 /proc/1/exe
As this requires mount privileges in the new namespace, this also requires to unshare a mount namespace first so the user namespace also gets privileges to perform new mounts in this new mount namespace. This still doesn't require to be root because (before the final fork and exec), the unshare process still got
CAP_SYS_ADMIN So in the end, this could be done for some usefulness:
$ unshare -U --map-user=$(id -u) --map-group=$(id -g) -m --mount-proc -f -p $ echo $$ 1 $ ls -l /proc/$$/exe lrwxrwxrwx 1 user user 0 Oct 8 21:49 /proc/1/exe -> /usr/bin/bash
Additional note: unsharing without mapping to root but mapping to the same user, when using an older version of the
unshare command lacking
--map-user can be done like this:
user@host$ echo $$; id -u; id -g; exec unshare -U -f -p 670034 1000 1000 nobody@host$ echo $$; id -u; id -g 1 65534 65534
then, this requires the usual help from an other process to write in the user mappings for the new user namespace (or possibly a recent version of the
unshare command to have done this in the first place). If this process isn't privileged (commands
newgidmap are setuid root so could set any mapping reserved for this user if needed) in the parent namespace, few choices are possible for useful mappings (usually root or the user itself).
other shell (still in parent namespaces):
user@host$ pstree -p 670034 unshare(670034)───bash(670638) user@host$ echo '1000 1000 1' > /proc/670034/uid_map user@host$ echo deny > /proc/670034/setgroups user@host$ echo '1000 1000 1' > /proc/670034/gid_map
first shell again:
nobody@host$ exec bash #for cosmetic effect user@host$ echo $$; id -u; id -g 1 1000 1000