session

package
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 2, 2022 License: BSD-3-Clause Imports: 13 Imported by: 0

Documentation

Overview

Package session is for managing cpu sessions, i.e. the process started by cpud.

New(port9p, cmd string, args ...string) creates a new Session. The port9p argument, if is not empty, specifies the 9p port to use. The cmd parameter specifies a command and arguments, a la exec.Command. Sessions are very similar to exec.Command, providing access to Stdin, Stdout, Stderr. For Stdin, Run determines if a pty is needed and will set one up.

Run will also set up a process namespace via 9p and other mounts, if needed. If CPU_NAMESPACE is non-empty, it defines the bind mounts from /tmp/cpu. See the cpu command documentation for more information on how CPU_NAMESPACE is set. If CPU_FSTAB is set, it is assumed to be a string in fstab(5) format and Run will mount the specified file systems. CPU_FSTAB is most often used for virtiofs mounts from virtual machines.

For the moment, servers only call Run(), which does all namespace, tty, and process startup. Run returns when the process it directly started returns. It does not wait for children.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Bind

type Bind struct {
	Local  string
	Remote string
}

Bind defines a bind mount. It records the Local directory, e.g. /bin, and the remote directory, e.g. /tmp/cpu/bin.

func ParseBinds

func ParseBinds(s string) ([]Bind, error)

ParseBinds parses a CPU_NAMESPACE-style string to a slice of Bind structures.

type Session

type Session struct {
	Stdin  io.Reader
	Stdout io.Writer
	Stderr io.Writer
	// contains filtered or unexported fields
}

Session is one instance of a cpu session, started by a cpud.

func New

func New(port9p, tmpMnt, cmd string, args ...string) *Session

New returns a New session with defaults set. It requires a port for 9p (which can be the empty string, but is usually not) and a command name.

func (*Session) DropPrivs

func (s *Session) DropPrivs() error

DropPrivs drops privileges to the level of os.Getuid / os.Getgid

func (*Session) Namespace

func (s *Session) Namespace() (error, error)

Namespace assembles a NameSpace for this cpud, iff CPU_NONCE is set and len(s.binds) > 0.

This code assumes you have a non-shared namespace. This is archieved in go by setting exec.Cmd.SysprocAttr.Unshareflags to CLONE_NEWNS; the go runtime will then do what is needed to privatize a namespace. I can say this because I wrote that code 5 years ago, and go tests for it are run as part of the go release process.

To reiterate, this package requires, for proper operation, that the process using it be in a private name space, and, further, that the namespace can't magically be reshared.

It's very hard and probably impossible to test for a namespace being set up properly on Linux. On plan 9 it's easy: read the process namespace file and see if it's empty. But no such operation is possible on Linux and, worse, since sometime in the 3.x kernel series, even once a namespace is unshared, another process can start using it via nsenter(2).

Hence this note: it is a warning to our future selves or users of this package.

Note, however, that cpud does the right thing, by setting Unshareflags to CLONE_NEWNS. Tests in the cpu server code ensure that continues to be the case.

tl;dr: Linux namespaces are a pretty terrible mess. They may have been inspired by Plan 9, but an understanding of some critical core ideas has been lost. As a result, they do not remotely represent any kind of security boundary.

func (*Session) Run

func (s *Session) Run() error

Run starts up a remote cpu session. It is started by a cpu daemon via a -remote switch.

This code assumes that cpud is running as init, or that an init has started a cpud, and that the code is running with a private namespace (CLONE_NEWNS on Linux; RFNAMEG on Plan9). On Linux, it starts as uid 0, and once the mount/bind is done, calls DropPrivs.

func (*Session) Terminal

func (s *Session) Terminal() error

Terminal sets up an interactive terminal.

func (*Session) TmpMounts

func (s *Session) TmpMounts() error

TmpMounts sets up directories, and bind mounts, in /tmp/cpu. N.B. the /tmp/cpu mount is private assuming this program was started correctly with the namespace unshared (on Linux and Plan 9; on *BSD or Windows no such guarantees can be made).

See the longer comment (rant) in session_linux.go

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL