# Use UTS (Unix-Time Sharing) to build a container ###### tags: `linux`, `container` OS: Ubuntu 20.04 LTS This is just playing around the UTS with unshare command on Ubuntu. I am not fully understand details and still have to further study. Namespaces allows partition of kernel resource such that one set of resources can be seem by one set of processes. UTS namespace allows for the segregation of hostnames. This help containers to have own specific hostname which make to identify containers. There are several type namespaces common used. - Process isolation (pid namespace) - Network interface (net namespace) - Unix timesharing system (uts namespace) - User namespace - Mount (mnt namespace) - Interprocess communication (IPC, share memory) - Cgroups #### initial check ``` root@ubuntu:~# hostname ubuntu ``` ``` root@ubuntu:~# df Filesystem 1K-blocks Used Available Use% Mounted on udev 970656 0 970656 0% /dev tmpfs 203088 988 202100 1% /run /dev/vda2 16445308 6358200 9232020 41% / tmpfs 1015436 0 1015436 0% /dev/shm tmpfs 5120 0 5120 0% /run/lock tmpfs 1015436 0 1015436 0% /sys/fs/cgroup /dev/loop2 56960 56960 0 100% /snap/core18/2538 /dev/loop0 56960 56960 0 100% /snap/core18/2344 /dev/loop3 63488 63488 0 100% /snap/core20/1611 /dev/loop4 69504 69504 0 100% /snap/lxd/22753 /dev/loop1 63488 63488 0 100% /snap/core20/1376 /dev/loop5 48128 48128 0 100% /snap/snapd/16292 /dev/loop6 69632 69632 0 100% /snap/lxd/22526 /dev/loop7 44800 44800 0 100% /snap/snapd/15177 tmpfs 203084 0 203084 0% /run/user/1000 ``` lsns in root user ``` root@ubuntu:~# lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 92 1 root /sbin/init 4026531836 pid 92 1 root /sbin/init 4026531837 user 92 1 root /sbin/init 4026531838 uts 89 1 root /sbin/init 4026531839 ipc 92 1 root /sbin/init 4026531840 mnt 86 1 root /sbin/init 4026531860 mnt 1 15 root kdevtmpfs 4026531992 net 92 1 root /sbin/init 4026532218 mnt 1 360 root /lib/systemd/systemd-udevd 4026532219 uts 1 360 root /lib/systemd/systemd-udevd 4026532220 mnt 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532221 uts 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532222 mnt 1 554 systemd-network /lib/systemd/systemd-networkd 4026532223 mnt 1 556 systemd-resolve /lib/systemd/systemd-resolved 4026532281 mnt 1 584 root /lib/systemd/systemd-logind 4026532282 uts 1 584 root /lib/systemd/systemd-logind ``` lsns in normal user ``` ubuntu@ubuntu:~$ lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 4 823 ubuntu /lib/systemd/systemd --user 4026531836 pid 4 823 ubuntu /lib/systemd/systemd --user 4026531837 user 4 823 ubuntu /lib/systemd/systemd --user 4026531838 uts 4 823 ubuntu /lib/systemd/systemd --user 4026531839 ipc 4 823 ubuntu /lib/systemd/systemd --user 4026531840 mnt 4 823 ubuntu /lib/systemd/systemd --user 4026531992 net 4 823 ubuntu /lib/systemd/systemd --user ``` #### Use root namespace to create container Create a UTS namespace. ``` root@ubuntu:~# unshare --fork --mount --uts /bin/bash root@ubuntu:~# mount -t tmpfs tmpfs /run root@ubuntu:~# hostnamectl set-hostname test-root-uts System has not been booted with systemd as init system (PID 1). Can't operate. Failed to create bus connection: Host is down root@ubuntu:~# hostname test-root-uts root@ubuntu:~# hostname test-root-uts ``` The namespaces are created by "unshare" ``` root@ubuntu:~# lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 97 1 root /sbin/init 4026531836 pid 97 1 root /sbin/init 4026531837 user 97 1 root /sbin/init 4026531838 uts 91 1 root /sbin/init 4026531839 ipc 97 1 root /sbin/init 4026531840 mnt 88 1 root /sbin/init 4026531860 mnt 1 15 root kdevtmpfs 4026531992 net 97 1 root /sbin/init 4026532218 mnt 1 360 root /lib/systemd/systemd-udevd 4026532219 uts 1 360 root /lib/systemd/systemd-udevd 4026532220 mnt 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532221 uts 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532222 mnt 1 554 systemd-network /lib/systemd/systemd-networkd 4026532223 mnt 1 556 systemd-resolve /lib/systemd/systemd-resolved 4026532224 mnt 3 1133 root unshare --fork --mount --uts /bin/bash 4026532225 uts 3 1133 root unshare --fork --mount --uts /bin/bash 4026532281 mnt 1 584 root /lib/systemd/systemd-logind 4026532282 uts 1 584 root /lib/systemd/systemd-logind ``` ``` root@ubuntu:~# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/vda2 16445308 6358200 9232020 41% / udev 970656 0 970656 0% /dev tmpfs 1015436 0 1015436 0% /dev/shm tmpfs 1015436 0 1015436 0% /run tmpfs 1015436 0 1015436 0% /sys/fs/cgroup /dev/loop2 56960 56960 0 100% /snap/core18/2538 /dev/loop0 56960 56960 0 100% /snap/core18/2344 /dev/loop3 63488 63488 0 100% /snap/core20/1611 /dev/loop4 69504 69504 0 100% /snap/lxd/22753 /dev/loop1 63488 63488 0 100% /snap/core20/1376 /dev/loop5 48128 48128 0 100% /snap/snapd/16292 /dev/loop6 69632 69632 0 100% /snap/lxd/22526 /dev/loop7 44800 44800 0 100% /snap/snapd/15177 ``` Open another terminal and enter the namespace. ``` ubuntu@ubuntu:~$ sudo su - [sudo] password for ubuntu: root@ubuntu:~# root@ubuntu:~# lsns | grep uts 4026531838 uts 101 1 root /sbin/init 4026532219 uts 1 360 root /lib/systemd/systemd-udevd 4026532221 uts 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532224 mnt 4 1133 root unshare --fork --mount --uts /bin/bash 4026532225 uts 4 1133 root unshare --fork --mount --uts /bin/bash 4026532282 uts 1 584 root /lib/systemd/systemd-logind ``` ``` root@ubuntu:~# nsenter -t 1133 -a root@test-root-uts:/# root@test-root-uts:/# df Filesystem 1K-blocks Used Available Use% Mounted on /dev/vda2 16445308 6358204 9232016 41% / udev 970656 0 970656 0% /dev tmpfs 1015436 0 1015436 0% /dev/shm tmpfs 1015436 0 1015436 0% /run tmpfs 1015436 0 1015436 0% /sys/fs/cgroup /dev/loop2 56960 56960 0 100% /snap/core18/2538 /dev/loop0 56960 56960 0 100% /snap/core18/2344 /dev/loop3 63488 63488 0 100% /snap/core20/1611 /dev/loop4 69504 69504 0 100% /snap/lxd/22753 /dev/loop1 63488 63488 0 100% /snap/core20/1376 /dev/loop5 48128 48128 0 100% /snap/snapd/16292 /dev/loop6 69632 69632 0 100% /snap/lxd/22526 /dev/loop7 44800 44800 0 100% /snap/snapd/15177 ``` #### Use user namespace to create container ``` ubuntu@ubuntu:~$ unshare --map-root-user --user --mount --uts --fork /bin/bash /bin/bash: cannot set uid to 65534: effective uid 0: Invalid argument ``` ``` bash-5.0$ whoami root bash-5.0$ lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 2 2289 root /bin/bash 4026531836 pid 2 2289 root /bin/bash 4026531839 ipc 2 2289 root /bin/bash 4026531992 net 2 2289 root /bin/bash 4026532224 user 2 2289 root /bin/bash 4026532225 mnt 2 2289 root /bin/bash 4026532226 uts 2 2289 root /bin/bash ``` Form root user, check the user namespaces. (2288) ``` root@ubuntu:~# lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 100 1 root /sbin/init 4026531836 pid 100 1 root /sbin/init 4026531837 user 98 1 root /sbin/init 4026531838 uts 95 1 root /sbin/init 4026531839 ipc 100 1 root /sbin/init 4026531840 mnt 92 1 root /sbin/init 4026531860 mnt 1 15 root kdevtmpfs 4026531992 net 100 1 root /sbin/init 4026532218 mnt 1 360 root /lib/systemd/systemd-udevd 4026532219 uts 1 360 root /lib/systemd/systemd-udevd 4026532220 mnt 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532221 uts 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532222 mnt 1 554 systemd-network /lib/systemd/systemd-networkd 4026532223 mnt 1 556 systemd-resolve /lib/systemd/systemd-resolved 4026532224 user 2 2288 root unshare --map-root-user --user --mount --uts --fork /bin/bash 4026532225 mnt 2 2288 root unshare --map-root-user --user --mount --uts --fork /bin/bash 4026532226 uts 2 2288 root unshare --map-root-user --user --mount --uts --fork /bin/bash 4026532281 mnt 1 584 root /lib/systemd/systemd-logind 4026532282 uts 1 584 root /lib/systemd/systemd-logind ``` Create namespace without "--fork" ``` ubuntu@ubuntu:~$ unshare --map-root-user --user --mount --uts /bin/bash /bin/bash: cannot set uid to 65534: effective uid 0: Invalid argument bash-5.0$ bash-5.0$ lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 2 2302 root /bin/bash 4026531836 pid 2 2302 root /bin/bash 4026531839 ipc 2 2302 root /bin/bash 4026531992 net 2 2302 root /bin/bash 4026532224 user 2 2302 root /bin/bash 4026532225 mnt 2 2302 root /bin/bash 4026532226 uts 2 2302 root /bin/bash ``` Check namespaces from root user. ``` root@ubuntu:~# lsns NS TYPE NPROCS PID USER COMMAND 4026531835 cgroup 99 1 root /sbin/init 4026531836 pid 99 1 root /sbin/init 4026531837 user 98 1 root /sbin/init 4026531838 uts 95 1 root /sbin/init 4026531839 ipc 99 1 root /sbin/init 4026531840 mnt 92 1 root /sbin/init 4026531860 mnt 1 15 root kdevtmpfs 4026531992 net 99 1 root /sbin/init 4026532218 mnt 1 360 root /lib/systemd/systemd-udevd 4026532219 uts 1 360 root /lib/systemd/systemd-udevd 4026532220 mnt 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532221 uts 1 506 systemd-timesync /lib/systemd/systemd-timesyncd 4026532222 mnt 1 554 systemd-network /lib/systemd/systemd-networkd 4026532223 mnt 1 556 systemd-resolve /lib/systemd/systemd-resolved 4026532224 user 1 2302 root /bin/bash 4026532225 mnt 1 2302 root /bin/bash 4026532226 uts 1 2302 root /bin/bash 4026532281 mnt 1 584 root /lib/systemd/systemd-logind 4026532282 uts 1 584 root /lib/systemd/systemd-logind ``` #### Troubleshooting - "unshare: unshare failed: Operation not permitted" ``` $ sudo setcap cap_sys_admin+ep /usr/bin/unshare ``` - "unshare: cannot open /proc/self/setgroups: Permission denied" ``` $ sudo chmod 4711 /usr/bin/unshare ``` #### Quotes ``` everything on a Linux system is some sort of file, and therefore file permissions are the first line of defense against an application that may misbehave. The primary way Linux handles file permissions is through the implementation of users. There are normal users, for which Linux applies privilege checking, and there is the superuser that bypasses most (if not all) checks. In short, the original Linux model was all-or-nothing. Linux capabilities were created to provide a more granular application of the security model. Instead of running the binary as root, you can apply only the specific capabilities an application requires to be effective. A capability set is the manner in which capabilities can be assigned to threads. ``` ``` The biggest advantage to the user namespace is the ability to run containers without root privileges. Additionally, depending on how you set up the UID mapping, you can completely avoid having a superuser inside a given user namespace. This means it is not possible to run any privileged processes inside of this type of namespace. ``` #### Reference - https://www.redhat.com/sysadmin/uts-namespace - https://en.wikipedia.org/wiki/Linux_namespaces#UTS - https://www.redhat.com/sysadmin/7-linux-namespaces - https://www.redhat.com/sysadmin/mount-namespaces - https://www.redhat.com/sysadmin/building-container-namespaces - https://unix.stackexchange.com/questions/252714/is-it-possible-to-run-unshare-n-program-as-an-unprivileged-user - https://super-unix.com/unixlinux/losing-permissions-by-adding-capability/ - https://www.redhat.com/sysadmin/cgroups-part-one - https://man7.org/linux/man-pages/man7/capabilities.7.html