Documentation ¶
Overview ¶
Package species defines the type constants and type names of the 8 Linux kernel namespace types ("species"). In addition, this package also defines how to represent namespace identifiers, which actually consist of not only an inode number, but also the device ID where a namespace inode is located on. This package also converts between the namespace type names and their corresponding (Linux kernel) constants, as well as between the internal and textual representations of namespace identifiers.
Namespace Identifiers ¶
Caveat: currently, the textual representation of namespace identifiers employed by the Linux kernel and CLI tools ignores the device ID part of a complete namespace identifier, but uses only the inode number.
Internally, all lxkns packages work with both the inode number as well as the device ID of a namespace. Please see also the notes below.
Namespace Type Constants ¶
While Golang's x/sys/unix package finally defines even the formerly missing CLONE_NEWCGROUP constant (which was missing from the syscall package), this package still redefines the namespace-related CLONE_NEWxxx identifiers to be type-safe. This way, they cannot accidentally be mixed with other CLONE_xxx constants, or the CLONE_xxx flags in general.
To provide backwards compatibility with older Go versions, namely Go 1.13, this package defines CLONE_NEWTIME itself when there is no underlying unix.CLONE_NEWTIME available. Applications using lxkns should thus only use species. CLONE_NEWTIME in order to be shielded from variations in Go's unix package.
Index ¶
Examples ¶
Constants ¶
const ( CLONE_NEWNS = NamespaceType(unix.CLONE_NEWNS) CLONE_NEWCGROUP = NamespaceType(unix.CLONE_NEWCGROUP) CLONE_NEWUTS = NamespaceType(unix.CLONE_NEWUTS) CLONE_NEWIPC = NamespaceType(unix.CLONE_NEWIPC) CLONE_NEWUSER = NamespaceType(unix.CLONE_NEWUSER) CLONE_NEWPID = NamespaceType(unix.CLONE_NEWPID) CLONE_NEWNET = NamespaceType(unix.CLONE_NEWNET) CLONE_NEWTIME = NamespaceType(cloneNewtime) )
The 8 type of Linux namespaces defined at this time (sic!). Please note that the 8th namespace is only supported since Kernel 5.6+.
These constants are used with several of the namespace-related functions, such as clone() in particular, but also setns(), unshare(), and the NS_GET_NSTYPE ioctl(). The origin for their definitions is: https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/sched.h
Oh, forgo golint with its "helicopter parents" attitude patronizing us about how names of Linux kernel definitions have to look like. Go for something grown up, such as golangci-lint, and many more, which hide the totally childish behavior of golint.
Variables ¶
var NoneID = NamespaceID{}
NoneID is a convenience for signalling an invalid or non-existing namespace identifier.
Functions ¶
func IDwithType ¶
func IDwithType(s string) (id NamespaceID, t NamespaceType)
IDwithType takes a string representation of a namespace instance, such as "net:[1234]", and returns the ID together with the type of the namespace (but see note below). In case the string is malformed or contains an unknown namespace type, IDwithType returns (NoneID, NaNS).
There is an important gotcha to be aware of: the Linux kernel only uses a namespace's inode number in its textual format, dropping the device ID where the namespace is located on. To work around this oversight and to allow for namespace IDs to be comparable using "==", IDwithType adds the missing device ID by guessing it from the net namespace of the current process at the time of its startup.
Example ¶
id, t := IDwithType("mnt:[12345678]") fmt.Printf("%q %d\n", t.Name(), id.Ino) // "nonsense" namespace textual representations return an identifier of // NoneID and a type of NaNS (not a namespace). id, t = IDwithType("foo:[-1]") fmt.Printf("%v %v\n", t, id)
Output: "mnt" 12345678 NaNS NoneID
Types ¶
type NamespaceID ¶
type NamespaceID struct { Dev uint64 // device ID maintaining the namespace (Golang insists on uint64) Ino uint64 // inode number of this namespace. }
NamespaceID represents a Linux kernel namespace identifier. NamespaceIDs can be compared for equality or inequality using Golang's "==" and "!=" operators. However, namespaceIDs are not ordered, so they cannot compared according to their order (they don't possess) using "<", et cetera.
While namespace identifiers currently use only 32bit values, we're playing safe here and keep with the 64bit-ness of inode numbers, as which they originally appear. Additionally, we also adhere to http://man7.org/linux/man-pages/man7/namespaces.7.html and also take the device a namespace inode lives on into consideration, to cover for a potential future with multiple namespace filesystems, as opposed to the single "nsfs" namespace filesystem of today.
Note, there are some caveats to watch for, such as that the current textual format used by the Linux kernel when rendering namespaces (references) as text does not cater for the device ID, but only a namespace's inode. The textual conversions in this package work around these limitations.
func NamespaceIDfromInode ¶
func NamespaceIDfromInode(ino uint64) NamespaceID
NamespaceIDfromInode is an inconvenience helper that caters for the current chaos in that several sources of inodes, such as the kernel's own textual references and 3rd party CLI tools such as "lsns", only give a namespace's inode number, but not its device ID. It does so by glancing the missing device ID from one of our own process' net namespace (at the startup time) and then adds that in the hope that things still work correctly for the moment.
func (NamespaceID) String ¶
func (nsid NamespaceID) String() string
String returns the namespace identifier in form of "NamespaceID(dev,#no)" as text, or "NoneID", if it is invalid. Please note that String on purpose does not use the text format used in the Linux kernel, as a namespace identifier has no namespace type information attached to it. Besides, not least it is used by Golang debuggers when rendering values, so we here follow Golang (tooling) convention.
type NamespaceType ¶
type NamespaceType uint64
NamespaceType mirrors the data type used in the Linux kernel for the namespace type constants. These constants are actually part of the clone() syscall options parameter.
const NaNS NamespaceType = 0
NaNS identifies an invalid namespace type.
func NameToType ¶
func NameToType(name string) NamespaceType
NameToType returns the namespace type value (constant CLONE_NEWNS, ...) corresponding to the specified namespace type name (such as "mnt", "net", et cetera).
Example ¶
for _, name := range []string{ "mnt", "cgroup", "uts", "ipc", "user", "pid", "net", "spam", } { fmt.Printf("0x%08x\n", uint64(NameToType(name))) }
Output: 0x00020000 0x02000000 0x04000000 0x08000000 0x10000000 0x20000000 0x40000000 0x00000000
func (NamespaceType) Name ¶
func (nstype NamespaceType) Name() string
Name returns the type name string (such as "mnt", "net", ...) of a namespace type value.
Example ¶
fmt.Println(CLONE_NEWCGROUP.Name())
Output: cgroup
func (NamespaceType) String ¶
func (nstype NamespaceType) String() string
String returns the Linux kernel namespace constant name for a given namespace type value.
Example ¶
for _, t := range []NamespaceType{ CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC, CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, } { fmt.Println(t.String()) }
Output: CLONE_NEWNS CLONE_NEWCGROUP CLONE_NEWUTS CLONE_NEWIPC CLONE_NEWUSER CLONE_NEWPID CLONE_NEWNET