浏览代码

Update runc/libcontainer to v0.0.6

Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
Mrunal Patel 9 年之前
父节点
当前提交
e8f7d5885d
共有 20 个文件被更改,包括 265 次插入81 次删除
  1. 2 0
      daemon/execdriver/native/driver.go
  2. 8 0
      daemon/execdriver/native/template/default_template_linux.go
  3. 1 1
      hack/vendor.sh
  4. 9 0
      vendor/src/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_disabled.go
  5. 5 5
      vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go
  6. 2 2
      vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_unix.go
  7. 6 0
      vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go
  8. 2 2
      vendor/src/github.com/opencontainers/runc/libcontainer/console_freebsd.go
  9. 2 2
      vendor/src/github.com/opencontainers/runc/libcontainer/console_linux.go
  10. 2 2
      vendor/src/github.com/opencontainers/runc/libcontainer/console_windows.go
  11. 41 15
      vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go
  12. 3 0
      vendor/src/github.com/opencontainers/runc/libcontainer/error.go
  13. 60 0
      vendor/src/github.com/opencontainers/runc/libcontainer/message_linux.go
  14. 2 2
      vendor/src/github.com/opencontainers/runc/libcontainer/network_linux.go
  15. 75 21
      vendor/src/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c
  16. 10 1
      vendor/src/github.com/opencontainers/runc/libcontainer/process.go
  17. 18 12
      vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go
  18. 1 0
      vendor/src/github.com/opencontainers/specs/.travis.yml
  19. 15 15
      vendor/src/github.com/opencontainers/specs/ROADMAP.md
  20. 1 1
      vendor/src/github.com/opencontainers/specs/code-of-conduct.md

+ 2 - 0
daemon/execdriver/native/driver.go

