1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Update libcontainer to aac9179bbadbf958054ce97ab36

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2015-09-22 16:33:00 -07:00
parent f6064cb42b
commit 189d2c7985
10 changed files with 133 additions and 79 deletions

View file

@ -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

View file

@ -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 {

View file

@ -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
}

View file

@ -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 {

View file

@ -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 {

View file

@ -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 {

View file

@ -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

View file

@ -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 {

View file

@ -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
}

View file

@ -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)