From 0cdfd5f27582a5fb2e9627fbec1245453eac4c15 Mon Sep 17 00:00:00 2001 From: Cory Snider Date: Mon, 8 May 2023 18:15:43 -0400 Subject: [PATCH] pkg/system: return rich errors from L(g|s)etxattr Signed-off-by: Cory Snider --- pkg/archive/archive.go | 10 +++++----- pkg/system/xattrs_linux.go | 20 ++++++++++++++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/pkg/archive/archive.go b/pkg/archive/archive.go index 34361a24ac..e10cd8f178 100644 --- a/pkg/archive/archive.go +++ b/pkg/archive/archive.go @@ -757,26 +757,26 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L } } - var errors []string + var xattrErrs []string for key, value := range hdr.Xattrs { if err := system.Lsetxattr(path, key, []byte(value), 0); err != nil { - if err == syscall.ENOTSUP || err == syscall.EPERM { + if errors.Is(err, syscall.ENOTSUP) || errors.Is(err, syscall.EPERM) { // We ignore errors here because not all graphdrivers support // xattrs *cough* old versions of AUFS *cough*. However only // ENOTSUP should be emitted in that case, otherwise we still // bail. // EPERM occurs if modifying xattrs is not allowed. This can // happen when running in userns with restrictions (ChromeOS). - errors = append(errors, err.Error()) + xattrErrs = append(xattrErrs, err.Error()) continue } return err } } - if len(errors) > 0 { + if len(xattrErrs) > 0 { logrus.WithFields(logrus.Fields{ - "errors": errors, + "errors": xattrErrs, }).Warn("ignored xattrs in archive: underlying filesystem doesn't support them") } diff --git a/pkg/system/xattrs_linux.go b/pkg/system/xattrs_linux.go index 95b609fe7a..4196b281b3 100644 --- a/pkg/system/xattrs_linux.go +++ b/pkg/system/xattrs_linux.go @@ -1,11 +1,19 @@ package system // import "github.com/docker/docker/pkg/system" -import "golang.org/x/sys/unix" +import ( + "io/fs" + + "golang.org/x/sys/unix" +) // Lgetxattr retrieves the value of the extended attribute identified by attr // and associated with the given path in the file system. // It will returns a nil slice and nil error if the xattr is not set. func Lgetxattr(path string, attr string) ([]byte, error) { + pathErr := func(err error) ([]byte, error) { + return nil, &fs.PathError{Op: "lgetxattr", Path: path, Err: err} + } + // Start with a 128 length byte array dest := make([]byte, 128) sz, errno := unix.Lgetxattr(path, attr, dest) @@ -14,7 +22,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) { // Buffer too small, use zero-sized buffer to get the actual size sz, errno = unix.Lgetxattr(path, attr, []byte{}) if errno != nil { - return nil, errno + return pathErr(errno) } dest = make([]byte, sz) sz, errno = unix.Lgetxattr(path, attr, dest) @@ -24,7 +32,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) { case errno == unix.ENODATA: return nil, nil case errno != nil: - return nil, errno + return pathErr(errno) } return dest[:sz], nil @@ -33,5 +41,9 @@ func Lgetxattr(path string, attr string) ([]byte, error) { // Lsetxattr sets the value of the extended attribute identified by attr // and associated with the given path in the file system. func Lsetxattr(path string, attr string, data []byte, flags int) error { - return unix.Lsetxattr(path, attr, data, flags) + err := unix.Lsetxattr(path, attr, data, flags) + if err != nil { + return &fs.PathError{Op: "lsetxattr", Path: path, Err: err} + } + return nil }