@@ -16,6 +16,7 @@ import (
 
 
 	"github.com/Sirupsen/logrus"
 	"github.com/Sirupsen/logrus"
 	"github.com/docker/docker/daemon/execdriver"
 	"github.com/docker/docker/daemon/execdriver"
+	"github.com/docker/docker/daemon/execdriver/native/template"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/parsers"
 	"github.com/docker/docker/pkg/pools"
 	"github.com/docker/docker/pkg/pools"
 	"github.com/docker/docker/pkg/reexec"
 	"github.com/docker/docker/pkg/reexec"
@@ -89,6 +90,7 @@ func NewDriver(root string, options []string) (*Driver, error) {
 			case "systemd":
 			case "systemd":
 				if systemd.UseSystemd() {
 				if systemd.UseSystemd() {
 					cgm = libcontainer.SystemdCgroups
 					cgm = libcontainer.SystemdCgroups
+					template.SystemdCgroups = true
 				} else {
 				} else {
 					// warn them that they chose the wrong driver
 					// warn them that they chose the wrong driver
 					logrus.Warn("You cannot use systemd as native.cgroupdriver, using cgroupfs instead")
 					logrus.Warn("You cannot use systemd as native.cgroupdriver, using cgroupfs instead")

+ 8 - 0
daemon/execdriver/native/template/default_template_linux.go

@@ -9,6 +9,9 @@ import (
 
 
 const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
 const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV
 
 
+// SystemdCgroups indicates whether systemd cgroup implemenation is in use or not
+var SystemdCgroups = false
+
 // New returns the docker default configuration for libcontainer
 // New returns the docker default configuration for libcontainer
 func New() *configs.Config {
 func New() *configs.Config {
 	container := &configs.Config{
 	container := &configs.Config{
@@ -94,5 +97,10 @@ func New() *configs.Config {
 		container.AppArmorProfile = "docker-default"
 		container.AppArmorProfile = "docker-default"
 	}
 	}
 
 
+	if SystemdCgroups {
+		container.Cgroups.Parent = "system.slice"
+		container.Cgroups.ScopePrefix = "docker"
+	}
+
 	return container
 	return container
 }
 }

+ 1 - 1
hack/vendor.sh

@@ -49,7 +49,7 @@ clone git github.com/miekg/pkcs11 80f102b5cac759de406949c47f0928b99bd64cdf
 clone git github.com/jfrazelle/go v1.5.1-1
 clone git github.com/jfrazelle/go v1.5.1-1
 clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
 clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c
 
 
-clone git github.com/opencontainers/runc v0.0.5 # libcontainer
+clone git github.com/opencontainers/runc v0.0.6 # libcontainer
 clone git github.com/opencontainers/specs 46d949ea81080c5f60dfb72ee91468b1e9fb2998 # specs
 clone git github.com/opencontainers/specs 46d949ea81080c5f60dfb72ee91468b1e9fb2998 # specs
 clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
 clone git github.com/seccomp/libseccomp-golang 1b506fc7c24eec5a3693cdcbed40d9c226cfc6a1
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)
 # libcontainer deps (see src/github.com/opencontainers/runc/Godeps/Godeps.json)

+ 9 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/apparmor/apparmor_disabled.go

@@ -2,10 +2,19 @@
 
 
 package apparmor
 package apparmor
 
 
+import (
+	"errors"
+)
+
+var ErrApparmorNotEnabled = errors.New("apparmor: config provided but apparmor not supported")
+
 func IsEnabled() bool {
 func IsEnabled() bool {
 	return false
 	return false
 }
 }
 
 
 func ApplyProfile(name string) error {
 func ApplyProfile(name string) error {
+	if name != "" {
+		return ErrApparmorNotEnabled
+	}
 	return nil
 	return nil
 }
 }

+ 5 - 5
vendor/src/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go

@@ -167,8 +167,8 @@ func (m *Manager) Apply(pid int) error {
 		properties []systemdDbus.Property
 		properties []systemdDbus.Property
 	)
 	)
 
 
-	if c.Slice != "" {
-		slice = c.Slice
+	if c.Parent != "" {
+		slice = c.Parent
 	}
 	}
 
 
 	properties = append(properties,
 	properties = append(properties,
@@ -406,8 +406,8 @@ func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
 	}
 	}
 
 
 	slice := "system.slice"
 	slice := "system.slice"
-	if c.Slice != "" {
-		slice = c.Slice
+	if c.Parent != "" {
+		slice = c.Parent
 	}
 	}
 
 
 	return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil
 	return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil
@@ -472,7 +472,7 @@ func (m *Manager) Set(container *configs.Config) error {
 }
 }
 
 
 func getUnitName(c *configs.Cgroup) string {
 func getUnitName(c *configs.Cgroup) string {
-	return fmt.Sprintf("%s-%s.scope", c.Parent, c.Name)
+	return fmt.Sprintf("%s-%s.scope", c.ScopePrefix, c.Name)
 }
 }
 
 
 // Atm we can't use the systemd device support because of two missing things:
 // Atm we can't use the systemd device support because of two missing things:

+ 2 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_unix.go

@@ -83,8 +83,8 @@ type Cgroup struct {
 	// Hugetlb limit (in bytes)
 	// Hugetlb limit (in bytes)
 	HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"`
 	HugetlbLimit []*HugepageLimit `json:"hugetlb_limit"`
 
 
-	// Parent slice to use for systemd TODO: remove in favor or parent
-	Slice string `json:"slice"`
+	// ScopePrefix decribes prefix for the scope name
+	ScopePrefix string `json:"scope_prefix"`
 
 
 	// Whether to disable OOM Killer
 	// Whether to disable OOM Killer
 	OomKillDisable bool `json:"oom_kill_disable"`
 	OomKillDisable bool `json:"oom_kill_disable"`

+ 6 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/configs/cgroup_unsupported.go

@@ -0,0 +1,6 @@
+// +build !windows,!linux,!freebsd
+
+package configs
+
+type Cgroup struct {
+}

+ 2 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/console_freebsd.go

@@ -6,8 +6,8 @@ import (
 	"errors"
 	"errors"
 )
 )
 
 
-// newConsole returns an initalized console that can be used within a container by copying bytes
+// NewConsole returns an initalized console that can be used within a container by copying bytes
 // from the master side to the slave that is attached as the tty for the container's init process.
 // from the master side to the slave that is attached as the tty for the container's init process.
-func newConsole(uid, gid int) (Console, error) {
+func NewConsole(uid, gid int) (Console, error) {
 	return nil, errors.New("libcontainer console is not supported on FreeBSD")
 	return nil, errors.New("libcontainer console is not supported on FreeBSD")
 }
 }

+ 2 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/console_linux.go

@@ -10,9 +10,9 @@ import (
 	"github.com/opencontainers/runc/libcontainer/label"
 	"github.com/opencontainers/runc/libcontainer/label"
 )
 )
 
 
-// newConsole returns an initalized console that can be used within a container by copying bytes
+// NewConsole returns an initalized console that can be used within a container by copying bytes
 // from the master side to the slave that is attached as the tty for the container's init process.
 // from the master side to the slave that is attached as the tty for the container's init process.
-func newConsole(uid, gid int) (Console, error) {
+func NewConsole(uid, gid int) (Console, error) {
 	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
 	master, err := os.OpenFile("/dev/ptmx", syscall.O_RDWR|syscall.O_NOCTTY|syscall.O_CLOEXEC, 0)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err

+ 2 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/console_windows.go

@@ -1,7 +1,7 @@
 package libcontainer
 package libcontainer
 
 
-// newConsole returns an initalized console that can be used within a container
-func newConsole(uid, gid int) (Console, error) {
+// NewConsole returns an initalized console that can be used within a container
+func NewConsole(uid, gid int) (Console, error) {
 	return &windowsConsole{}, nil
 	return &windowsConsole{}, nil
 }
 }
 
 

+ 41 - 15
vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go

@@ -3,8 +3,10 @@
 package libcontainer
 package libcontainer
 
 
 import (
 import (
+	"bytes"
 	"encoding/json"
 	"encoding/json"
 	"fmt"
 	"fmt"
+	"io"
 	"io/ioutil"
 	"io/ioutil"
 	"os"
 	"os"
 	"os/exec"
 	"os/exec"
@@ -19,6 +21,7 @@ import (
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/cgroups"
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/configs"
 	"github.com/opencontainers/runc/libcontainer/criurpc"
 	"github.com/opencontainers/runc/libcontainer/criurpc"
+	"github.com/vishvananda/netlink/nl"
 )
 )
 
 
 const stdioFdCount = 3
 const stdioFdCount = 3
@@ -218,7 +221,7 @@ func (c *linuxContainer) newParentProcess(p *Process, doInit bool) (parentProces
 		return nil, newSystemError(err)
 		return nil, newSystemError(err)
 	}
 	}
 	if !doInit {
 	if !doInit {
-		return c.newSetnsProcess(p, cmd, parentPipe, childPipe), nil
+		return c.newSetnsProcess(p, cmd, parentPipe, childPipe)
 	}
 	}
 	return c.newInitProcess(p, cmd, parentPipe, childPipe)
 	return c.newInitProcess(p, cmd, parentPipe, childPipe)
 }
 }
@@ -273,23 +276,24 @@ func (c *linuxContainer) newInitProcess(p *Process, cmd *exec.Cmd, parentPipe, c
 	}, nil
 	}, nil
 }
 }
 
 
