Merge pull request #264 from rhvgoyal/spec-allow-propgation-flags
libcontainer: Allow passing mount propagation flags
This commit is contained in:
commit
cae6b31029
|
@ -1,5 +1,13 @@
|
|||
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"`
|
||||
|
@ -13,6 +21,9 @@ type Mount struct {
|
|||
// Mount flags.
|
||||
Flags int `json:"flags"`
|
||||
|
||||
// Propagation Flags
|
||||
PropagationFlags []int `json:"propagation_flags"`
|
||||
|
||||
// Mount data applied to the mount.
|
||||
Data string `json:"data"`
|
||||
|
||||
|
@ -25,3 +36,40 @@ 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
|
||||
}
|
||||
|
|
|
@ -96,7 +96,6 @@ func mountCmd(cmd configs.Command) error {
|
|||
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
||||
var (
|
||||
dest = m.Destination
|
||||
data = label.FormatMountLabel(m.Data, mountLabel)
|
||||
)
|
||||
if !strings.HasPrefix(dest, rootfs) {
|
||||
dest = filepath.Join(rootfs, dest)
|
||||
|
@ -107,12 +106,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), "")
|
||||
return m.MountPropagate(rootfs, mountLabel)
|
||||
case "mqueue":
|
||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), ""); err != nil {
|
||||
if err := m.MountPropagate(rootfs, mountLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
return label.SetFileLabel(dest, mountLabel)
|
||||
|
@ -123,7 +122,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
|
||||
if err := m.MountPropagate(rootfs, mountLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
if stat != nil {
|
||||
|
@ -136,12 +135,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
|
||||
return m.MountPropagate(rootfs, mountLabel)
|
||||
case "securityfs":
|
||||
if err := os.MkdirAll(dest, 0755); err != nil {
|
||||
return err
|
||||
}
|
||||
return syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data)
|
||||
return m.MountPropagate(rootfs, mountLabel)
|
||||
case "bind":
|
||||
stat, err := os.Stat(m.Source)
|
||||
if err != nil {
|
||||
|
@ -162,11 +161,11 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
if err := createIfNotExists(dest, stat.IsDir()); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags), data); err != nil {
|
||||
if err := m.MountPropagate(rootfs, mountLabel); err != nil {
|
||||
return err
|
||||
}
|
||||
// bind mount won't change mount options, we need remount to make mount options effective.
|
||||
if err := syscall.Mount(m.Source, dest, m.Device, uintptr(m.Flags|syscall.MS_REMOUNT), ""); err != nil {
|
||||
if err := m.Remount(rootfs); err != nil {
|
||||
return err
|
||||
}
|
||||
if m.Relabel != "" {
|
||||
|
@ -178,11 +177,6 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
if m.Flags&syscall.MS_PRIVATE != 0 {
|
||||
if err := syscall.Mount("", dest, "none", uintptr(syscall.MS_PRIVATE), ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case "cgroup":
|
||||
binds, err := getCgroupMounts(m)
|
||||
if err != nil {
|
||||
|
@ -196,11 +190,12 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
}
|
||||
}
|
||||
tmpfs := &configs.Mount{
|
||||
Source: "tmpfs",
|
||||
Device: "tmpfs",
|
||||
Destination: m.Destination,
|
||||
Flags: defaultMountFlags,
|
||||
Data: "mode=755",
|
||||
Source: "tmpfs",
|
||||
Device: "tmpfs",
|
||||
Destination: m.Destination,
|
||||
Flags: defaultMountFlags,
|
||||
Data: "mode=755",
|
||||
PropagationFlags: m.PropagationFlags,
|
||||
}
|
||||
if err := mountToRootfs(tmpfs, rootfs, mountLabel); err != nil {
|
||||
return err
|
||||
|
@ -235,8 +230,11 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string) error {
|
|||
}
|
||||
if m.Flags&syscall.MS_RDONLY != 0 {
|
||||
// remount cgroup root as readonly
|
||||
rootfsCgroup := filepath.Join(rootfs, m.Destination)
|
||||
if err := syscall.Mount("", rootfsCgroup, "", defaultMountFlags|syscall.MS_REMOUNT|syscall.MS_RDONLY, ""); err != nil {
|
||||
mcgrouproot := &configs.Mount{
|
||||
Destination: m.Destination,
|
||||
Flags: defaultMountFlags | syscall.MS_RDONLY,
|
||||
}
|
||||
if err := mcgrouproot.Remount(rootfs); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -269,10 +267,11 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
|
|||
return nil, err
|
||||
}
|
||||
binds = append(binds, &configs.Mount{
|
||||
Device: "bind",
|
||||
Source: filepath.Join(mm.Mountpoint, relDir),
|
||||
Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
|
||||
Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags,
|
||||
Device: "bind",
|
||||
Source: filepath.Join(mm.Mountpoint, relDir),
|
||||
Destination: filepath.Join(m.Destination, strings.Join(mm.Subsystems, ",")),
|
||||
Flags: syscall.MS_BIND | syscall.MS_REC | m.Flags,
|
||||
PropagationFlags: m.PropagationFlags,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
49
spec.go
49
spec.go
|
@ -387,7 +387,7 @@ func createLibcontainerConfig(cgroupName string, spec *specs.LinuxSpec, rspec *s
|
|||
}
|
||||
|
||||
func createLibcontainerMount(cwd, dest string, m specs.Mount) *configs.Mount {
|
||||
flags, data := parseMountOptions(m.Options)
|
||||
flags, pgflags, data := parseMountOptions(m.Options)
|
||||
source := m.Source
|
||||
if m.Type == "bind" {
|
||||
if !filepath.IsAbs(source) {
|
||||
|
@ -395,11 +395,12 @@ func createLibcontainerMount(cwd, dest string, m specs.Mount) *configs.Mount {
|
|||
}
|
||||
}
|
||||
return &configs.Mount{
|
||||
Device: m.Type,
|
||||
Source: source,
|
||||
Destination: dest,
|
||||
Data: data,
|
||||
Flags: flags,
|
||||
Device: m.Type,
|
||||
Source: source,
|
||||
Destination: dest,
|
||||
Data: data,
|
||||
Flags: flags,
|
||||
PropagationFlags: pgflags,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -519,12 +520,13 @@ func createLibContainerRlimit(rlimit specs.Rlimit) (configs.Rlimit, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
// parseMountOptions parses the string and returns the flags and any mount data that
|
||||
// it contains.
|
||||
func parseMountOptions(options []string) (int, string) {
|
||||
// parseMountOptions parses the string and returns the flags, propagation
|
||||
// flags and any mount data that it contains.
|
||||
func parseMountOptions(options []string) (int, []int, string) {
|
||||
var (
|
||||
flag int
|
||||
data []string
|
||||
flag int
|
||||
pgflag []int
|
||||
data []string
|
||||
)
|
||||
flags := map[string]struct {
|
||||
clear bool
|
||||
|
@ -547,22 +549,27 @@ func parseMountOptions(options []string) (int, string) {
|
|||
"norelatime": {true, syscall.MS_RELATIME},
|
||||
"nostrictatime": {true, syscall.MS_STRICTATIME},
|
||||
"nosuid": {false, syscall.MS_NOSUID},
|
||||
"private": {false, syscall.MS_PRIVATE},
|
||||
"rbind": {false, syscall.MS_BIND | syscall.MS_REC},
|
||||
"relatime": {false, syscall.MS_RELATIME},
|
||||
"remount": {false, syscall.MS_REMOUNT},
|
||||
"ro": {false, syscall.MS_RDONLY},
|
||||
"rprivate": {false, syscall.MS_PRIVATE | syscall.MS_REC},
|
||||
"rshared": {false, syscall.MS_SHARED | syscall.MS_REC},
|
||||
"rslave": {false, syscall.MS_SLAVE | syscall.MS_REC},
|
||||
"runbindable": {false, syscall.MS_UNBINDABLE | syscall.MS_REC},
|
||||
"rw": {true, syscall.MS_RDONLY},
|
||||
"shared": {false, syscall.MS_SHARED},
|
||||
"slave": {false, syscall.MS_SLAVE},
|
||||
"strictatime": {false, syscall.MS_STRICTATIME},
|
||||
"suid": {true, syscall.MS_NOSUID},
|
||||
"sync": {false, syscall.MS_SYNCHRONOUS},
|
||||
"unbindable": {false, syscall.MS_UNBINDABLE},
|
||||
}
|
||||
propagationFlags := map[string]struct {
|
||||
clear bool
|
||||
flag int
|
||||
}{
|
||||
"private": {false, syscall.MS_PRIVATE},
|
||||
"shared": {false, syscall.MS_SHARED},
|
||||
"slave": {false, syscall.MS_SLAVE},
|
||||
"unbindable": {false, syscall.MS_UNBINDABLE},
|
||||
"rprivate": {false, syscall.MS_PRIVATE | syscall.MS_REC},
|
||||
"rshared": {false, syscall.MS_SHARED | syscall.MS_REC},
|
||||
"rslave": {false, syscall.MS_SLAVE | syscall.MS_REC},
|
||||
"runbindable": {false, syscall.MS_UNBINDABLE | syscall.MS_REC},
|
||||
}
|
||||
for _, o := range options {
|
||||
// If the option does not exist in the flags table or the flag
|
||||
|
@ -574,11 +581,13 @@ func parseMountOptions(options []string) (int, string) {
|
|||
} else {
|
||||
flag |= f.flag
|
||||
}
|
||||
} else if f, exists := propagationFlags[o]; exists && f.flag != 0 {
|
||||
pgflag = append(pgflag, f.flag)
|
||||
} else {
|
||||
data = append(data, o)
|
||||
}
|
||||
}
|
||||
return flag, strings.Join(data, ",")
|
||||
return flag, pgflag, strings.Join(data, ",")
|
||||
}
|
||||
|
||||
func setupSeccomp(config *specs.Seccomp) (*configs.Seccomp, error) {
|
||||
|
|
Loading…
Reference in New Issue