2021-08-23 09:14:53 -04:00
|
|
|
//go:build linux
|
2016-10-17 00:30:16 -04:00
|
|
|
// +build linux
|
|
|
|
|
2018-02-05 16:05:59 -05:00
|
|
|
package overlayutils // import "github.com/docker/docker/daemon/graphdriver/overlayutils"
|
2016-10-17 00:30:16 -04:00
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2019-11-07 17:20:40 -05:00
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
2017-11-15 19:48:43 -05:00
|
|
|
|
2022-05-12 13:25:05 -04:00
|
|
|
"github.com/containerd/containerd/pkg/userns"
|
2017-11-15 19:48:43 -05:00
|
|
|
"github.com/docker/docker/daemon/graphdriver"
|
2019-11-07 17:20:40 -05:00
|
|
|
"github.com/pkg/errors"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
"golang.org/x/sys/unix"
|
2016-10-17 00:30:16 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
// ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type.
|
|
|
|
func ErrDTypeNotSupported(driver, backingFs string) error {
|
|
|
|
msg := fmt.Sprintf("%s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.", driver, backingFs)
|
|
|
|
if backingFs == "xfs" {
|
|
|
|
msg += " Reformat the filesystem with ftype=1 to enable d_type support."
|
|
|
|
}
|
2018-05-09 09:26:14 -04:00
|
|
|
|
|
|
|
if backingFs == "extfs" {
|
|
|
|
msg += " Reformat the filesystem (or use tune2fs) with -O filetype flag to enable d_type support."
|
|
|
|
}
|
|
|
|
|
2017-11-15 19:48:43 -05:00
|
|
|
msg += " Backing filesystems without d_type support are not supported."
|
|
|
|
|
|
|
|
return graphdriver.NotSupportedError(msg)
|
2016-10-17 00:30:16 -04:00
|
|
|
}
|
2019-11-07 17:20:40 -05:00
|
|
|
|
2019-11-07 18:03:29 -05:00
|
|
|
// SupportsOverlay checks if the system supports overlay filesystem
|
|
|
|
// by performing an actual overlay mount.
|
|
|
|
//
|
|
|
|
// checkMultipleLowers parameter enables check for multiple lowerdirs,
|
|
|
|
// which is required for the overlay2 driver.
|
|
|
|
func SupportsOverlay(d string, checkMultipleLowers bool) error {
|
2021-04-28 02:37:36 -04:00
|
|
|
// We can't rely on go-selinux.GetEnabled() to detect whether SELinux is enabled,
|
|
|
|
// because RootlessKit doesn't mount /sys/fs/selinux in the child: https://github.com/rootless-containers/rootlesskit/issues/94
|
|
|
|
// So we check $_DOCKERD_ROOTLESS_SELINUX, which is set by dockerd-rootless.sh .
|
|
|
|
if os.Getenv("_DOCKERD_ROOTLESS_SELINUX") == "1" {
|
|
|
|
// Kernel 5.11 introduced support for rootless overlayfs, but incompatible with SELinux,
|
|
|
|
// so fallback to fuse-overlayfs.
|
|
|
|
// https://github.com/moby/moby/issues/42333
|
|
|
|
return errors.New("overlay is not supported for Rootless with SELinux")
|
|
|
|
}
|
|
|
|
|
2021-08-24 06:10:50 -04:00
|
|
|
td, err := os.MkdirTemp(d, "check-overlayfs-support")
|
2019-11-07 17:20:40 -05:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
defer func() {
|
|
|
|
if err := os.RemoveAll(td); err != nil {
|
|
|
|
logrus.Warnf("Failed to remove check directory %v: %v", td, err)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} {
|
|
|
|
if err := os.Mkdir(filepath.Join(td, dir), 0755); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mnt := filepath.Join(td, "merged")
|
2019-11-07 18:03:29 -05:00
|
|
|
lowerDir := path.Join(td, "lower2")
|
|
|
|
if checkMultipleLowers {
|
|
|
|
lowerDir += ":" + path.Join(td, "lower1")
|
|
|
|
}
|
|
|
|
opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, path.Join(td, "upper"), path.Join(td, "work"))
|
2019-11-07 17:20:40 -05:00
|
|
|
if err := unix.Mount("overlay", mnt, "overlay", 0, opts); err != nil {
|
|
|
|
return errors.Wrap(err, "failed to mount overlay")
|
|
|
|
}
|
|
|
|
if err := unix.Unmount(mnt, 0); err != nil {
|
|
|
|
logrus.Warnf("Failed to unmount check directory %v: %v", mnt, err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-05-12 13:25:05 -04:00
|
|
|
|
|
|
|
// GetOverlayXattr combines the overlay module's xattr class with the named
|
|
|
|
// xattr -- `user` when mounted inside a user namespace, and `trusted` when
|
|
|
|
// mounted in the 'root' namespace.
|
|
|
|
func GetOverlayXattr(name string) string {
|
|
|
|
class := "trusted"
|
|
|
|
if userns.RunningInUserNS() {
|
|
|
|
class = "user"
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%s.overlay.%s", class, name)
|
|
|
|
}
|