-func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe, childPipe *os.File) *setnsProcess {
-	cmd.Env = append(cmd.Env,
-		fmt.Sprintf("_LIBCONTAINER_INITPID=%d", c.initProcess.pid()),
-		"_LIBCONTAINER_INITTYPE=setns",
-	)
-	if p.consolePath != "" {
-		cmd.Env = append(cmd.Env, "_LIBCONTAINER_CONSOLE_PATH="+p.consolePath)
+func (c *linuxContainer) newSetnsProcess(p *Process, cmd *exec.Cmd, parentPipe, childPipe *os.File) (*setnsProcess, error) {
+	cmd.Env = append(cmd.Env, "_LIBCONTAINER_INITTYPE=setns")
+	// for setns process, we dont have to set cloneflags as the process namespaces
+	// will only be set via setns syscall
+	data, err := c.bootstrapData(0, c.initProcess.pid(), p.consolePath)
+	if err != nil {
+		return nil, err
 	}
 	}
 	// TODO: set on container for process management
 	// TODO: set on container for process management
 	return &setnsProcess{
 	return &setnsProcess{
-		cmd:         cmd,
-		cgroupPaths: c.cgroupManager.GetPaths(),
-		childPipe:   childPipe,
-		parentPipe:  parentPipe,
-		config:      c.newInitConfig(p),
-		process:     p,
-	}
+		cmd:           cmd,
+		cgroupPaths:   c.cgroupManager.GetPaths(),
+		childPipe:     childPipe,
+		parentPipe:    parentPipe,
+		config:        c.newInitConfig(p),
+		process:       p,
+		bootstrapData: data,
+	}, nil
 }
 }
 
 
 func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
 func (c *linuxContainer) newInitConfig(process *Process) *initConfig {
@@ -1021,3 +1025,25 @@ func (c *linuxContainer) currentState() (*State, error) {
 	}
 	}
 	return state, nil
 	return state, nil
 }
 }
