overlayutils.go 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. //go:build linux
  2. // +build linux
  3. package overlayutils // import "github.com/docker/docker/daemon/graphdriver/overlayutils"
  4. import (
  5. "context"
  6. "fmt"
  7. "os"
  8. "path"
  9. "path/filepath"
  10. "github.com/containerd/containerd/log"
  11. "github.com/containerd/containerd/pkg/userns"
  12. "github.com/docker/docker/daemon/graphdriver"
  13. "github.com/pkg/errors"
  14. "golang.org/x/sys/unix"
  15. )
  16. // ErrDTypeNotSupported denotes that the backing filesystem doesn't support d_type.
  17. func ErrDTypeNotSupported(driver, backingFs string) error {
  18. msg := fmt.Sprintf("%s: the backing %s filesystem is formatted without d_type support, which leads to incorrect behavior.", driver, backingFs)
  19. if backingFs == "xfs" {
  20. msg += " Reformat the filesystem with ftype=1 to enable d_type support."
  21. }
  22. if backingFs == "extfs" {
  23. msg += " Reformat the filesystem (or use tune2fs) with -O filetype flag to enable d_type support."
  24. }
  25. msg += " Backing filesystems without d_type support are not supported."
  26. return graphdriver.NotSupportedError(msg)
  27. }
  28. // SupportsOverlay checks if the system supports overlay filesystem
  29. // by performing an actual overlay mount.
  30. //
  31. // checkMultipleLowers parameter enables check for multiple lowerdirs,
  32. // which is required for the overlay2 driver.
  33. func SupportsOverlay(d string, checkMultipleLowers bool) error {
  34. // We can't rely on go-selinux.GetEnabled() to detect whether SELinux is enabled,
  35. // because RootlessKit doesn't mount /sys/fs/selinux in the child: https://github.com/rootless-containers/rootlesskit/issues/94
  36. // So we check $_DOCKERD_ROOTLESS_SELINUX, which is set by dockerd-rootless.sh .
  37. if os.Getenv("_DOCKERD_ROOTLESS_SELINUX") == "1" {
  38. // Kernel 5.11 introduced support for rootless overlayfs, but incompatible with SELinux,
  39. // so fallback to fuse-overlayfs.
  40. // https://github.com/moby/moby/issues/42333
  41. return errors.New("overlay is not supported for Rootless with SELinux")
  42. }
  43. td, err := os.MkdirTemp(d, "check-overlayfs-support")
  44. if err != nil {
  45. return err
  46. }
  47. defer func() {
  48. if err := os.RemoveAll(td); err != nil {
  49. log.G(context.TODO()).Warnf("Failed to remove check directory %v: %v", td, err)
  50. }
  51. }()
  52. for _, dir := range []string{"lower1", "lower2", "upper", "work", "merged"} {
  53. if err := os.Mkdir(filepath.Join(td, dir), 0o755); err != nil {
  54. return err
  55. }
  56. }
  57. mnt := filepath.Join(td, "merged")
  58. lowerDir := path.Join(td, "lower2")
  59. if checkMultipleLowers {
  60. lowerDir += ":" + path.Join(td, "lower1")
  61. }
  62. opts := fmt.Sprintf("lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, path.Join(td, "upper"), path.Join(td, "work"))
  63. if err := unix.Mount("overlay", mnt, "overlay", 0, opts); err != nil {
  64. return errors.Wrap(err, "failed to mount overlay")
  65. }
  66. if err := unix.Unmount(mnt, 0); err != nil {
  67. log.G(context.TODO()).Warnf("Failed to unmount check directory %v: %v", mnt, err)
  68. }
  69. return nil
  70. }
  71. // GetOverlayXattr combines the overlay module's xattr class with the named
  72. // xattr -- `user` when mounted inside a user namespace, and `trusted` when
  73. // mounted in the 'root' namespace.
  74. func GetOverlayXattr(name string) string {
  75. class := "trusted"
  76. if userns.RunningInUserNS() {
  77. class = "user"
  78. }
  79. return fmt.Sprintf("%s.overlay.%s", class, name)
  80. }