Package: linuxns-rel
Linux Kernel Namespace RelationsNOTE:Linux Kernel 4.9+ and Python 3.5+ supported onlyThis Python 3 package allows discovering the following Linux Kernel
namespace relationships and properties, without having to delve intoioctl()hell:theowninguser namespace of another Linux kernel namespace.theparentnamespace of either a user or a PID namespace.type of a Linux kernel namespace: user, PID, network, ...owner user ID of a user namespace.See alsoioctl() operations for Linux namespacesfor more background information of the namespace operations exposed by
this Python library.Installation$pip3installlinuxns-relNOTE:the installation automatically detects Debian 9 Stretch and
correctly handles installing the PyQt5 package, if it is missing, in
at most version 5.10.1 -- as this is the last known working PyQt5
release on Debian 9 Stretch.API DocumentationPlease head over to ourlinuxns_rel API documentationon GitHub Pages.CLI ExamplesNOTE:Debian 9 Stretch users will lack the ability discover the
owner user ID of hierarchical namespaces. The reason is that Debian
9 Stretch ships with outdated Linux kernels that lack the required
Kernel functionality. Please enjoy this kind ofstability. (Or is
this "austerity"?)List User NamespacesYou can either use a simplelsusernsorsudo lsuserns-- the latter
ensures that you'll seealluser namespaces instead of only those you have
user access to. Optionally, you can also see which other namespaces are owned
by specific user namespaces.NOTE:lsuserns(andlspidns) discover user and pid namespaces from
more locations thanlsnsdoes:/proc/$PID/ns/(the only location supported bylsns)/proc/$PID/fd/(open file descriptors referencing namespaces; onlylsusernsatm)namespaceioctl()(see "man 2 ioctl_ns")$sudolsusernsmay yield something like this, a pretty hierarchy of Linux kernel user
namespaces:user:[4026531837] process "init (1)" namespace-owning user "root" (0)
 ├── user:[4026532217] process "sleep (9403)" namespace-owning user "harald" (1000)
 ├── user:[4026532401] process "firefox (1374)" namespace-owning user "harald" (1000)
 ├── user:[4026532582] process namespace-owning user "harald" (1000)
 │   └── user:[4026532583] process namespace-owning user "harald" (1000)
 │       └── user:[4026532584] process namespace-owning user "harald" (1000)
 │           └── user:[4026532585] process "bash (1468)" namespace-owning user "harald" (1000)
 ├── user:[4026532639] process "firefox (2723)" namespace-owning user "harald" (1000)
 ├── user:[4026532696] process "firefox (2768)" namespace-owning user "harald" (1000)
 └── user:[4026532936] process "firefox (17192)" namespace-owning user "harald" (1000)If you want to additionally see which non-user namespaces are owned by the user namespaces, then add the CLI arg-d(as in "details"):$sudolsuserns-dNOTE:-ccolorizes the output, differentiating namespaces in color
