From 189d2c79858d08a4cf3454bd7367989a005a4e3b Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Tue, 22 Sep 2015 16:33:00 -0700 Subject: [PATCH] Update libcontainer to aac9179bbadbf958054ce97ab36 Signed-off-by: Michael Crosby --- hack/vendor.sh | 2 +- .../runc/libcontainer/configs/config.go | 14 ++++- .../runc/libcontainer/configs/mount.go | 45 -------------- .../runc/libcontainer/console_linux.go | 2 +- .../runc/libcontainer/container_linux.go | 5 +- .../runc/libcontainer/init_linux.go | 42 ++++++++++--- .../runc/libcontainer/nsenter/nsexec.c | 22 ++++++- .../runc/libcontainer/process_linux.go | 7 ++- .../runc/libcontainer/rootfs_linux.go | 61 +++++++++++++++---- .../libcontainer/seccomp/seccomp_linux.go | 12 ++++ 10 files changed, 133 insertions(+), 79 deletions(-) diff --git a/hack/vendor.sh b/hack/vendor.sh index fcdbe639a2..7550694b0e 100755 --- a/hack/vendor.sh +++ b/hack/vendor.sh @@ -42,7 +42,7 @@ clone git github.com/endophage/gotuf 9bcdad0308e34a49f38448b8ad436ad8860825ce clone git github.com/jfrazelle/go 6e461eb70cb4187b41a84e9a567d7137bdbe0f16 clone git github.com/agl/ed25519 d2b94fd789ea21d12fac1a4443dd3a3f79cda72c -clone git github.com/opencontainers/runc 08b5415ffa3769ff7c1d2f673f61382d69aabb7d # libcontainer +clone git github.com/opencontainers/runc aac9179bbadbf958054ce97ab368ac178140e5da # libcontainer # libcontainer deps (see src/github.com/docker/libcontainer/update-vendor.sh) clone git github.com/coreos/go-systemd v3 clone git github.com/godbus/dbus v2 diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/configs/config.go b/vendor/src/github.com/opencontainers/runc/libcontainer/configs/config.go index f26287608a..4b298e1eae 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/configs/config.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/configs/config.go @@ -20,8 +20,12 @@ type IDMap struct { } // Seccomp represents syscall restrictions +// By default, only the native architecture of the kernel is allowed to be used +// for syscalls. Additional architectures can be added by specifying them in +// Architectures. type Seccomp struct { DefaultAction Action `json:"default_action"` + Architectures []string `json:"architectures"` Syscalls []*Syscall `json:"syscalls"` } @@ -169,6 +173,9 @@ type Config struct { // Hooks are a collection of actions to perform at various container lifecycle events. // Hooks are not able to be marshaled to json but they are also not needed to. Hooks *Hooks `json:"-"` + + // Version is the version of opencontainer specification that is supported. + Version string `json:"version"` } type Hooks struct { @@ -182,9 +189,10 @@ type Hooks struct { // HookState is the payload provided to a hook on execution. type HookState struct { - ID string `json:"id"` - Pid int `json:"pid"` - Root string `json:"root"` + Version string `json:"version"` + ID string `json:"id"` + Pid int `json:"pid"` + Root string `json:"root"` } type Hook interface { diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/configs/mount.go b/vendor/src/github.com/opencontainers/runc/libcontainer/configs/mount.go index f982da14de..cc770c916f 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/configs/mount.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/configs/mount.go @@ -1,13 +1,5 @@ package configs -import ( - "path/filepath" - "strings" - "syscall" - - "github.com/opencontainers/runc/libcontainer/label" -) - type Mount struct { // Source path for the mount. Source string `json:"source"` @@ -36,40 +28,3 @@ type Mount struct { // Optional Command to be run after Source is mounted. PostmountCmds []Command `json:"postmount_cmds"` } - -func (m *Mount) Remount(rootfs string) error { - var ( - dest = m.Destination - ) - if !strings.HasPrefix(dest, rootfs) { - dest = filepath.Join(rootfs, dest) - } - - if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil { - return err - } - return nil -} - -// Do the mount operation followed by additional mounts required to take care -// of propagation flags. -func (m *Mount) MountPropagate(rootfs string, mountLabel string) error { - var ( - dest = m.Destination - data = label.FormatMountLabel(m.Data, mountLabel) - ) - if !strings.HasPrefix(dest, rootfs) { - dest = filepath.Join(rootfs, dest) - } - - if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil { - return err - } - - for _, pflag := range m.PropagationFlags { - if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil { - return err - } - } - return nil -} diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/console_linux.go b/vendor/src/github.com/opencontainers/runc/libcontainer/console_linux.go index 3ac6bfec8c..f345f572b3 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/console_linux.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/console_linux.go @@ -75,7 +75,7 @@ func (c *linuxConsole) Close() error { // mount initializes the console inside the rootfs mounting with the specified mount label // and applying the correct ownership of the console. -func (c *linuxConsole) mount(rootfs, mountLabel string, uid, gid int) error { +func (c *linuxConsole) mount(rootfs, mountLabel string) error { oldMask := syscall.Umask(0000) defer syscall.Umask(oldMask) if err := label.SetFileLabel(c.slavePath, mountLabel); err != nil { diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go b/vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go index 153c237d32..853aedf4dd 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/container_linux.go @@ -250,8 +250,9 @@ func (c *linuxContainer) Destroy() error { c.initProcess = nil if c.config.Hooks != nil { s := configs.HookState{ - ID: c.id, - Root: c.config.Rootfs, + Version: c.config.Version, + ID: c.id, + Root: c.config.Rootfs, } for _, hook := range c.config.Hooks.Poststop { if err := hook.Run(s); err != nil { diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/init_linux.go b/vendor/src/github.com/opencontainers/runc/libcontainer/init_linux.go index 0433913ab7..ddb1186595 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/init_linux.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/init_linux.go @@ -187,16 +187,10 @@ func setupUser(config *initConfig) error { return err } } - // change the permissions on the STDIO of the current process so that when the user - // is changed for the container, it's STDIO of the process matches the user. - for _, fd := range []uintptr{ - os.Stdin.Fd(), - os.Stderr.Fd(), - os.Stdout.Fd(), - } { - if err := syscall.Fchown(int(fd), execUser.Uid, execUser.Gid); err != nil { - return err - } + // before we change to the container's user make sure that the processes STDIO + // is correctly owned by the user that we are switching to. + if err := fixStdioPermissions(execUser); err != nil { + return err } suppGroups := append(execUser.Sgids, addGroups...) if err := syscall.Setgroups(suppGroups); err != nil { @@ -218,6 +212,34 @@ func setupUser(config *initConfig) error { return nil } +// fixStdioPermissions fixes the permissions of PID 1's STDIO within the container to the specified user. +// The ownership needs to match because it is created outside of the container and needs to be +// localized. +func fixStdioPermissions(u *user.ExecUser) error { + var null syscall.Stat_t + if err := syscall.Stat("/dev/null", &null); err != nil { + return err + } + for _, fd := range []uintptr{ + os.Stdin.Fd(), + os.Stderr.Fd(), + os.Stdout.Fd(), + } { + var s syscall.Stat_t + if err := syscall.Fstat(int(fd), &s); err != nil { + return err + } + // skip chown of /dev/null if it was used as one of the STDIO fds. + if s.Rdev == null.Rdev { + continue + } + if err := syscall.Fchown(int(fd), u.Uid, u.Gid); err != nil { + return err + } + } + return nil +} + // setupNetwork sets up and initializes any network interface inside the container. func setupNetwork(config *initConfig) error { for _, config := range config.Networks { diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c b/vendor/src/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c index cd02d00a0a..69b077bfb5 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/nsenter/nsexec.c @@ -65,11 +65,11 @@ static int clone_parent(jmp_buf * env) void nsexec() { - char *namespaces[] = { "ipc", "uts", "net", "pid", "mnt" }; + char *namespaces[] = { "ipc", "uts", "net", "pid", "mnt", "user" }; const int num = sizeof(namespaces) / sizeof(char *); jmp_buf env; char buf[PATH_MAX], *val; - int i, tfd, child, len, pipenum, consolefd = -1; + int i, tfd, self_tfd, child, len, pipenum, consolefd = -1; pid_t pid; char *console; @@ -114,17 +114,30 @@ void nsexec() exit(1); } + self_tfd = open("/proc/self/ns", O_DIRECTORY | O_RDONLY); + if (self_tfd == -1) { + pr_perror("Failed to open /proc/self/ns"); + exit(1); + } + for (i = 0; i < num; i++) { struct stat st; + struct stat self_st; int fd; /* Symlinks on all namespaces exist for dead processes, but they can't be opened */ - if (fstatat(tfd, namespaces[i], &st, AT_SYMLINK_NOFOLLOW) == -1) { + if (fstatat(tfd, namespaces[i], &st, 0) == -1) { // Ignore nonexistent namespaces. if (errno == ENOENT) continue; } + /* Skip namespaces we're already part of */ + if (fstatat(self_tfd, namespaces[i], &self_st, 0) != -1 && + st.st_ino == self_st.st_ino) { + continue; + } + fd = openat(tfd, namespaces[i], O_RDONLY); if (fd == -1) { pr_perror("Failed to open ns file %s for ns %s", buf, @@ -139,6 +152,9 @@ void nsexec() close(fd); } + close(self_tfd); + close(tfd); + if (setjmp(env) == 1) { // Child diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go b/vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go index f191c16ee2..0072e19483 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/process_linux.go @@ -203,9 +203,10 @@ func (p *initProcess) start() (err error) { }() if p.config.Config.Hooks != nil { s := configs.HookState{ - ID: p.container.id, - Pid: p.pid(), - Root: p.config.Config.Rootfs, + Version: p.container.config.Version, + ID: p.container.id, + Pid: p.pid(), + Root: p.config.Config.Rootfs, } for _, hook := range p.config.Config.Hooks.Prestart { if err := hook.Run(s); err != nil { diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/rootfs_linux.go b/vendor/src/github.com/opencontainers/runc/libcontainer/rootfs_linux.go index 51f961dfaf..3e3a7d2e02 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/rootfs_linux.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/rootfs_linux.go @@ -68,7 +68,7 @@ func setupRootfs(config *configs.Config, console *linuxConsole) (err error) { return newSystemError(err) } if !setupDev { - if err := reOpenDevNull(config.Rootfs); err != nil { + if err := reOpenDevNull(); err != nil { return newSystemError(err) } } @@ -106,12 +106,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { if err := os.MkdirAll(dest, 0755); err != nil { return err } - return m.MountPropagate(rootfs, mountLabel) + return mountPropagate(m, rootfs, mountLabel) case "mqueue": if err := os.MkdirAll(dest, 0755); err != nil { return err } - if err := m.MountPropagate(rootfs, mountLabel); err != nil { + if err := mountPropagate(m, rootfs, mountLabel); err != nil { return err } return label.SetFileLabel(dest, mountLabel) @@ -122,7 +122,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { return err } } - if err := m.MountPropagate(rootfs, mountLabel); err != nil { + if err := mountPropagate(m, rootfs, mountLabel); err != nil { return err } if stat != nil { @@ -135,12 +135,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { if err := os.MkdirAll(dest, 0755); err != nil { return err } - return m.MountPropagate(rootfs, mountLabel) + return mountPropagate(m, rootfs, mountLabel) case "securityfs": if err := os.MkdirAll(dest, 0755); err != nil { return err } - return m.MountPropagate(rootfs, mountLabel) + return mountPropagate(m, rootfs, mountLabel) case "bind": stat, err := os.Stat(m.Source) if err != nil { @@ -158,14 +158,16 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { if err := checkMountDestination(rootfs, dest); err != nil { return err } + // update the mount with the correct dest after symlinks are resolved. + m.Destination = dest if err := createIfNotExists(dest, stat.IsDir()); err != nil { return err } - if err := m.MountPropagate(rootfs, mountLabel); err != nil { + if err := mountPropagate(m, rootfs, mountLabel); err != nil { return err } // bind mount won't change mount options, we need remount to make mount options effective. - if err := m.Remount(rootfs); err != nil { + if err := remount(m, rootfs); err != nil { return err } if m.Relabel != "" { @@ -234,7 +236,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error { Destination: m.Destination, Flags: defaultMountFlags | syscall.MS_RDONLY, } - if err := mcgrouproot.Remount(rootfs); err != nil { + if err := remount(mcgrouproot, rootfs); err != nil { return err } } @@ -328,7 +330,7 @@ func setupDevSymlinks(rootfs string) error { // this method will make them point to `/dev/null` in this container's rootfs. This // needs to be called after we chroot/pivot into the container's rootfs so that any // symlinks are resolved locally. -func reOpenDevNull(rootfs string) error { +func reOpenDevNull() error { var stat, devNullStat syscall.Stat_t file, err := os.Open("/dev/null") if err != nil { @@ -433,7 +435,7 @@ func setupPtmx(config *configs.Config, console *linuxConsole) error { return fmt.Errorf("symlink dev ptmx %s", err) } if console != nil { - return console.mount(config.Rootfs, config.MountLabel, 0, 0) + return console.mount(config.Rootfs, config.MountLabel) } return nil } @@ -532,3 +534,40 @@ func writeSystemProperty(key, value string) error { keyPath := strings.Replace(key, ".", "/", -1) return ioutil.WriteFile(path.Join("/proc/sys", keyPath), []byte(value), 0644) } + +func remount(m *configs.Mount, rootfs string) error { + var ( + dest = m.Destination + ) + if !strings.HasPrefix(dest, rootfs) { + dest = filepath.Join(rootfs, dest) + } + + if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil { + return err + } + return nil +} + +// Do the mount operation followed by additional mounts required to take care +// of propagation flags. +func mountPropagate(m *configs.Mount, rootfs string, mountLabel string) error { + var ( + dest = m.Destination + data = label.FormatMountLabel(m.Data, mountLabel) + ) + if !strings.HasPrefix(dest, rootfs) { + dest = filepath.Join(rootfs, dest) + } + + if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil { + return err + } + + for _, pflag := range m.PropagationFlags { + if err := syscall.Mount("", dest, "", uintptr(pflag), ""); err != nil { + return err + } + } + return nil +} diff --git a/vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go b/vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go index 58bdbf6d63..1e9ccf8f2d 100644 --- a/vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go +++ b/vendor/src/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go @@ -37,6 +37,18 @@ func InitSeccomp(config *configs.Seccomp) error { return fmt.Errorf("error creating filter: %s", err) } + // Add extra architectures + for _, arch := range config.Architectures { + scmpArch, err := libseccomp.GetArchFromString(arch) + if err != nil { + return err + } + + if err := filter.AddArch(scmpArch); err != nil { + return err + } + } + // Unset no new privs bit if err := filter.SetNoNewPrivsBit(false); err != nil { return fmt.Errorf("error setting no new privileges: %s", err)