package mountopts import ( "golang.org/x/sys/unix" ) // UnprivilegedMountFlags gets the set of mount flags that are set on the mount that contains the given // path and are locked by CL_UNPRIVILEGED. 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. // // TODO: Move to github.com/moby/sys/mount, and update BuildKit copy of this code as well (https://github.com/moby/buildkit/blob/v0.13.0/util/rootless/mountopts/mountopts_linux.go#L11-L18) func UnprivilegedMountFlags(path string) ([]string, error) { var statfs unix.Statfs_t if err := unix.Statfs(path, &statfs); err != nil { return nil, err } // The set of keys come from https://github.com/torvalds/linux/blob/v4.13/fs/namespace.c#L1034-L1048. unprivilegedFlags := map[uint64]string{ unix.MS_RDONLY: "ro", unix.MS_NODEV: "nodev", unix.MS_NOEXEC: "noexec", unix.MS_NOSUID: "nosuid", unix.MS_NOATIME: "noatime", unix.MS_RELATIME: "relatime", unix.MS_NODIRATIME: "nodiratime", } var flags []string for mask, flag := range unprivilegedFlags { if uint64(statfs.Flags)&mask == mask { flags = append(flags, flag) } } return flags, nil }