Merge v1.2.1-master
Signed-off-by: Emile Vauge <emile@vauge.com>
This commit is contained in:
parent
a590155b0b
commit
aeb17182b4
396 changed files with 27271 additions and 9969 deletions
197
vendor/github.com/opencontainers/runc/utils_linux.go
generated
vendored
197
vendor/github.com/opencontainers/runc/utils_linux.go
generated
vendored
|
@ -5,6 +5,7 @@ package main
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
@ -14,7 +15,9 @@ import (
|
|||
"github.com/coreos/go-systemd/activation"
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/specconv"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
@ -76,11 +79,18 @@ func newProcess(p specs.Process) (*libcontainer.Process, error) {
|
|||
// TODO: fix libcontainer's API to better support uid/gid in a typesafe way.
|
||||
User: fmt.Sprintf("%d:%d", p.User.UID, p.User.GID),
|
||||
Cwd: p.Cwd,
|
||||
Capabilities: p.Capabilities,
|
||||
Label: p.SelinuxLabel,
|
||||
NoNewPrivileges: &p.NoNewPrivileges,
|
||||
AppArmorProfile: p.ApparmorProfile,
|
||||
}
|
||||
if p.Capabilities != nil {
|
||||
lp.Capabilities = &configs.Capabilities{}
|
||||
lp.Capabilities.Bounding = p.Capabilities.Bounding
|
||||
lp.Capabilities.Effective = p.Capabilities.Effective
|
||||
lp.Capabilities.Inheritable = p.Capabilities.Inheritable
|
||||
lp.Capabilities.Permitted = p.Capabilities.Permitted
|
||||
lp.Capabilities.Ambient = p.Capabilities.Ambient
|
||||
}
|
||||
for _, gid := range p.User.AdditionalGids {
|
||||
lp.AdditionalGroups = append(lp.AdditionalGroups, strconv.FormatUint(uint64(gid), 10))
|
||||
}
|
||||
|
@ -94,53 +104,62 @@ func newProcess(p specs.Process) (*libcontainer.Process, error) {
|
|||
return lp, nil
|
||||
}
|
||||
|
||||
func dupStdio(process *libcontainer.Process, rootuid, rootgid int) error {
|
||||
process.Stdin = os.Stdin
|
||||
process.Stdout = os.Stdout
|
||||
process.Stderr = os.Stderr
|
||||
for _, fd := range []uintptr{
|
||||
os.Stdin.Fd(),
|
||||
os.Stdout.Fd(),
|
||||
os.Stderr.Fd(),
|
||||
} {
|
||||
if err := syscall.Fchown(int(fd), rootuid, rootgid); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// If systemd is supporting sd_notify protocol, this function will add support
|
||||
// for sd_notify protocol from within the container.
|
||||
func setupSdNotify(spec *specs.Spec, notifySocket string) {
|
||||
spec.Mounts = append(spec.Mounts, specs.Mount{Destination: notifySocket, Type: "bind", Source: notifySocket, Options: []string{"bind"}})
|
||||
spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("NOTIFY_SOCKET=%s", notifySocket))
|
||||
}
|
||||
|
||||
func destroy(container libcontainer.Container) {
|
||||
if err := container.Destroy(); err != nil {
|
||||
logrus.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
// setupIO sets the proper IO on the process depending on the configuration
|
||||
// If there is a nil error then there must be a non nil tty returned
|
||||
func setupIO(process *libcontainer.Process, rootuid, rootgid int, console string, createTTY, detach bool) (*tty, error) {
|
||||
// detach and createTty will not work unless a console path is passed
|
||||
// so error out here before changing any terminal settings
|
||||
if createTTY && detach && console == "" {
|
||||
return nil, fmt.Errorf("cannot allocate tty if runc will detach")
|
||||
}
|
||||
// setupIO modifies the given process config according to the options.
|
||||
func setupIO(process *libcontainer.Process, rootuid, rootgid int, createTTY, detach bool, sockpath string) (*tty, error) {
|
||||
if createTTY {
|
||||
return createTty(process, rootuid, rootgid, console)
|
||||
process.Stdin = nil
|
||||
process.Stdout = nil
|
||||
process.Stderr = nil
|
||||
t := &tty{}
|
||||
if !detach {
|
||||
parent, child, err := utils.NewSockPair("console")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
process.ConsoleSocket = child
|
||||
t.postStart = append(t.postStart, parent, child)
|
||||
t.consoleC = make(chan error, 1)
|
||||
go func() {
|
||||
if err := t.recvtty(process, parent); err != nil {
|
||||
t.consoleC <- err
|
||||
}
|
||||
t.consoleC <- nil
|
||||
}()
|
||||
} else {
|
||||
// the caller of runc will handle receiving the console master
|
||||
conn, err := net.Dial("unix", sockpath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uc, ok := conn.(*net.UnixConn)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("casting to UnixConn failed")
|
||||
}
|
||||
t.postStart = append(t.postStart, uc)
|
||||
socket, err := uc.File()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.postStart = append(t.postStart, socket)
|
||||
process.ConsoleSocket = socket
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
// when runc will detach the caller provides the stdio to runc via runc's 0,1,2
|
||||
// and the container's process inherits runc's stdio.
|
||||
if detach {
|
||||
if err := dupStdio(process, rootuid, rootgid); err != nil {
|
||||
if err := inheritStdio(process); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tty{}, nil
|
||||
}
|
||||
return createStdioPipes(process, rootuid, rootgid)
|
||||
return setupProcessPipes(process, rootuid, rootgid)
|
||||
}
|
||||
|
||||
// createPidFile creates a file with the processes pid inside it atomically
|
||||
|
@ -167,6 +186,11 @@ func createPidFile(path string, process *libcontainer.Process) error {
|
|||
return os.Rename(tmpName, path)
|
||||
}
|
||||
|
||||
// XXX: Currently we autodetect rootless mode.
|
||||
func isRootless() bool {
|
||||
return os.Geteuid() != 0
|
||||
}
|
||||
|
||||
func createContainer(context *cli.Context, id string, spec *specs.Spec) (libcontainer.Container, error) {
|
||||
config, err := specconv.CreateLibcontainerConfig(&specconv.CreateOpts{
|
||||
CgroupName: id,
|
||||
|
@ -174,18 +198,12 @@ func createContainer(context *cli.Context, id string, spec *specs.Spec) (libcont
|
|||
NoPivotRoot: context.Bool("no-pivot"),
|
||||
NoNewKeyring: context.Bool("no-new-keyring"),
|
||||
Spec: spec,
|
||||
Rootless: isRootless(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err := os.Stat(config.Rootfs); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("rootfs (%q) does not exist", config.Rootfs)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
factory, err := loadFactory(context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -198,13 +216,19 @@ type runner struct {
|
|||
shouldDestroy bool
|
||||
detach bool
|
||||
listenFDs []*os.File
|
||||
preserveFDs int
|
||||
pidFile string
|
||||
console string
|
||||
consoleSocket string
|
||||
container libcontainer.Container
|
||||
create bool
|
||||
notifySocket *notifySocket
|
||||
}
|
||||
|
||||
func (r *runner) run(config *specs.Process) (int, error) {
|
||||
if err := r.checkTerminal(config); err != nil {
|
||||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
process, err := newProcess(*config)
|
||||
if err != nil {
|
||||
r.destroy()
|
||||
|
@ -214,55 +238,66 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
|||
process.Env = append(process.Env, fmt.Sprintf("LISTEN_FDS=%d", len(r.listenFDs)), "LISTEN_PID=1")
|
||||
process.ExtraFiles = append(process.ExtraFiles, r.listenFDs...)
|
||||
}
|
||||
rootuid, err := r.container.Config().HostUID()
|
||||
baseFd := 3 + len(process.ExtraFiles)
|
||||
for i := baseFd; i < baseFd+r.preserveFDs; i++ {
|
||||
process.ExtraFiles = append(process.ExtraFiles, os.NewFile(uintptr(i), "PreserveFD:"+strconv.Itoa(i)))
|
||||
}
|
||||
rootuid, err := r.container.Config().HostRootUID()
|
||||
if err != nil {
|
||||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
rootgid, err := r.container.Config().HostGID()
|
||||
rootgid, err := r.container.Config().HostRootGID()
|
||||
if err != nil {
|
||||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
tty, err := setupIO(process, rootuid, rootgid, r.console, config.Terminal, r.detach || r.create)
|
||||
if err != nil {
|
||||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
handler := newSignalHandler(tty, r.enableSubreaper)
|
||||
startFn := r.container.Start
|
||||
var (
|
||||
detach = r.detach || r.create
|
||||
startFn = r.container.Start
|
||||
)
|
||||
if !r.create {
|
||||
startFn = r.container.Run
|
||||
}
|
||||
if err := startFn(process); err != nil {
|
||||
// Setting up IO is a two stage process. We need to modify process to deal
|
||||
// with detaching containers, and then we get a tty after the container has
|
||||
// started.
|
||||
handler := newSignalHandler(r.enableSubreaper, r.notifySocket)
|
||||
tty, err := setupIO(process, rootuid, rootgid, config.Terminal, detach, r.consoleSocket)
|
||||
if err != nil {
|
||||
r.destroy()
|
||||
tty.Close()
|
||||
return -1, err
|
||||
}
|
||||
if err := tty.ClosePostStart(); err != nil {
|
||||
defer tty.Close()
|
||||
if err = startFn(process); err != nil {
|
||||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
if err := tty.waitConsole(); err != nil {
|
||||
r.terminate(process)
|
||||
r.destroy()
|
||||
return -1, err
|
||||
}
|
||||
if err = tty.ClosePostStart(); err != nil {
|
||||
r.terminate(process)
|
||||
r.destroy()
|
||||
tty.Close()
|
||||
return -1, err
|
||||
}
|
||||
if r.pidFile != "" {
|
||||
if err := createPidFile(r.pidFile, process); err != nil {
|
||||
if err = createPidFile(r.pidFile, process); err != nil {
|
||||
r.terminate(process)
|
||||
r.destroy()
|
||||
tty.Close()
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
if r.detach || r.create {
|
||||
tty.Close()
|
||||
return 0, nil
|
||||
}
|
||||
status, err := handler.forward(process)
|
||||
status, err := handler.forward(process, tty, detach)
|
||||
if err != nil {
|
||||
r.terminate(process)
|
||||
}
|
||||
if detach {
|
||||
return 0, nil
|
||||
}
|
||||
r.destroy()
|
||||
tty.Close()
|
||||
return status, err
|
||||
}
|
||||
|
||||
|
@ -273,8 +308,20 @@ func (r *runner) destroy() {
|
|||
}
|
||||
|
||||
func (r *runner) terminate(p *libcontainer.Process) {
|
||||
p.Signal(syscall.SIGKILL)
|
||||
p.Wait()
|
||||
_ = p.Signal(syscall.SIGKILL)
|
||||
_, _ = p.Wait()
|
||||
}
|
||||
|
||||
func (r *runner) checkTerminal(config *specs.Process) error {
|
||||
detach := r.detach || r.create
|
||||
// Check command-line for sanity.
|
||||
if detach && config.Terminal && r.consoleSocket == "" {
|
||||
return fmt.Errorf("cannot allocate tty if runc will detach without setting console socket")
|
||||
}
|
||||
if (!detach || !config.Terminal) && r.consoleSocket != "" {
|
||||
return fmt.Errorf("cannot use console socket if runc will not detach or allocate tty")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateProcessSpec(spec *specs.Process) error {
|
||||
|
@ -295,11 +342,21 @@ func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, e
|
|||
if id == "" {
|
||||
return -1, errEmptyID
|
||||
}
|
||||
|
||||
notifySocket := newNotifySocket(context, os.Getenv("NOTIFY_SOCKET"), id)
|
||||
if notifySocket != nil {
|
||||
notifySocket.setupSpec(context, spec)
|
||||
}
|
||||
|
||||
container, err := createContainer(context, id, spec)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
detach := context.Bool("detach")
|
||||
|
||||
if notifySocket != nil {
|
||||
notifySocket.setupSocket()
|
||||
}
|
||||
|
||||
// Support on-demand socket activation by passing file descriptors into the container init process.
|
||||
listenFDs := []*os.File{}
|
||||
if os.Getenv("LISTEN_FDS") != "" {
|
||||
|
@ -310,9 +367,11 @@ func startContainer(context *cli.Context, spec *specs.Spec, create bool) (int, e
|
|||
shouldDestroy: true,
|
||||
container: container,
|
||||
listenFDs: listenFDs,
|
||||
console: context.String("console"),
|
||||
detach: detach,
|
||||
notifySocket: notifySocket,
|
||||
consoleSocket: context.String("console-socket"),
|
||||
detach: context.Bool("detach"),
|
||||
pidFile: context.String("pid-file"),
|
||||
preserveFDs: context.Int("preserve-fds"),
|
||||
create: create,
|
||||
}
|
||||
return r.run(&spec.Process)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue