diff --git a/drivers/copy/copy_linux.go b/drivers/copy/copy_linux.go index 1cd16a501..c2156861f 100644 --- a/drivers/copy/copy_linux.go +++ b/drivers/copy/copy_linux.go @@ -25,6 +25,7 @@ import ( "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/pools" "github.com/containers/storage/pkg/system" + "github.com/containers/storage/pkg/unshare" rsystem "github.com/opencontainers/runc/libcontainer/system" "golang.org/x/sys/unix" ) @@ -293,6 +294,10 @@ func doCopyXattrs(srcPath, dstPath string) error { } } + if unshare.IsRootless() { + return nil + } + // We need to copy this attribute if it appears in an overlay upper layer, as // this function is used to copy those. It is set by overlay if a directory // is removed and then re-created and should not inherit anything from the diff --git a/drivers/overlay/check.go b/drivers/overlay/check.go index 9a62e7d75..67287b492 100644 --- a/drivers/overlay/check.go +++ b/drivers/overlay/check.go @@ -10,6 +10,7 @@ import ( "path/filepath" "syscall" + "github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/pkg/mount" "github.com/containers/storage/pkg/system" @@ -54,7 +55,7 @@ func doesSupportNativeDiff(d, mountOpts string) error { } // Mark l2/d as opaque - if err := system.Lsetxattr(filepath.Join(td, "l2", "d"), "trusted.overlay.opaque", []byte("y"), 0); err != nil { + if err := system.Lsetxattr(filepath.Join(td, "l2", "d"), archive.GetOverlayXattrName("opaque"), []byte("y"), 0); err != nil { return errors.Wrap(err, "failed to set opaque flag on middle layer") } @@ -78,7 +79,7 @@ func doesSupportNativeDiff(d, mountOpts string) error { } // Check l3/d does not have opaque flag - xattrOpaque, err := system.Lgetxattr(filepath.Join(td, "l3", "d"), "trusted.overlay.opaque") + xattrOpaque, err := system.Lgetxattr(filepath.Join(td, "l3", "d"), archive.GetOverlayXattrName("opaque")) if err != nil { return errors.Wrap(err, "failed to read opaque flag on upper layer") } @@ -95,7 +96,7 @@ func doesSupportNativeDiff(d, mountOpts string) error { return errors.Wrap(err, "failed to rename dir in merged directory") } // get the xattr of "d2" - xattrRedirect, err := system.Lgetxattr(filepath.Join(td, "l3", "d2"), "trusted.overlay.redirect") + xattrRedirect, err := system.Lgetxattr(filepath.Join(td, "l3", "d2"), archive.GetOverlayXattrName("redirect")) if err != nil { return errors.Wrap(err, "failed to read redirect flag on upper layer") } @@ -161,7 +162,7 @@ func doesMetacopy(d, mountOpts string) (bool, error) { if err := os.Chmod(filepath.Join(td, "merged", "f"), 0600); err != nil { return false, errors.Wrap(err, "error changing permissions on file for metacopy check") } - metacopy, err := system.Lgetxattr(filepath.Join(td, "l2", "f"), "trusted.overlay.metacopy") + metacopy, err := system.Lgetxattr(filepath.Join(td, "l2", "f"), archive.GetOverlayXattrName("metacopy")) if err != nil { return false, errors.Wrap(err, "metacopy flag was not set on file in upper layer") } diff --git a/pkg/archive/archive.go b/pkg/archive/archive.go index 1d21471eb..aa6689593 100644 --- a/pkg/archive/archive.go +++ b/pkg/archive/archive.go @@ -20,6 +20,7 @@ import ( "github.com/containers/storage/pkg/pools" "github.com/containers/storage/pkg/promise" "github.com/containers/storage/pkg/system" + "github.com/containers/storage/pkg/unshare" gzip "github.com/klauspost/pgzip" rsystem "github.com/opencontainers/runc/libcontainer/system" "github.com/pkg/errors" @@ -1489,3 +1490,14 @@ func TarPath(uidmap []idtools.IDMap, gidmap []idtools.IDMap) func(path string) ( }) } } + +// GetOverlayXattrName returns the xattr used by the overlay driver with the +// given name. +// It uses the trusted.overlay prefix when running as root, and user.overlay +// in rootless mode. +func GetOverlayXattrName(name string) string { + if unshare.IsRootless() { + return fmt.Sprintf("user.overlay.%s", name) + } + return fmt.Sprintf("trusted.overlay.%s", name) +} diff --git a/pkg/archive/archive_linux.go b/pkg/archive/archive_linux.go index 4efd5d3d9..f5c69d1c2 100644 --- a/pkg/archive/archive_linux.go +++ b/pkg/archive/archive_linux.go @@ -12,6 +12,10 @@ import ( "golang.org/x/sys/unix" ) +func getOverlayOpaqueXattrName() string { + return GetOverlayXattrName("opaque") +} + func GetWhiteoutConverter(format WhiteoutFormat, data interface{}) TarWhiteoutConverter { if format == OverlayWhiteoutFormat { if rolayers, ok := data.([]string); ok && len(rolayers) > 0 { @@ -39,13 +43,13 @@ func (o overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi if fi.Mode()&os.ModeDir != 0 { // convert opaque dirs to AUFS format by writing an empty file with the whiteout prefix - opaque, err := system.Lgetxattr(path, "trusted.overlay.opaque") + opaque, err := system.Lgetxattr(path, getOverlayOpaqueXattrName()) if err != nil { return nil, err } if len(opaque) == 1 && opaque[0] == 'y' { if hdr.Xattrs != nil { - delete(hdr.Xattrs, "trusted.overlay.opaque") + delete(hdr.Xattrs, getOverlayOpaqueXattrName()) } // If there are no lower layers, then it can't have been deleted in this layer. if len(o.rolayers) == 0 { @@ -114,7 +118,7 @@ func (overlayWhiteoutConverter) ConvertReadWithHandler(hdr *tar.Header, path str // if a directory is marked as opaque by the AUFS special file, we need to translate that to overlay if base == WhiteoutOpaqueDir { - err := handler.Setxattr(dir, "trusted.overlay.opaque", []byte{'y'}) + err := handler.Setxattr(dir, getOverlayOpaqueXattrName(), []byte{'y'}) // don't write the file itself return false, err } diff --git a/pkg/archive/archive_linux_test.go b/pkg/archive/archive_linux_test.go index c0ab010eb..58b7ee080 100644 --- a/pkg/archive/archive_linux_test.go +++ b/pkg/archive/archive_linux_test.go @@ -26,7 +26,7 @@ func setupOverlayTestDir(t *testing.T, src string) { err := os.Mkdir(filepath.Join(src, "d1"), 0700) require.NoError(t, err) - err = system.Lsetxattr(filepath.Join(src, "d1"), "trusted.overlay.opaque", []byte("y"), 0) + err = system.Lsetxattr(filepath.Join(src, "d1"), getOverlayOpaqueXattrName(), []byte("y"), 0) require.NoError(t, err) err = ioutil.WriteFile(filepath.Join(src, "d1", "f1"), []byte{}, 0600) @@ -36,7 +36,7 @@ func setupOverlayTestDir(t *testing.T, src string) { err = os.Mkdir(filepath.Join(src, "d2"), 0750) require.NoError(t, err) - err = system.Lsetxattr(filepath.Join(src, "d2"), "trusted.overlay.opaque", []byte("y"), 0) + err = system.Lsetxattr(filepath.Join(src, "d2"), getOverlayOpaqueXattrName(), []byte("y"), 0) require.NoError(t, err) err = ioutil.WriteFile(filepath.Join(src, "d2", "f1"), []byte{}, 0660) @@ -60,7 +60,7 @@ func setupOverlayLowerDir(t *testing.T, lower string) { } func checkOpaqueness(t *testing.T, path string, opaque string) { - xattrOpaque, err := system.Lgetxattr(path, "trusted.overlay.opaque") + xattrOpaque, err := system.Lgetxattr(path, getOverlayOpaqueXattrName()) require.NoError(t, err) if string(xattrOpaque) != opaque { diff --git a/pkg/archive/changes_linux.go b/pkg/archive/changes_linux.go index ea1dae052..a3addebe6 100644 --- a/pkg/archive/changes_linux.go +++ b/pkg/archive/changes_linux.go @@ -349,7 +349,7 @@ func overlayDeletedFile(layers []string, root, path string, fi os.FileInfo) (str return "", nil } // If the directory isn't marked as opaque, then it's just a normal directory. - opaque, err := system.Lgetxattr(filepath.Join(root, path), "trusted.overlay.opaque") + opaque, err := system.Lgetxattr(filepath.Join(root, path), getOverlayOpaqueXattrName()) if err != nil { return "", err }