Skip to content

Commit

Permalink
Merge pull request #10210 from swagatbora90/preserve-flags-cherry-pic…
Browse files Browse the repository at this point in the history
…k-1.7

[release/1.7] Preserve CL_UNPRIVILEGED locked flags during remount of bind mounts
  • Loading branch information
dmcgowan committed May 15, 2024
2 parents f2cce98 + ad85652 commit 36bbb4d
Showing 1 changed file with 46 additions and 1 deletion.
47 changes: 46 additions & 1 deletion mount/mount_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strings"
"time"

"github.com/containerd/containerd/pkg/userns"
"golang.org/x/sys/unix"
)

Expand Down Expand Up @@ -114,12 +115,56 @@ func (m *Mount) mount(target string) (err error) {

const broflags = unix.MS_BIND | unix.MS_RDONLY
if oflags&broflags == broflags {
// Preserve CL_UNPRIVILEGED "locked" flags of the
// bind mount target when we remount to make the bind readonly.
// This is necessary to ensure that
// bind-mounting "with options" will not fail with user namespaces, due to
// kernel restrictions that require user namespace mounts to preserve
// CL_UNPRIVILEGED locked flags.
var unprivFlags int
if userns.RunningInUserNS() {
unprivFlags, err = getUnprivilegedMountFlags(target)
if err != nil {
return err
}
}
// Remount the bind to apply read only.
return unix.Mount("", target, "", uintptr(oflags|unix.MS_REMOUNT), "")
return unix.Mount("", target, "", uintptr(oflags|unprivFlags|unix.MS_REMOUNT), "")
}
return nil
}

// Get the set of mount flags that are set on the mount that contains the given
// path and are locked by CL_UNPRIVILEGED.
//
// From https://github.com/moby/moby/blob/v23.0.1/daemon/oci_linux.go#L430-L460
func getUnprivilegedMountFlags(path string) (int, error) {
var statfs unix.Statfs_t
if err := unix.Statfs(path, &statfs); err != nil {
return 0, err
}

// The set of keys come from https://github.com/torvalds/linux/blob/v4.13/fs/namespace.c#L1034-L1048.
unprivilegedFlags := []int{
unix.MS_RDONLY,
unix.MS_NODEV,
unix.MS_NOEXEC,
unix.MS_NOSUID,
unix.MS_NOATIME,
unix.MS_RELATIME,
unix.MS_NODIRATIME,
}

var flags int
for flag := range unprivilegedFlags {
if int(statfs.Flags)&flag == flag {
flags |= flag
}
}

return flags, nil
}

// Unmount the provided mount path with the flags
func Unmount(target string, flags int) error {
if err := unmount(target, flags); err != nil && err != unix.EINVAL {
Expand Down

0 comments on commit 36bbb4d

Please sign in to comment.