Podman uid mapping and podman user namespaces

UID mapping and user namespaces will come into picture when we are running a rootless container. In this article, we will see how podman uid mapping really works, and on what basis the uid mapping happens
This article can be considered as a continuation of the podman rootless container introduction article, so consider go through the rootless container article, for better understanding.

We will do one exercise for understanding the uid mapping, and it starts by running a rootless container.

  • Lets run a rootless container, for doing this, start a container with a non-root user, in my case user abhi
[root@localhost ~]# su abhi
[abhi@localhost root]$ whoami
abhi
[abhi@localhost root]$ id
uid=1001(abhi) gid=1001(abhi) groups=1001(abhi),0(root),10(wheel) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
[abhi@localhost root]$ podman run -it centos sh
sh-4.4# id
uid=0(root) gid=0(root) groups=0(root)
  • When we inspect the user inside the container we can see that, the user is root even though the container is started by a non-root user
  • From the container's point of view, it will be running as a root user
  • Run some process and verify its behavior from containers point of view and host point of view
#Execute on container
sh-4.4# sleep 2130 &
[1] 41
sh-4.4# hostname
7c622daca98c
sh-4.4# ps -ef|grep 2130
root 41 1 0 06:06 pts/0 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2130
root 43 1 0 06:06 pts/0 00:00:00 grep 2130
  • From the containers point of view , the sleep processes is running with root user
#Execute on host
[abhi@localhost root]$ ps -ef|grep 2130
abhi 61765 48256 0 11:36 pts/0 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 2130
abhi 61824 48176 0 11:42 pts/1 00:00:00 grep --color=auto 2130
  • From the above code snippet, it can be seen that, from host point of view the process which is started inside the container is running as user abhi. It should be noted that with this same user only we have started our container also
  • As continuation of this exercise lets create one user inside the container and lets run the a sample process and see its behavior
#Execute on container
sh-4.4# useradd -u 5000 justin
sh-4.4# su - justin
[justin@7c622daca98c ~]$ sleep 5600 &
[1] 35
[justin@7c622daca98c ~]$ ps -ef|grep 5600
justin 35 18 0 04:06 pts/0 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5600
  • From the above code snippet, it can be seen that, a user justin is created with uid 5000 and with user justin a sleep process is created
  • While analyzing the sleep process, it can be seen that from container's point of view, the process is running by user justin
  • Lets verify from host point of view, how the sleep 5600 is running
#Execute on host
[abhi@localhost root]$ ps -ef|grep sleep
170535 48459 48425 0 09:36 pts/0 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5600
abhi 48462 48176 0 09:36 pts/1 00:00:00 grep --color=auto sleep
  • From host point of view, process is running with a uid of 170535. But How the uid of user justin (5000) become 170535 ?

How Container to Host UID mapping works ?

User namespaces are feature in linux, that allow user accounts to be isolated in namespaces and allow for processes to have different uid and gid numbers inside and outside of the user namespace. This is what actually happening for the user justin in our above example

  • For viewing the namespaces which are accessible to the container, we can execute lsns -t user command
#Execute on host
sh-4.4# lsns -t user
NS                TYPE NPROCS PID USER COMMAND
4026532381 user     2           1   root     sh
  • The user namespace 4026532381 was automatically created when we the container was created by the podman
  • When we analyze the same command from the host machine, we can see that the host user abhi have access to two namespaces, one of which is the container namespace itself. The second namespace is of the user abhi itself
[abhi@localhost root]$ lsns -t user
NS                TYPE  NPROCS PID    USER COMMAND
4026531837 user     2         48176  abhi   bash
4026532381 user   10         20219 abhi    catatonit -P
  • The subuid or subordinate uid  which a user is permitted to use in a user namespace is available in the /etc/subuid file and gid is present in /etc/subgid file
  • The content of the subuid and subgid file for my machine is as follows
[abhi@localhost root]$ cat /etc/subuid
linuxdatahub:100000:65536
abhi:165536:65536
[abhi@localhost root]$ cat /etc/subgid
linuxdatahub:100000:65536
abhi:165536:65536
  • By default when a user is created, in RHEL 8 a range of 65536 sub ordinate uid is assigned to it
  • Below the syntax of the entry in subuid file. First entry is username, second entry is the starting of the uid series and third entry will be number of sub uids that the usernamespace can allow. In other words we can say that the user abhi is having sub oridinate uid range of 165536 to 165536+65536-1=231071 (-1 is there since, the number itself is having one count)

Podman uid mapping and podman user namespaces

  • For a new user, a new entry will get automatically added in /etc/subuid and /etc/subgid. The starting uid will be the end of the previous users sub uid range
  • A new user test is added, when we inspect the subuid file. It can be seen that a range of 65536 subuid is getting added. So now the starting uid will be 231072 
[abhi@localhost root]$ cat /etc/subuid
linuxdatahub:100000:65536
abhi:165536:65536
test:231072:65536
[abhi@localhost root]$ cat /etc/subgid
linuxdatahub:100000:65536
abhi:165536:65536
test:231072:65536
  • Login back to the rootless container which we have created in the beginning of this exercise. We will see the content of the /proc/1/uid_map file
  • proc/1/uid_map will have the uid map for the process with pid 1
  • When podman creates a container, it sets the uid_map  based on the content of  /etc/subuid. Below is the content of the uid_map for my container
sh-4.4# cat /proc/1/uid_map
0 1001 1
1 165536 65536
  • Format of the uid_map is shown below

Podman uid mapping and podman user namespaces

  • The uid 0 in the container is mapped to the uid 1000 in the host, and length of the uid is 1, which indicates that this is for single user (abhi). In short root user inside the container is mapped as user abhi (uid 1000) in the host which started the rootless container
  • second line of the uid_map file shows the there is 65536 uids that are mapped starting from  uid 1 in the container to 165536 uid in the host. Below screen snippet shows the complete mapping

Podman uid mapping and podman user namespaces

  • Lets add a new user justin with a uid of  5000 and lets start a process with user justin. Below code snippet shows the same
sh-4.4# useradd -u 5000 justin
sh-4.4# su - justin
[justin@7c622daca98c ~]$ sleep 5600 &
[1] 35
[justin@7c622daca98c ~]$ ps -ef
UID PID PPID C STIME TTY TIME CMD
justin 18 17 0 04:04 pts/0 00:00:00 -bash
justin 35 18 0 04:06 pts/0 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5600
  • It can be seen that from containers point of view, the process is started with user justin who is having uid of 5000
  • Now lets check the same user from the host point of view. But before that lets calculate the host uid number based on the uid_map file
  • Below can be considered as the equation for calculating the hostuid. We are substracting 1, as the container starts and runs with id of 1
Host UID =starting uid within the container  + container uid -1
170535= 165536+5000 -1
  • Upon inspecting the uid in the host machine, we could see that our calculation of the host uid was correct
[abhi@localhost root]$ ps -ef|grep sleep
170535 48459 48425 0 09:36 pts/0 00:00:00 /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 5600
  • Inorder to get a complete mapping of the user between the host and the container, we can user podman top command
[abhi@localhost root]$ podman top 7c622daca98c user huser args
USER HUSER COMMAND
root   1001     sh
tom   172535   /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 780
root   1001     su justin
justin 170535 bash
justin 170535  /usr/bin/coreutils --coreutils-prog-shebang=sleep /usr/bin/sleep 3400
  • From the above code snippet, it can be seen that first column USER shows the user inside the container, and the second column "HUSER" will show the user for the same process from host

Search on LinuxDataHub

Leave a Comment