mirror of
https://github.com/opencontainers/runc.git
synced 2025-10-18 13:30:54 +08:00
libcontainer: Allow passing mount propagation flags
Right now if one passes a mount propagation flag in spec file, it does not take effect. For example, try following in spec json file. { "type": "bind", "source": "/root/mnt-source", "destination": "/root/mnt-dest", "options": "rbind,shared" } One would expect that /root/mnt-dest will be shared inside the container but that's not the case. #findmnt -o TARGET,PROPAGATION `-/root/mnt-dest private Reason being that propagation flags can't be passed in along with other regular flags. They need to be passed in a separate call to mount syscall. That too, one propagation flag at a time. (from mount man page). Hence, store propagation flags separately in a slice and apply these in that order after the mount call wherever appropriate. This allows user to control the propagation property of mount point inside the container. Storing them separately also solves another problem where recursive flag (syscall.MS_REC) can get mixed up. For example, options "rbind,private" and "bind,rprivate" will be same and there will be no way to differentiate between these if all the flags are stored in a single integer. This patch would allow one to pass propagation flags "[r]shared,[r]slave, [r]private,[r]unbindable" in spec file as per mount property. Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
This commit is contained in:
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) {
|
||||
|
Reference in New Issue
Block a user