+
+// bootstrapData encodes the necessary data in netlink binary format as a io.Reader.
+// Consumer can write the data to a bootstrap program such as one that uses
+// nsenter package to bootstrap the container's init process correctly, i.e. with
+// correct namespaces, uid/gid mapping etc.
+func (c *linuxContainer) bootstrapData(cloneFlags uintptr, pid int, consolePath string) (io.Reader, error) {
+	// create the netlink message
+	r := nl.NewNetlinkRequest(int(InitMsg), 0)
+	// write pid
+	r.AddData(&Int32msg{
+		Type:  PidAttr,
+		Value: uint32(pid),
+	})
+	// write console path
+	if consolePath != "" {
+		r.AddData(&Bytemsg{
+			Type:  ConsolePathAttr,
+			Value: []byte(consolePath),
+		})
+	}
+	return bytes.NewReader(r.Serialize()), nil
+}

+ 3 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/error.go

@@ -22,6 +22,7 @@ const (
 
 
 	// Common errors
 	// Common errors
 	ConfigInvalid
 	ConfigInvalid
+	ConsoleExists
 	SystemError
 	SystemError
 )
 )
 
 
@@ -43,6 +44,8 @@ func (c ErrorCode) String() string {
 		return "Container is not stopped"
 		return "Container is not stopped"
 	case ContainerNotRunning:
 	case ContainerNotRunning:
 		return "Container is not running"
 		return "Container is not running"
+	case ConsoleExists:
+		return "Console exists for process"
 	default:
 	default:
 		return "Unknown error"
 		return "Unknown error"
 	}
 	}

+ 60 - 0
vendor/src/github.com/opencontainers/runc/libcontainer/message_linux.go

@@ -0,0 +1,60 @@
+// +build linux
+
+package libcontainer
+
+import (
+	"syscall"
+
+	"github.com/vishvananda/netlink/nl"
+)
+
+// list of known message types we want to send to bootstrap program
+// The number is randomly chosen to not conflict with known netlink types
+const (
+	InitMsg         uint16 = 62000
+	PidAttr         uint16 = 27281
+	ConsolePathAttr uint16 = 27282
+)
+
+type Int32msg struct {
+	Type  uint16
+	Value uint32
+}
+
+// int32msg has the following representation
+// | nlattr len | nlattr type |
+// | uint32 value             |
+func (msg *Int32msg) Serialize() []byte {
+	buf := make([]byte, msg.Len())
+	native := nl.NativeEndian()
+	native.PutUint16(buf[0:2], uint16(msg.Len()))
+	native.PutUint16(buf[2:4], msg.Type)
+	native.PutUint32(buf[4:8], msg.Value)
+	return buf
+}
+
+func (msg *Int32msg) Len() int {
+	return syscall.NLA_HDRLEN + 4
+}
+
+// bytemsg has the following representation
+// | nlattr len | nlattr type |
+// | value              | pad |
+type Bytemsg struct {
+	Type  uint16
+	Value []byte
+}
+
+func (msg *Bytemsg) Serialize() []byte {
+	l := msg.Len()
+	buf := make([]byte, (l+syscall.NLA_ALIGNTO-1) & ^(syscall.NLA_ALIGNTO-1))
+	native := nl.NativeEndian()
+	native.PutUint16(buf[0:2], uint16(l))
+	native.PutUint16(buf[2:4], msg.Type)
+	copy(buf[4:], msg.Value)
+	return buf
+}
+
+func (msg *Bytemsg) Len() int {
+	return syscall.NLA_HDRLEN + len(msg.Value) + 1 // null-terminated
+}

+ 2 - 2
vendor/src/github.com/opencontainers/runc/libcontainer/network_linux.go

