This article is a follow-up on the one about network namespaces, yeah, 2 years later.

Introduction:

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.

Tar format
Source


Can we have an example please?

Of course...

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)
~
>>


After an 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:

newuidmap


Then, inside another terminal, we define the association of userid 0 inside the user namespace with uid 1000 outside the user namespace:

newuidmap


Finally, we can verify, the uid has been updated, according to our mapping

newuidmap


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:





Unexpected Quote:

"God gave us the gift of life; it is up to us to give ourselves the gift of living well." – Voltaire