based on their types.In the output, "⟜" denotes a non-user namespace (ipc, mnt, net, ...) which is
owned by a particular user namespace.user:[4026531837] process "init (1)" namespace-owning user "root" (0)
 ├── ⟜ cgroup:[4026531835] process "init (1)"
 ├── ⟜ ipc:[4026531839] process "init (1)"
 ├── ⟜ mnt:[4026531840] process "init (1)"
 ├── ⟜ mnt:[4026531860] process "[kdevtmpfs] (57)"
 ├── ⟜ mnt:[4026532216] process "systemd-udevd (470)"
 ├── ⟜ mnt:[4026532263] process "systemd-resolved (1217)"
 ├── ⟜ mnt:[4026532264] process "systemd-timesyncd (1218)"
 ├── ⟜ mnt:[4026532452] process "haveged (1223)"
 ├── ⟜ mnt:[4026532453] process "ModemManager (1264)"
 ├── ⟜ mnt:[4026532454] process "NetworkManager (1268)"
 ├── ⟜ mnt:[4026532455] process "irqbalance (1312)"
 ├── ⟜ mnt:[4026532456] process "mpd (1402)"
 ├── ⟜ mnt:[4026532524] process "upowerd (1618)"
 ├── ⟜ net:[4026532000] process "init (1)"
 ├── ⟜ net:[4026532266] process "haveged (1223)"
 ├── ⟜ net:[4026532458] process "rtkit-daemon (2148)"
 ├── ⟜ pid:[4026531836] process "init (1)"
 ├── ⟜ uts:[4026531838] process "init (1)"
 ├── user:[4026532217] process "sleep (9403)" namespace-owning user "harald" (1000)
 │   └── ⟜ net:[4026532219] process "sleep (9403)"
 ├── user:[4026532401] process "firefox (1374)" namespace-owning user "harald" (1000)
 │   ├── ⟜ ipc:[4026532512] process "firefox (1374)"
 │   └── ⟜ net:[4026532529] process "firefox (1374)"
 ├── user:[4026532582] process namespace-owning user "harald" (1000)
 │   └── user:[4026532583] process namespace-owning user "harald" (1000)
 │       └── user:[4026532584] process namespace-owning user "harald" (1000)
 │           └── user:[4026532585] process "bash (1468)" namespace-owning user "harald" (1000)
 ├── user:[4026532639] process "firefox (2723)" namespace-owning user "harald" (1000)
 │   ├── ⟜ ipc:[4026532640] process "firefox (2723)"
 │   └── ⟜ net:[4026532642] process "firefox (2723)"
 ├── user:[4026532696] process "firefox (2768)" namespace-owning user "harald" (1000)
 │   ├── ⟜ ipc:[4026532697] process "firefox (2768)"
 │   └── ⟜ net:[4026532699] process "firefox (2768)"
 └── user:[4026532936] process "firefox (17192)" namespace-owning user "harald" (1000)
     ├── ⟜ ipc:[4026532937] process "firefox (17192)"
     └── ⟜ net:[4026532939] process "firefox (17192)"If you have either Chromium or/and Firefox running, then these will
add some user namespaces in order to sandbox their inner workings. And
to add in some more hierarchical user namespaces, in another terminal
session simply issue the following command:$unshare-Urunshare-Urunshare-Urunshare-UrDebian users may need tosudobecause their distro's default
configuration prohibits ordinary users to create new user namespaces.List PID Namespaces$sudolspidnsshows the PID namespace hierarchy, such as:pid:[4026531836] process "init" owner user:[4026531837] root (0)
 ├── pid:[4026532532] process "sh" owner user:[4026531837] root (0)
 └── pid:[4026532468] process "chromium-browser --type=zygote" owner user:[4026532467] foobar (1000)
     ├── pid:[4026532464] process "chromium-browser" owner user:[4026532589] foobar (1000)
     ├── pid:[4026532466] process "chromium-browser" owner user:[4026532589] foobar (1000)
     └── pid:[4026532590] process "chromium-browser" owner user:[4026532589] foobar (1000)Don't worry that the PID namespace hierarchy doesn't match the user
namespace hierarchy. That's perfectly fine, depending on which programs
run. In our example, we didn't create new PID namespaces when usingunshare, so we see only additional PID namespaces created by
Chromium (Firefox doesn't create them though).Namespace GraphOkay, with the famousgraphvizinstalled (apt-get install graphviz)
now simply do:$sudo-EgraphnsNote:-Eensures that the graph viewer will correctly use the your
desktop environment theme....and you get something fancy with arrows, et cetera, in a cute (erm,
"qute") little viewer window:The view window supports these actions:mouse drag: move the visible area around inside the view window
(usefull when either the graph is really large or when zoomed in).mouse wheel: zoom in/out.+/-keys: zoom in/out.1key: reset zoom to 1x.skey: save image to an SVG file.qkey: close and exit the viewer.hkey: show help on mouse and keys.Potentially FAQsQ: Why doget_userns()andget_parentns()return file objects
(TextIO) instead of filesystem paths?A: Because that's what the Linux namespace-relatedioctl()functions are giving us: open file descriptors referencing namespaces
in the specialnsfsnamespace filesystem. There are no paths
associated with them.Q: What argument types doget_nstype(),get_userns(),get_parentns(), andget_owner_uid()expect?A: Choose your weapon:a filesystem path (name), such as/proc/self/ns/user,an open file object (TextIO), such as returned byopen(),an open file descriptor, such as returned byfileno()methods.Q: Why doesget_parentns()throw an PermissionError?A: There are multiple causes:you didn't specify a PID or user namespace,the parent namespace either doesn't exist,or the parent namespace is inaccessible to you,oh, you really have no access to the namespace reference.Q: Why doesget_userns()throw an PermissionError?A: You don't have access to the owning user namespace.