3

I run unshare -r touch file. However, unshare -r chown nobody file gives me Invalid argument. Why?

2 Answers2

3

Once a new user namespace is created, to "complete" this, UID and GID mappings must be done, once and for all.

The initial user, if unprivileged, is allowed to do this mapping, but can only map itself in the new user namespace: that means only one UID and one GID can be mapped without privilege.

In this restricted case, only two users in the new user namespace are interesting candidates for this single user mapping: either root, to gain privileges including related with other associated namespaces (eg: network or mount), or itself (typically with multi-layers user namespaces: initial (john) -> userns1 (root) -> userns2 (john again) ). So usually root is chosen (that's what the -r option is doing).

Among root privileges there are those related to changing or affecting UID, for processes, files... But in this new user namespace, all other UID beside the one chosen: 0 for root, are not mapped. They are mapped as (the overflow UID) nobody (65534) and any attempt to alter or change them results in EINVAL (Invalid argument). That's different from EPERM (Operation not permitted) which would be the result of the same operation from the unprivileged user in the initial user namespace. But the overall goal is the same: no way to gain privilege or access on the host (initial namespace...) by trying to cheat with the use of an user namespace.

If you have to work with multiple UIDs in a namespace created by an unprivileged user, you must use a privileged helper. One such helper is ubiquitous and a prerequisite for containers technology (Docker, LXC ...) when used with an unprivileged user: newuidmap (and its companion newgidmap). This tool is setuid-root (it would need at least CAP_SETUID but probably some others are needed) and can grant the new user namespace with a whole mapping range from per-user entry in /etc/subuid//etc/subgid in addition to the user itself.

More details can be found in this Q/A: Can subordinate user ID be used to grant file system permissions?

A.B
  • 31,762
  • 2
  • 62
  • 101
  • Thanks for the answer! Just a few questions: 1. Let's say my `unshare` command is short lived (for example, an `ls`). How can `newuidmap` act on it fast enough (given that you need the PID ahead of time), unless you mean that you call newuidmap within the namespace? 2. Is there a way to use newuidmap without needing to write to `/etc/subuid`, like some sort of temporary file? 3. I've looked at the man pages for both of the tools; however, I still don't understand what `uid` and `loweruid` would mean in this context. Could you give an example of usage? – DrownedSuccess Jul 27 '22 at 17:24
  • you can use this construct: shell 1: `unshare --user -- sh -c 'echo $$; sleep 10; exec ls'` . You have 10 seconds to run newuidmap on a 2nd shell. Of course this should be automated in a better way. – A.B Jul 27 '22 at 17:45
  • It wouldn't work if you also unshared the pid namespace. Anyway, I think this LXC tool (which doesn't require using LXC) can do about what you want: [lxc-usernsexec](https://manpages.debian.org/lxc/lxc-usernsexec.1#m) . It relies on `newuidmap`/`newgidmap` as helper. – A.B Jul 27 '22 at 18:10
  • and answer to 2/ the configuration used by a setuid-root tool must be in control of the root account. If you can provide your custom configuration you could gain privileges by the help of this tool actually run as root. 3/ Example usages can be found in my linked Q/A at the end of the answer and in the linked [`lxc-usernsexec`](https://manpages.debian.org/lxc/lxc-usernsexec.1) command man. Of course the reference is in [`user_namespaces(7)`](https://manpages.debian.org/manpages/user_namespaces.7#Unmapped_user_and_group_IDs). – A.B Jul 27 '22 at 18:23
  • After some debugging, it works. However, on the host namespace, I can't access the outer uids (eg, if UID 19000 on the host is mapped to 19 in the namespace, while I can access UID 19 in the namespace, I can't access files owned by UID 19000 in the host). – DrownedSuccess Aug 12 '22 at 17:38
  • That's to be expected: no special privilege on the host. You have to use a namespace. You can make some wrapper if you have to use this often. – A.B Aug 12 '22 at 21:49
  • I tried to run a FUSE process in a user namespace where it is root, but it failed with `fusermount3: mount failed: Operation not permitted`. – DrownedSuccess Aug 13 '22 at 12:42
  • I more than answered your initial question. Sorry can't debug all your further attempts at doing something that goes further than what was asked. I guess that when a kernel module is involved (fuse), it's not very clear how namespace behaves. – A.B Aug 13 '22 at 12:50
  • Ok, thanks for all your help so far. – DrownedSuccess Aug 13 '22 at 13:27
2

Only root can change ownership to another user. With unshare -r you will become root, but only in your own namespace

~$ unshare -r touch /tmp/foo
~$ unshare -r ls -l  /tmp/foo
-rw-r--r-- 1 root root 0 27. Jul 14:20 /tmp/foo
~$  ls -l  /tmp/foo
-rw-r--r-- 1 user user 0 27. Jul 14:20 /tmp/foo

Since an chown in the namespace would tamper with the file system in the "real" namespace this is prevented.

Harry
  • 194
  • 4