linux-namespaces-0.1.3.0: Work with linux namespaces: create new or enter existing ones

Stabilityprovisional
Portabilitynon-portable (requires Linux)
Safe HaskellNone
LanguageHaskell2010

System.Linux.Namespaces

Contents

Description

This module provides bindings to the unshare(2) and setns(2) linux system calls. The former can be used to create new namespaces and move the calling process to them, whereas the latter can be used to move the calling process to an already existing namespace created by some other process.

Note that linux provides another function related to namespaces which is not supported by this module: clone(2). This function works like fork(2) and is used to create new namespaces (like unshare(2)). Unfortunately, like fork(2), it does not interact well with GHC'c RTS which is why it has been omitted from this module.

Note: Using this module in a program that uses the threaded RTS does not make much sense. Namespaces are per process/thread and manipulating them in one thread will not affect the namespaces of the other threads of the same process. The threaded RTS makes it is hard to predict what OS thread will be used to run the haskell threads. Therefore, using this module in such applications will result in unpredictable behavior. Similarly, using this module in ghci is problematic too.

Synopsis

Main types and functions

unshare :: [Namespace] -> IO () Source #

Detach the process from one or more namespaces and move it to new ones. See the man page of unshare(2) for more details.

setNamespace Source #

Arguments

:: Fd

A file descriptor referring to a namespace file in a /proc/[pid]/ns/ directory.

-> Maybe Namespace

Specify the namespace type that the file descriptor must refer to. If the two types do not match, the function will fail. Use Nothing to allow any type.

-> IO () 

Move the process to an already existing namespace. See the man page of setns(2) for more details. See also enterNamespace for a slightly higher level version of this function.

Utility functions

enterNamespace Source #

Arguments

:: ProcessID

The pid of any process in the target namespace.

-> Namespace

The type of the namespace.

-> IO () 

Move the process to an already existing namespace. This is a wrapper around setNamespace. This function requires /proc to be mounted.

data NamespaceID Source #

A unique namespace id.

Instances

Enum NamespaceID Source # 
Eq NamespaceID Source # 
Integral NamespaceID Source # 
Num NamespaceID Source # 
Ord NamespaceID Source # 
Read NamespaceID Source # 
Real NamespaceID Source # 
Show NamespaceID Source # 

getNamespaceID Source #

Arguments

:: Maybe ProcessID

The pid of any process in the target namespace. Use Nothing for the namespace of the calling process.

-> Namespace

The type of the namespace.

-> IO NamespaceID 

Retrieve the id of a Namespace. Useful for debugging. This function requires /proc to be mounted.

User/Group mappings

data UserMapping Source #

A single user mapping, used with user namespaces. See user_namespaces(7) for more details.

data GroupMapping Source #

A single group mapping, used with user namespaces. See user_namespaces(7) for more details.

writeUserMappings Source #

Arguments

:: Maybe ProcessID

The pid of any process in the target user namespace. Use Nothing for the namespace of the calling process.

-> [UserMapping]

The mappings.

-> IO () 

Define the user mappings for the specified user namespace. This function requires /proc to be mounted. See user_namespaces(7) for more details.

writeGroupMappings Source #

Arguments

:: Maybe ProcessID

The pid of any process in the target user namespace. Use Nothing for the namespace of the calling process.

-> [GroupMapping]

The mappings.

-> Bool

Prevent processes in the child user namespace from calling setgroups. This is needed if the calling process does not have the CAP_SETGID capability in the parent namespace.

-> IO () 

Define the group mappings for the specified user namespace. This function requires /proc to be mounted. See user_namespaces(7) for more details.

Example

Here's an example of creating a new network namespace. We also create a user namespace. This allows us to execute the program as an unprivileged user.

import System.Process
import System.Posix.User
import System.Linux.Namespaces

main :: IO ()
main = do
    putStrLn "*** Network interfaces in the parent namespace ***"
    callCommand "ip addr"
    putStrLn ""

    -- find the uid, we must do that before unshare
    uid <- getEffectiveUserID

    unshare [User, Network]
    -- map current user to user 0 (i.e. root) inside the namespace
    writeUserMappings Nothing [UserMapping 0 uid 1]

    -- enable the loopback interface
    -- we can do that because we are root inside the namespace
    callCommand "ip link set dev lo up"

    putStrLn "*** Network interfaces in the new namespace ***"
    callCommand "ip addr"