1 Introduction
2 Maintainers
3 Download
4 Build
5 Covers
6 Description of the utilities
6.1 lxc-pid
6.2 lxc-start2
6.3 cmpns
6.4 clonens
6.5 execns
6.6 shns
6.7 shns2
6.8 shns3
6.9 idns
6.10 ownerns
6.11 parentns
6.12 userns
6.13 linfo
6.14 setnshost
6.15 fsinfo
The examples programs available here illustrate the articles serie published in french in GNU Linux Magazine France presenting the Linux namespaces in details from user to kernel space. They are written with a minimum number of lines to make them easier to understand. Hence, the source code may appear not robust (no checks on the return codes, basic algorithmic...).
The articles are first published in the magazine. The list is located here. They become available for free after 4 to 6 months and a pdf copy is stored in the articles sub-directory:
- Les namespaces ou l'art de se démultiplier;
- Les utilitaires relatifs aux namespaces;
- Les structures de données des namespaces dans le noyau;
- Le fonctionnement des namespaces dans le noyau;
- Identité multiple avec le namespace user;
- A la découverte des namespaces mount et uts;
- Les bizarreries de l'isolation des IPC;
- Les namespaces network et pid;
- Le namespace cgroup ne sera pas le dernier de la lignée.
For any question or remark, please contact me
The source code is available on github. Use the following command to clone it:
$ git clone https://github.com/Rachid-Koucha/linux_ns.git
The example programs are at the top level. The articles available for free are in the articles sub-directory in pdf format.
The build is done with cmake:
$ cmake .
-- The C compiler identification is GNU 9.3.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
[...]
$ make
Scanning dependencies of target reaper
[ 1%] Building C object CMakeFiles/reaper.dir/reaper.c.o
[ 2%] Linking C executable reaper
[ 2%] Built target reaper
[...]
To clean the built files:
$ make clean
The covers of the published articles are:
- Issue#239 of July/August 2020:
- Issue#240 of September 2020:
- Issue#243 of December 2020:
- Issue#245 of February 2021:
- Issue#246 of March 2021:
- Issue#247 of April 2021:
- Issue#250 of July-August 2021:
- Issue#256 of March-April 2022:
- Issue#258 of July-August 2022:
The following simple utilities are used to illustrate the articles serie concerning the Linux namespaces. They are not designed to be used in a larger scope although they may provide some hints to write some more elaborated tools around the Linux namespaces.
lxc-pid
is a shell script which retrieves and displays the pid of the init process of a LXC container.
For example:
$ sudo lxc-start -n bbox
$ sudo lxc-ls -f
$ sudo lxc-ls -f
NAME STATE AUTOSTART GROUPS IPV4 IPV6 UNPRIVILEGED
bbox RUNNING 0 - 10.0.3.230 - false
$ sudo ./lxc-pid bbox
14642
$ sudo lxc-stop -n bbox
$ $ sudo ./lxc-pid bbox
Unknown container bbox
lxc-start2
is a shell script to start a LXC container which displays its name in its shell prompt.
For example, we start a container named bbox (of course it is supposed to have been created):
$ sudo ./lxc-start2 bbox
$ sudo lxc-attach -n bbox
$ sudo lxc-console -n bbox -t 0
Connected to tty 0
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself
BusyBox v1.30.1 (Ubuntu 1:1.30.1-4ubuntu4) built-in shell (ash)
Enter 'help' for a list of built-in commands.
bbox# <CTRL>+<a>+<q>
$
cmpns
compares the namespaces of two processes which identifiers are passed as parameters.
In this example, we compare the namespaces of the current shell with the namespaces of the init process of the host:
$ sudo ./cmpns $$ 1
cgroup is equal
ipc is equal
mnt is equal
net is equal
pid is equal
user is equal
uts is equal
In this example, we compare the namespaces of the current shell with the namespaces of the init process of a LXC container:
$ sudo lxc-start -n bbox
$ sudo ./lxc-pid bbox
14857
$ sudo ./cmpns $$ 14857
cgroup is different
ipc is different
mnt is different
net is different
pid is different
user is equal
uts is different
Privileged containers run in the same user namespaces as the host. Hence, the equality in the above display.
clonens
creates a new process in new namespaces. The latters are passed as
parameters with their symbolic names (cgroup, ipc, mnt, net, pid, user and uts).
For example, in one terminal, we launch a process in new pid and uts namespaces. The launched process is suspended on pause()
:
$ sudo ./clonens pid uts
Created process 14950 in requested namespaces
In another terminal, we compare the namespaces of the new process with the namespaces of the current shell to verify that the uts and pid namespaces are different:
$ sudo ./cmpns 14950 $$
cgroup is equal
ipc is equal
mnt is equal
net is equal
pid is different
user is equal
uts is different
execns
executes a program in one or more namespaces of a running process.
In this example, we run a shell in the namespaces of the init process of a running LXC container:
$ sudo ./lxc-pid bbox
14857
$ PS1="\h#\x20" sudo -E ./execns 14857 /bin/sh
Moved into namespace ipc
Moved into namespace pid
Moved into namespace net
Moved into namespace uts
Moved into namespace cgroup
Moved into namespace mnt
BusyBox v1.30.1 (Ubuntu 1:1.30.1-4ubuntu4) built-in shell (ash)
Enter 'help' for a list of built-in commands.
bbox# exit
program's status: 0 (0x0)
shns
creates a shell in the namespaces specified as parameters.
For example:
$ PS1="SHNS# " sudo -E ./shns
New namespace 'ipc'
New namespace 'pid'
New namespace 'net'
New namespace 'user'
New namespace 'uts'
New namespace 'cgroup'
New namespace 'mnt'
SHNS# date
dim. 28 mars 2021 18:57:37 CEST
SHNS# exit
/bin/sh: 5: Cannot set tty process group (No such process)
program's status: 0 (0x0)
Like shns
, shns2
creates a shell in the namespaces specified as parameters. But it prompts the user just before the execution of the shell.
For example:
$ PS1='SHNS$ ' ./shns2 ipc uts mnt user
New namespace 'ipc'
New namespace 'user'
New namespace 'uts'
New namespace 'mnt'
Process#15706 go forward ([Y]/N)?
shns3
is the synthesis of shns
and shns2
. The usage is:
$ ./shns3 -h
Usage: shns3 [-h] [-d level] [-n nsname] [-u uidmap] [-g gidmap] [-s path]
-h|--help : This help
-h|--debug level : Debug level
-n|--nspc nsname : Create namespace
'nsname' is: cgroup|ipc|net|mnt|pid|user|uts
-u|--umap uidmap : User id mapping
'uidmap' is 'uid loweruid count'
-g|--gmap gidmap : Group id mapping
'gidmap' is 'gid lowergid count'
-s|--shell path : Execute shell
'path' is '/bin/sh' by default
The namespaces to create are passed with the --nspc
option. The user ids and group ids mappings are respectively passed through the --umap
and --gmap
options. For example:
$ ./shns3 -u '0 1000 1' -u '1 100000 100' -g '0 1000 1' -g '1 100000 100' -d 1
DEBUG_1 (main#358): New namespace 'ipc'
DEBUG_1 (main#358): New namespace 'pid'
DEBUG_1 (main#358): New namespace 'net'
DEBUG_1 (main#358): New namespace 'user'
DEBUG_1 (main#358): New namespace 'uts'
DEBUG_1 (main#358): New namespace 'cgroup'
DEBUG_1 (main#358): New namespace 'mnt'
DEBUG_1 (main#409): Running 'newuidmap 7565 0 1000 1 1 100000 100'...
DEBUG_1 (main#424): Running 'newgidmap 7565 0 1000 1 1 100000 100'...
# id
uid=0(root) gid=0(root) groups=0(root),65534(nogroup)
#
idns
displays the identifiers of one or more namespaces of a given process. By default, all
the namespaces are considered.
For example, to display the identifiers of the namespaces of the current shell:
$ sudo ./idns $$
/proc/7622/ns/cgroup [Device,Inode]: [4,4026531835]
/proc/7622/ns/ipc [Device,Inode]: [4,4026531839]
/proc/7622/ns/mnt [Device,Inode]: [4,4026531840]
/proc/7622/ns/net [Device,Inode]: [4,4026531992]
/proc/7622/ns/pid [Device,Inode]: [4,4026531836]
/proc/7622/ns/uts [Device,Inode]: [4,4026531838]
/proc/7622/ns/user [Device,Inode]: [4,4026531837]
$ sudo ./idns $$ uts ipc
/proc/7622/ns/uts [Device,Inode]: [4,4026531838]
/proc/7622/ns/ipc [Device,Inode]: [4,4026531839]
ownerns
displays the user_ns owning a the namespaces of a given process.
For example, we display the user_ns owning the namespaces of the current shell:
$ sudo ./ownerns $$
/proc/7622/ns/cgroup belongs to [Device,Inode]: [4,4026531837]
/proc/7622/ns/ipc belongs to [Device,Inode]: [4,4026531837]
/proc/7622/ns/mnt belongs to [Device,Inode]: [4,4026531837]
/proc/7622/ns/net belongs to [Device,Inode]: [4,4026531837]
/proc/7622/ns/pid belongs to [Device,Inode]: [4,4026531837]
/proc/7622/ns/uts belongs to [Device,Inode]: [4,4026531837]
ERROR@main#87: ioctl(/proc/7622/ns/user, NS_GET_USERNS): 'Operation not permitted' (1)
parentns
displays the parent namespace of a the namespaces of a given process. This works only for
hierarchical namespaces (i.e. pid_ns and user_ns).
For example, we display the parent user_ns of the init process of a running LXC container:
$ sudo ./lxc-pid bbox
14857
$ sudo ./parentns 14857 pid user
/proc/14857/ns/pid is child of [Device,Inode]: [4,4026531836]
ERROR@main#89: ioctl(/proc/14857/ns/user, NS_GET_PARENT): 'Operation not permitted' (1)
In the above display, there is an error for the user_ns as a privileged container runs in the user_ns as the host. And it is not possible to get the parent user namespace of the initial user_ns.
userns
displays the name and the user identifier of the user which created the user namespaces of a given process.
For example, we display the user identifier of the creator of the user namespace of the current shell:
$ echo $$
7622
$ sudo ./userns $$
/proc/7622/ns/user belongs to user: 'root' (0)
linfo
displays information about a symbolink link.
For example:
$ ./linfo /proc/$$/ns/mnt
Symbolic link:
Name: /proc/3098/ns/mnt
Rights: 0777
Device (major/minor): 0x0/0x5
Inode: 0x1a284 (107140)
Target:
Name: mnt:[4026531840]
Rights: 0444
Device (major/minor): 0x0/0x4
Inode: 0xf0000000 (4026531840)
setnshost
sets the hostname in the uts namespace of a given process.
For example, we set the hostname in a LXC container using the pid of its init process:
$ sudo lxc-start -n bbox
$ sudo lxc-console -n bbox -t 0
Connected to tty 0
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself
BusyBox v1.30.1 (Ubuntu 1:1.30.1-4ubuntu4) built-in shell (ash)
Enter 'help' for a list of built-in commands.
/ # hostname
bbox
/ # <CTRL>+<a>+<q>
$ sudo ./lxc-pid bbox
5865
$ sudo ./setnshost 5865 qwerty
$ sudo lxc-console -n bbox -t 0
Connected to tty 0
Type <Ctrl+a q> to exit the console, <Ctrl+a Ctrl+a> to enter Ctrl+a itself
/ # hostname
qwerty
/ # <CTRL>+<a>+<q>
$
fsinfo
displays the information about a file system into which a file/directory resides.
To display the information about the root file system on my machine:
$ ./fsinfo /
Type : 0xef53 (EXT2/3/4FS)
Block size : 4096
Total blocks : 119916557
Total free blocks: 117922759
Total files : 30531584
Max name length : 255
Mount flags : 0x1020 (REMOUNT BIND)
The following displays the information about the PROCFS file system into which the ns
directory resides:
$ ./fsinfo /proc/$$/ns
Type : 0x9fa0 (PROCFS)
Block size : 4096
Total blocks : 0
Total free blocks: 0
Total files : 0
Max name length : 255
Mount flags : 0x102e (NODEV NOEXEC NOSUID REMOUNT BIND)
The following displays the information about the NSFS file system into which reside the targets of the symbolic links in the latter directory:
$ ./fsinfo /proc/$$/ns/mnt
Type : 0x6e736673 (NSFS)
Block size : 4096
Total blocks : 0
Total free blocks: 0
Total files : 0
Max name length : 255
Mount flags : 0x20 (REMOUNT)