@@ -93,7 +93,7 @@ func (l *loopback) create(n *network, nspid int) error {
 }
 }
 
 
 func (l *loopback) initialize(config *network) error {
 func (l *loopback) initialize(config *network) error {
-	return netlink.LinkSetUp(&netlink.Device{netlink.LinkAttrs{Name: "lo"}})
+	return netlink.LinkSetUp(&netlink.Device{LinkAttrs: netlink.LinkAttrs{Name: "lo"}})
 }
 }
 
 
 func (l *loopback) attach(n *configs.Network) (err error) {
 func (l *loopback) attach(n *configs.Network) (err error) {
@@ -111,7 +111,7 @@ type veth struct {
 }
 }
 
 
 func (v *veth) detach(n *configs.Network) (err error) {
 func (v *veth) detach(n *configs.Network) (err error) {
-	return netlink.LinkSetMaster(&netlink.Device{netlink.LinkAttrs{Name: n.HostInterfaceName}}, nil)
+	return netlink.LinkSetMaster(&netlink.Device{LinkAttrs: netlink.LinkAttrs{Name: n.HostInterfaceName}}, nil)
 }
 }
 
 
 // attach a container network interface to an external network
 // attach a container network interface to an external network

+ 75 - 21
vendor/src/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c

@@ -17,6 +17,11 @@
 #include <sched.h>
 #include <sched.h>
 #include <signal.h>
 #include <signal.h>
 
 
+#include <linux/netlink.h>
+#include <linux/types.h>
+#include <stdint.h>
+#include <sys/socket.h>
+
 /* All arguments should be above stack, because it grows down */
 /* All arguments should be above stack, because it grows down */
 struct clone_arg {
 struct clone_arg {
 	/*
 	/*
@@ -63,24 +68,33 @@ static int clone_parent(jmp_buf * env)
 	return child;
 	return child;
 }
 }
 
 
+static uint32_t readint32(char *buf)
+{
+	return *(uint32_t *) buf;
+}
+
+// list of known message types we want to send to bootstrap program
+// These are defined in libcontainer/message_linux.go
+#define INIT_MSG 62000
+#define PID_ATTR 27281
+#define CONSOLE_PATH_ATTR 27282
+
 void nsexec()
 void nsexec()
 {
 {
 	char *namespaces[] = { "ipc", "uts", "net", "pid", "mnt", "user" };
 	char *namespaces[] = { "ipc", "uts", "net", "pid", "mnt", "user" };
 	const int num = sizeof(namespaces) / sizeof(char *);
 	const int num = sizeof(namespaces) / sizeof(char *);
 	jmp_buf env;
 	jmp_buf env;
 	char buf[PATH_MAX], *val;
 	char buf[PATH_MAX], *val;
-	int i, tfd, self_tfd, child, len, pipenum, consolefd = -1;
-	pid_t pid;
-	char *console;
+	int i, tfd, self_tfd, child, n, len, pipenum, consolefd = -1;
+	pid_t pid = 0;
 
 
-	val = getenv("_LIBCONTAINER_INITPID");
-	if (val == NULL)
+	// if we dont have INITTYPE or this is the init process, skip the bootstrap process
+	val = getenv("_LIBCONTAINER_INITTYPE");
+	if (val == NULL || strcmp(val, "standard") == 0) {
 		return;
 		return;
-
-	pid = atoi(val);
-	snprintf(buf, sizeof(buf), "%d", pid);
-	if (strcmp(val, buf)) {
-		pr_perror("Unable to parse _LIBCONTAINER_INITPID");
+	}
+	if (strcmp(val, "setns") != 0) {
+		pr_perror("Invalid inittype %s", val);
 		exit(1);
 		exit(1);
 	}
 	}
 
 
@@ -89,7 +103,6 @@ void nsexec()
 		pr_perror("Child pipe not found");
 		pr_perror("Child pipe not found");
 		exit(1);
 		exit(1);
 	}
 	}
-
 	pipenum = atoi(val);
 	pipenum = atoi(val);
 	snprintf(buf, sizeof(buf), "%d", pipenum);
 	snprintf(buf, sizeof(buf), "%d", pipenum);
 	if (strcmp(val, buf)) {
 	if (strcmp(val, buf)) {
@@ -97,13 +110,56 @@ void nsexec()
 		exit(1);
 		exit(1);
 	}
 	}
 
 
-	console = getenv("_LIBCONTAINER_CONSOLE_PATH");
-	if (console != NULL) {
-		consolefd = open(console, O_RDWR);
-		if (consolefd < 0) {
-			pr_perror("Failed to open console %s", console);
-			exit(1);
+	char nlbuf[NLMSG_HDRLEN];
+	struct nlmsghdr *nh;
+	if ((n = read(pipenum, nlbuf, NLMSG_HDRLEN)) != NLMSG_HDRLEN) {
+		pr_perror("Failed to read netlink header, got %d", n);
+		exit(1);
+	}
+
+	nh = (struct nlmsghdr *)nlbuf;
+	if (nh->nlmsg_type == NLMSG_ERROR) {
+		pr_perror("Invalid netlink header message");
+		exit(1);
+	}
+	if (nh->nlmsg_type != INIT_MSG) {
+		pr_perror("Unexpected netlink message type %d", nh->nlmsg_type);
+		exit(1);
+	}
+	// read the netlink payload
+	len = NLMSG_PAYLOAD(nh, 0);
+	char data[len];
+	if ((n = read(pipenum, data, len)) != len) {
+		pr_perror("Failed to read netlink payload, got %d", n);
+		exit(1);
+	}
+
+	int start = 0;
+	struct nlattr *attr;
+	while (start < len) {
+		int payload_len;
+		attr = (struct nlattr *)((void *)data + start);
+		start += NLA_HDRLEN;
+		payload_len = attr->nla_len - NLA_HDRLEN;
+		switch (attr->nla_type) {
+		case PID_ATTR:
+			pid = (pid_t) readint32(data + start);
+			break;
+		case CONSOLE_PATH_ATTR:
+			consolefd = open((char *)data + start, O_RDWR);
+			if (consolefd < 0) {
+				pr_perror("Failed to open console %s", (char *)data + start);
+				exit(1);
+			}
+			break;
 		}
 		}
+		start += NLA_ALIGN(payload_len);
+	}
+
+	// required pid to be passed
+	if (pid == 0) {
+		pr_perror("missing pid");
+		exit(1);
 	}
 	}
 
 
 	/* Check that the specified process exists */
 	/* Check that the specified process exists */
@@ -133,15 +189,13 @@ void nsexec()
 		}
 		}
 
 
 		/* Skip namespaces we're already part of */
 		/* Skip namespaces we're already part of */
-		if (fstatat(self_tfd, namespaces[i], &self_st, 0) != -1 &&
-		    st.st_ino == self_st.st_ino) {
+		if (fstatat(self_tfd, namespaces[i], &self_st, 0) != -1 && st.st_ino == self_st.st_ino) {
 			continue;
 			continue;
 		}
 		}
 
 
 		fd = openat(tfd, namespaces[i], O_RDONLY);
 		fd = openat(tfd, namespaces[i], O_RDONLY);
 		if (fd == -1) {
 		if (fd == -1) {
-			pr_perror("Failed to open ns file %s for ns %s", buf,
-				  namespaces[i]);
+			pr_perror("Failed to open ns file %s for ns %s", buf, namespaces[i]);
 			exit(1);
 			exit(1);
 		}
 		}
 		// Set the namespace.
 		// Set the namespace.

+ 10 - 1
vendor/src/github.com/opencontainers/runc/libcontainer/process.go

@@ -80,10 +80,19 @@ func (p Process) Signal(sig os.Signal) error {
 
 
 // NewConsole creates new console for process and returns it
 // NewConsole creates new console for process and returns it
 func (p *Process) NewConsole(rootuid int) (Console, error) {
 func (p *Process) NewConsole(rootuid int) (Console, error) {
-	console, err := newConsole(rootuid, rootuid)
+	console, err := NewConsole(rootuid, rootuid)
 	if err != nil {
 	if err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	p.consolePath = console.Path()
 	p.consolePath = console.Path()
 	return console, nil
 	return console, nil
 }
 }
+
+// ConsoleFromPath sets the process's console with the path provided
+func (p *Process) ConsoleFromPath(path string) error {
+	if p.consolePath != "" {
+		return newGenericError(fmt.Errorf("console path already exists for process"), ConsoleExists)
+	}
+	p.consolePath = path
+	return nil
+}

+ 18 - 12
vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go

@@ -41,13 +41,14 @@ type parentProcess interface {
 }
 }
 
 
 type setnsProcess struct {
 type setnsProcess struct {
-	cmd         *exec.Cmd
-	parentPipe  *os.File
-	childPipe   *os.File
-	cgroupPaths map[string]string
-	config      *initConfig
-	fds         []string
-	process     *Process
+	cmd           *exec.Cmd
+	parentPipe    *os.File
+	childPipe     *os.File
+	cgroupPaths   map[string]string
+	config        *initConfig
+	fds           []string
+	process       *Process
+	bootstrapData io.Reader
 }
 }
 
 
 func (p *setnsProcess) startTime() (string, error) {
 func (p *setnsProcess) startTime() (string, error) {
@@ -64,6 +65,16 @@ func (p *setnsProcess) signal(sig os.Signal) error {
 
 
 func (p *setnsProcess) start() (err error) {
 func (p *setnsProcess) start() (err error) {
 	defer p.parentPipe.Close()
 	defer p.parentPipe.Close()
+	err = p.cmd.Start()
+	p.childPipe.Close()
+	if err != nil {
+		return newSystemError(err)
+	}
+	if p.bootstrapData != nil {
+		if _, err := io.Copy(p.parentPipe, p.bootstrapData); err != nil {
+			return newSystemError(err)
+		}
+	}
 	if err = p.execSetns(); err != nil {
 	if err = p.execSetns(); err != nil {
 		return newSystemError(err)
 		return newSystemError(err)
 	}
 	}
@@ -96,11 +107,6 @@ func (p *setnsProcess) start() (err error) {
 // before the go runtime boots, we wait on the process to die and receive the child's pid
 // before the go runtime boots, we wait on the process to die and receive the child's pid
 // over the provided pipe.
 // over the provided pipe.
 func (p *setnsProcess) execSetns() error {
 func (p *setnsProcess) execSetns() error {
-	err := p.cmd.Start()
-	p.childPipe.Close()
-	if err != nil {
-		return newSystemError(err)
-	}
 	status, err := p.cmd.Process.Wait()
 	status, err := p.cmd.Process.Wait()
 	if err != nil {
 	if err != nil {
 		p.cmd.Wait()
 		p.cmd.Wait()

+ 1 - 0
vendor/src/github.com/opencontainers/specs/.travis.yml

@@ -17,3 +17,4 @@ script:
   - go vet -x ./...
   - go vet -x ./...
   - $HOME/gopath/bin/golint ./...
   - $HOME/gopath/bin/golint ./...
   - $HOME/gopath/bin/git-validation -run DCO,short-subject -v -range ${TRAVIS_COMMIT_RANGE}
   - $HOME/gopath/bin/git-validation -run DCO,short-subject -v -range ${TRAVIS_COMMIT_RANGE}
+  

+ 15 - 15
vendor/src/github.com/opencontainers/specs/ROADMAP.md

@@ -10,7 +10,7 @@ Topics listed in the roadmap do not mean that they will be implemented or added
 
 
 ### Digest and Hashing
 ### Digest and Hashing
 
 
-A bundle is designed to be moved between hosts.
+A bundle is designed to be moved between hosts. 
 Although OCI doesn't define a transport method we should have a cryptographic digest of the on-disk bundle that can be used to verify that a bundle is not corrupted and in an expected configuration.
 Although OCI doesn't define a transport method we should have a cryptographic digest of the on-disk bundle that can be used to verify that a bundle is not corrupted and in an expected configuration.
 
 
 *Owner:* philips
 *Owner:* philips
@@ -20,11 +20,11 @@ Although OCI doesn't define a transport method we should have a cryptographic di
 There are some discussions about having `runtime.json` being optional for containers and specifying defaults.
 There are some discussions about having `runtime.json` being optional for containers and specifying defaults.
 Runtimes would use this standard set of defaults for containers and `runtime.json` would provide overrides for fine tuning of these extra host or platform specific settings.
 Runtimes would use this standard set of defaults for containers and `runtime.json` would provide overrides for fine tuning of these extra host or platform specific settings.
 
 
-*Owner:*
+*Owner:*  
 
 
 ### Define Container Lifecycle
 ### Define Container Lifecycle
 
 
-Containers have a lifecycle and being able to identify and document the lifecycle of a container is very helpful for implementations of the spec.
+Containers have a lifecycle and being able to identify and document the lifecycle of a container is very helpful for implementations of the spec.  
 The lifecycle events of a container also help identify areas to implement hooks that are portable across various implementations and platforms.
 The lifecycle events of a container also help identify areas to implement hooks that are portable across various implementations and platforms.
 
 
 *Owner:* mrunalp
 *Owner:* mrunalp
@@ -33,27 +33,27 @@ The lifecycle events of a container also help identify areas to implement hooks
 
 
 Define what type of actions a runtime can perform on a container without imposing hardships on authors of platforms that do not support advanced options.
 Define what type of actions a runtime can perform on a container without imposing hardships on authors of platforms that do not support advanced options.
 
 
-*Owner:*
+*Owner:*  
 
 
 ### Clarify rootfs requirement in base spec
 ### Clarify rootfs requirement in base spec
 
 
 Is the rootfs needed or should it just be expected in the bundle without having a field in the spec?
 Is the rootfs needed or should it just be expected in the bundle without having a field in the spec?
 
 
-*Owner:*
+*Owner:*  
 
 
 ### Container Definition
 ### Container Definition
 
 
 Define what a software container is and its attributes in a cross platform way.
 Define what a software container is and its attributes in a cross platform way.
 
 
-*Owner:*
+*Owner:*  
 
 
 ### Live Container Updates
 ### Live Container Updates
 
 
-Should we allow dynamic container updates to runtime options?
+Should we allow dynamic container updates to runtime options? 
 
 
 *Owner:* vishh
 *Owner:* vishh
 
 
-### Protobuf Config
+### Protobuf Config 
 
 
 We currently have only one language binding for the spec and that is Go.
 We currently have only one language binding for the spec and that is Go.
 If we change the specs format in the respository to be something like protobuf then the generation for multiple language bindings become effortless.
 If we change the specs format in the respository to be something like protobuf then the generation for multiple language bindings become effortless.
@@ -62,7 +62,7 @@ If we change the specs format in the respository to be something like protobuf t
 
 
 ### Validation Tooling
 ### Validation Tooling
 
 
-Provide validation tooling for compliance with OCI spec and runtime environment.
+Provide validation tooling for compliance with OCI spec and runtime environment. 
 
 
 *Owner:* mrunalp
 *Owner:* mrunalp
 
 
@@ -70,27 +70,27 @@ Provide validation tooling for compliance with OCI spec and runtime environment.
 
 
 Decide on a robust versioning schema for the spec as it evolves.
 Decide on a robust versioning schema for the spec as it evolves.
 
 
-*Owner:*
+*Owner:*  
 
 
 ### Printable/Compiled Spec
 ### Printable/Compiled Spec
 
 
 Reguardless of how the spec is written, ensure that it is easy to read and follow for first time users.
 Reguardless of how the spec is written, ensure that it is easy to read and follow for first time users.
 
 
-*Owner:* vbatts
+*Owner:* vbatts 
 
 
 ### Base Config Compatibility
 ### Base Config Compatibility
 
 
 Ensure that the base configuration format is viable for various platforms.
 Ensure that the base configuration format is viable for various platforms.
 
 
-Systems:
+Systems: 
 
 
 * Solaris
 * Solaris
-* Windows
+* Windows 
 * Linux
 * Linux
 
 
-*Owner:*
+*Owner:* 
 
 
 ### Full Lifecycle Hooks
 ### Full Lifecycle Hooks
 Ensure that we have lifecycle hooks in the correct places with full coverage over the container lifecycle.
 Ensure that we have lifecycle hooks in the correct places with full coverage over the container lifecycle.
 
 
-*Owner:*
+*Owner:*  

+ 1 - 1
vendor/src/github.com/opencontainers/specs/code-of-conduct.md

@@ -30,7 +30,7 @@ The OpenContainers team reserves the right to deny participation any individual
 Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct.
 Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct.
 By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project.
 By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project.
 
 
-## Thanks
+## Thanks 
 
 
 Thanks to the [Fedora Code of Conduct](https://getfedora.org/code-of-conduct) and [Contributor Covenant](http://contributor-covenant.org) for inspiration and ideas.
 Thanks to the [Fedora Code of Conduct](https://getfedora.org/code-of-conduct) and [Contributor Covenant](http://contributor-covenant.org) for inspiration and ideas.