setns_init_linux.go 3.4 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// +build linux

package libcontainer

import (
	"fmt"
	"os"
	"runtime"

	"github.com/opencontainers/runc/libcontainer/apparmor"
	"github.com/opencontainers/runc/libcontainer/keys"
	"github.com/opencontainers/runc/libcontainer/seccomp"
	"github.com/opencontainers/runc/libcontainer/system"
	"github.com/opencontainers/runc/libenclave"
	"github.com/opencontainers/selinux/go-selinux/label"
	"github.com/pkg/errors"
jia zhang's avatar
jia zhang 已提交
17
	"github.com/sirupsen/logrus"
18 19 20 21 22 23 24 25 26 27 28 29 30

	"golang.org/x/sys/unix"
)

// linuxSetnsInit performs the container's initialization for running a new process
// inside an existing container.
type linuxSetnsInit struct {
	pipe          *os.File
	consoleSocket *os.File
	config        *initConfig
	logPipe       *os.File
	logLevel      string
	agentPipe     *os.File
31
	detached      bool
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
}

func (l *linuxSetnsInit) getSessionRingName() string {
	return fmt.Sprintf("_ses.%s", l.config.ContainerId)
}

func (l *linuxSetnsInit) Init() error {
	runtime.LockOSThread()
	defer runtime.UnlockOSThread()

	if !l.config.Config.NoNewKeyring {
		if err := label.SetKeyLabel(l.config.ProcessLabel); err != nil {
			return err
		}
		defer label.SetKeyLabel("")
		// Do not inherit the parent's session keyring.
		if _, err := keys.JoinSessionKeyring(l.getSessionRingName()); err != nil {
			// Same justification as in standart_init_linux.go as to why we
			// don't bail on ENOSYS.
			//
			// TODO(cyphar): And we should have logging here too.
			if errors.Cause(err) != unix.ENOSYS {
				return errors.Wrap(err, "join session keyring")
			}
		}
	}
	if l.config.CreateConsole {
		if err := setupConsole(l.consoleSocket, l.config, false); err != nil {
			return err
		}
		if err := system.Setctty(); err != nil {
			return err
		}
	}
	if l.config.NoNewPrivileges {
		if err := unix.Prctl(unix.PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); err != nil {
			return err
		}
	}
	if err := label.SetProcessLabel(l.config.ProcessLabel); err != nil {
		return err
	}
	defer label.SetProcessLabel("")
	// Without NoNewPrivileges seccomp is a privileged operation, so we need to
	// do this before dropping capabilities; otherwise do it as late as possible
	// just before execve so as few syscalls take place after it as possible.
	if l.config.Config.Seccomp != nil && !l.config.NoNewPrivileges {
		if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil {
			return err
		}
	}
	if err := finalizeNamespace(l.config); err != nil {
		return err
	}
	if err := apparmor.ApplyProfile(l.config.AppArmorProfile); err != nil {
		return err
	}
	// Set seccomp as close to execve as possible, so as few syscalls take
	// place afterward (reducing the amount of syscalls that users need to
	// enable in their seccomp profiles).
	if l.config.Config.Seccomp != nil && l.config.NoNewPrivileges {
		if err := seccomp.InitSeccomp(l.config.Config.Seccomp); err != nil {
			return newSystemErrorWithCause(err, "init seccomp")
		}
	}
	if l.config.Config.Enclave != nil {
jia zhang's avatar
jia zhang 已提交
98 99 100 101 102 103 104
		cfg := &libenclave.RuneletConfig{
			InitPipe:  l.pipe,
			LogPipe:   l.logPipe,
			LogLevel:  l.logLevel,
			FifoFd:    -1,
			AgentPipe: l.agentPipe,
			Detached:  l.detached,
105
		}
106

jia zhang's avatar
jia zhang 已提交
107
		exitCode, err := libenclave.StartInitialization(l.config.Args, cfg)
108 109 110 111
		if err != nil {
			logrus.Fatal(err)
			os.Exit(1)
		}
jia zhang's avatar
jia zhang 已提交
112
		logrus.Debugf("enclave payload exit code: %d", exitCode)
113 114
		os.Exit(int(exitCode))
		// make compiler happy
jia zhang's avatar
jia zhang 已提交
115
		return fmt.Errorf("failed to initialize runelet")
116 117 118
	}
	return system.Execv(l.config.Args[0], l.config.Args[0:], os.Environ())
}