This article is a follow-up on the one about network namespaces, yeah, 2 years later.
User namespaces allow per-namespace mappings of user and group IDs. Imagine, a process, unprivileged for operations outside the user namespace, but with root privileges inside the namespace.
Can we have an example please?
First, we open a terminal, we print the current process ID and the process owner:
~ >> echo $$ # print process ID 5955 ~ >> id # print process owner uid=1000(nsukami) gid=1000(nsukami) groupes=1000(nsukami),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),129(sambashare),138(lxd),999(docker) ~ >>
Then, we start a new shell, we create another process. We can see the child process ID is different from the previous one, the parent process ID. But the process owner is still the same:
~ >> bash # start a new shell ~ >> echo $$ # print process ID 7637 ~ >> id # print process owner uid=1000(nsukami) gid=1000(nsukami) groupes=1000(nsukami),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),120(lpadmin),129(sambashare),138(lxd),999(docker) ~ >>
exit, we're back to the parent shell. Now, let's start a new shell with a different user namespace, using the unshare command:
unshare - run program with some namespaces unshared from parent
>> exit exit ~ >> echo $$ 5955 ~ >> unshare -U bash # start a new shell with a different user namespace ~ >> echo $$ 7747 ~ >> id # we are nobody uid=65534(nobody) gid=65534(nogroup) groupes=65534(nogroup) ~ >>
Where does the 65534 come from?
Again, from the Unmapped user and group IDs section inside user_namespaces(7) documation we can read:
There are various places where an unmapped user ID (group ID) may be exposed to user space. For example, the first process in a new user namespace may call getuid(2) before a user ID mapping has been defined for the namespace. In most such cases, an unmapped user ID is converted to the overflow user ID (group ID); the default value for the overflow user ID (group ID) is 65534. See the descriptions of /proc/sys/kernel/overflowuid and /proc/sys/kernel/overflowgid in proc(5).
~ root# cat /proc/sys/kernel/overflowuid 65534 ~ root# cat /proc/sys/kernel/overflowgid 65534 ~ root#
Can we define our own ID mapping?
First, inside our user namespace, the uid is 65534:
Then, inside another terminal, we define the association of userid 0 inside the user namespace with uid 1000 outside the user namespace:
Finally, we can verify, the uid has been updated, according to our mapping
All right. Why are we talking about those things?
Because LXD containers
~ root# cat /etc/subuid nsukami:100000:65536 lxd:165536:65536 root:165536:65536 lxd:1000:1 # mapping uid 0 inside the container to uid 1000 outside the container root:1000:1 ~ root# cat /etc/subgid nsukami:100000:65536 lxd:165536:65536 root:165536:65536 lxd:1000:1 root:1000:1 ~ root#
Any concrete and interesting use case?
I was reading Jessie Frazelle article about running inside Docker containers.
More on the topic
Thanks a lot for reading. Let's hope I won't write about mount namespaces on 2020. But before that, I strongly recommend the following links:
- user_namespaces - overview of Linux user namespaces
- unshare - disassociate parts of the process execution context
- newuidmap - set the uid mapping of a user namespace
"God gave us the gift of life; it is up to us to give ourselves the gift of living well." – Voltaire