Documentation ¶
Overview ¶
This package provides a simple wrapper around the linux 'clone' system call. The aim was to be as compatible with os/exec as possible so this could be used as a direct drop in replacement. Some functionality is improved upon, but mostly this enables several things that can only be done with a wrapper around clone and some added cgo code.
NAME SPACES ¶
This package supports either joining the name spaces of existing processes, or creating whole new name spaces for the process being executed. The current list of supported name spaces include IPC, Mount, Network, PID, and UTS, with PID being special in that its impossible to join a PID name space.
Each of these will isolate the process in some way, for example, removing visibility of the network interfaces on a machine, hiding away other processes, making a whole new file system layout that does not impact other running processes, etc.
For more information see this: http://lwn.net/Articles/531114/
DOUBLE FORKING ¶
This package enables a golang binary to execute another binary by first double forking. This allows the new binary to be a child of initd (pid 1) rather than the calling process. This is very useful for making daemons.
CGROUPS ¶
This package enables a process to be joined into cgroups before it is executed. This ensures that a process can not fork prior to being added or spawn new threads, etc.
OTHER FEATURES ¶
These are features that exist in os/exec as well as this module.
This package also supports changing user credentials via the SysProcAttr field, chrooting the process, writing to non os.File buffers via an automatically created goroutine.
TODO ¶
There are still many things to do within this module: * Examples! * Implement the functionality in SysProcAttr fully. * Finish testing some of the more edge case functionality. * Better documentation. * Warning about user name spaces and setuid being required. * Automatic proc mounting in the child for pid name spaces. * User namespace support in the CLI.
Index ¶
- type Cmd
- func (c *Cmd) CombinedOutput() ([]byte, error)
- func (c *Cmd) Output() ([]byte, error)
- func (c *Cmd) Run() error
- func (c *Cmd) Start() (err error)
- func (c *Cmd) StderrPipe() (io.ReadCloser, error)
- func (c *Cmd) StdinPipe() (io.WriteCloser, error)
- func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
- func (c *Cmd) Wait() (err error)
- type MapElement
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Cmd ¶
type Cmd struct { // This is the path to the binary that should be executed. Path string // This is the list of arguments that will be passed to exec, including // the command name as Args[0]. Args []string // This is the environment of the process. If this is nil then the // environment of the calling process will be used. Env []string // The working directory of the command. If Dir is empty then the calling // processes working directory will be used. Dir string // This is the io.Reader that will be used as the processes stdin. If this // is a os.File object then writing to the descriptor will be done // directly, otherwise a goroutine will be started to copy data from the // real descriptor to the internal reader. Stdin io.Reader // These are the io.Writers for Stdout, and Stderr. These work like // Stdin in that an os.File object is treated specially and will continue // to work even after the golang process has died. Stdout io.Writer Stderr io.Writer // This is a list of extra files that will be passed into the process. // these will be mapped in as file descriptor 3+i. Unlike Stdin these // MUST be os.File objects. ExtraFiles []*os.File // This is a list of system specific attributes. This will be translated // into system specific functionally. SysProcAttr *syscall.SysProcAttr // This is the underlying Process once started. Process *os.Process // This it the processes state information about the running process. ProcessState *os.ProcessState // This is a list of cgroups tasks files that should have the new processes // pid written into. This is used to ensure that the new process is a // member of a specific set of cgroups. If any of these files can not // be written to then the child will not be executed. CgroupsTasksFiles []string // If this is set to true then the clone cycle will double fork. This // leaves the new process as a child of initd but means that Wait() // will return only when the first child exits, not the second. // If setting this it is best to just use Run(). DoubleFork bool // These are name spaces that should be joined by the cloned child // before executing the process. This is either empty, or a string // of the form "/proc/123/ns/ipc". Note that its impossible to join // a PID name space so its not listed here. IPCNameSpace string MountNameSpace string NetworkNameSpace string UserNameSpace string UTSNameSpace string PIDNameSpace string // These boolean values are used to let the clone system know that it // should use the flags that specifically create new name spaces when // creating the child process. NewIPCNameSpace bool NewMountNameSpace bool NewNetworkNameSpace bool NewPIDNameSpace bool NewUserNameSpace bool NewUTSNameSpace bool // If NewUserNameSpace is set to true then these two fields will allow // the user map to be defined in the new user namespace. It is an error // to define these if NewUserNameSpace is not true. Leaving these as // nil will cause gocloen to not alter the user or group settings in // the new namespace. // // An important note here is that the user namespace does not kick in // until a call to setuid() and setgid() takes place. As such you // should almost always use UserNameSpace and NewUserNameSpace with // SysProcAttr set to some UID and GID. UserMap []MapElement GroupMap []MapElement // Hostname in net ns Hostname string // If set to true then the child process will create pseudo // devices: tty, zero, null, full, random, urandom CreatePseudoDevices bool // contains filtered or unexported fields }
This is a structure that mirrors the basic model of os/exec.Cmd but enables a ton of extra very linux specific features via the "clone" system call.
func Command ¶
This is a helper function that will create a Cmd object with the given commandline pre-populated.
func (*Cmd) CombinedOutput ¶
Returns stdout and stderr combined after running the process.
func (*Cmd) StderrPipe ¶
func (c *Cmd) StderrPipe() (io.ReadCloser, error)
StderrPipe returns a pipe that will be connected to the commands stderr.
func (*Cmd) StdinPipe ¶
func (c *Cmd) StdinPipe() (io.WriteCloser, error)
StdinPipe returns a pipe that will be connected to the commands stdin.
func (*Cmd) StdoutPipe ¶
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)
StdoutPipe returns a pipe that will be connected to the commands stdout.
type MapElement ¶
type MapElement struct { // This is the UID or GID to use inside of the user namespace. Inside uint64 // This is the UID or GID to use outside of the user namespace. Outside uint64 // This sets how many mappings this should cover. Length uint64 }
This data element is used to represent a user namespace uid or gid mapping. The three fields are represented in the uid_map or gid_map /proc eitries.
Example: {Inside: 0, Outside: 1000, Length: 4096} Using these settings would make the uid 0 inside of the namespace map to the uid 1000 outside, 1 would map to 1001, so on until 4095 would map to 5095.