diff --git a/libcontainer/container.go b/libcontainer/container.go index c7cac35..1e032c0 100644 --- a/libcontainer/container.go +++ b/libcontainer/container.go @@ -23,7 +23,7 @@ type Container struct { Networks []*Network `json:"networks,omitempty"` // nil for host's network stack Cgroups *cgroups.Cgroup `json:"cgroups,omitempty"` // cgroups Context Context `json:"context,omitempty"` // generic context for specific options (apparmor, selinux) - Mounts []Mount `json:"mounts,omitempty"` + Mounts Mounts `json:"mounts,omitempty"` } // Network defines configuration for a container's networking stack @@ -38,11 +38,22 @@ type Network struct { Mtu int `json:"mtu,omitempty"` } -// Bind mounts from the host system to the container -// -type Mount struct { - Source string `json:"source"` // Source path, in the host namespace - Destination string `json:"destination"` // Destination path, in the container - Writable bool `json:"writable"` - Private bool `json:"private"` +type Mounts []Mount + +func (s Mounts) OfType(t string) Mounts { + out := Mounts{} + for _, m := range s { + if m.Type == t { + out = append(out, m) + } + } + return out +} + +type Mount struct { + Type string `json:"type,omitempty"` + Source string `json:"source,omitempty"` // Source path, in the host namespace + Destination string `json:"destination,omitempty"` // Destination path, in the container + Writable bool `json:"writable,omitempty"` + Private bool `json:"private,omitempty"` } diff --git a/libcontainer/nsinit/mount.go b/libcontainer/nsinit/mount.go index e4869a0..ee48032 100644 --- a/libcontainer/nsinit/mount.go +++ b/libcontainer/nsinit/mount.go @@ -17,6 +17,14 @@ import ( // default mount point flags const defaultMountFlags = syscall.MS_NOEXEC | syscall.MS_NOSUID | syscall.MS_NODEV +type mount struct { + source string + path string + device string + flags int + data string +} + // setupNewMountNamespace is used to initialize a new mount namespace for an new // container in the rootfs that is specified. // @@ -33,7 +41,7 @@ func setupNewMountNamespace(rootfs, console string, container *libcontainer.Cont if err := system.Mount(rootfs, rootfs, "bind", syscall.MS_BIND|syscall.MS_REC, ""); err != nil { return fmt.Errorf("mouting %s as bind %s", rootfs, err) } - if err := mountSystem(rootfs, container.Context["mount_label"]); err != nil { + if err := mountSystem(rootfs, container); err != nil { return fmt.Errorf("mount system %s", err) } if err := setupBindmounts(rootfs, container.Mounts); err != nil { @@ -183,19 +191,8 @@ func setupConsole(rootfs, console string, mountLabel string) error { // mountSystem sets up linux specific system mounts like sys, proc, shm, and devpts // inside the mount namespace -func mountSystem(rootfs string, mountLabel string) error { - for _, m := range []struct { - source string - path string - device string - flags int - data string - }{ - {source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags}, - {source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags}, - {source: "shm", path: filepath.Join(rootfs, "dev", "shm"), device: "tmpfs", flags: defaultMountFlags, data: label.FormatMountLabel("mode=1777,size=65536k", mountLabel)}, - {source: "devpts", path: filepath.Join(rootfs, "dev", "pts"), device: "devpts", flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, data: label.FormatMountLabel("newinstance,ptmxmode=0666,mode=620,gid=5", mountLabel)}, - } { +func mountSystem(rootfs string, container *libcontainer.Container) error { + for _, m := range newSystemMounts(rootfs, container.Context["mount_label"], container.Mounts) { if err := os.MkdirAll(m.path, 0755); err != nil && !os.IsExist(err) { return fmt.Errorf("mkdirall %s %s", m.path, err) } @@ -249,8 +246,8 @@ func remountSys() error { return nil } -func setupBindmounts(rootfs string, bindMounts []libcontainer.Mount) error { - for _, m := range bindMounts { +func setupBindmounts(rootfs string, bindMounts libcontainer.Mounts) error { + for _, m := range bindMounts.OfType("bind") { var ( flags = syscall.MS_BIND | syscall.MS_REC dest = filepath.Join(rootfs, m.Destination) @@ -274,3 +271,16 @@ func setupBindmounts(rootfs string, bindMounts []libcontainer.Mount) error { } return nil } + +func newSystemMounts(rootfs, mountLabel string, mounts libcontainer.Mounts) []mount { + systemMounts := []mount{ + {source: "proc", path: filepath.Join(rootfs, "proc"), device: "proc", flags: defaultMountFlags}, + {source: "shm", path: filepath.Join(rootfs, "dev", "shm"), device: "tmpfs", flags: defaultMountFlags, data: label.FormatMountLabel("mode=1777,size=65536k", mountLabel)}, + {source: "devpts", path: filepath.Join(rootfs, "dev", "pts"), device: "devpts", flags: syscall.MS_NOSUID | syscall.MS_NOEXEC, data: label.FormatMountLabel("newinstance,ptmxmode=0666,mode=620,gid=5", mountLabel)}, + } + + if len(mounts.OfType("sysfs")) == 1 { + systemMounts = append(systemMounts, mount{source: "sysfs", path: filepath.Join(rootfs, "sys"), device: "sysfs", flags: defaultMountFlags}) + } + return systemMounts +}