From 43bf65c174aff8f7c30a100c2783510009345e55 Mon Sep 17 00:00:00 2001 From: Cory Snider Date: Mon, 22 Jan 2024 15:08:02 -0500 Subject: [PATCH] pkg/system: return even richer xattr errors The names of extended attributes are not completely freeform. Attributes are namespaced, and the kernel enforces (among other things) that only attributes whose names are prefixed with a valid namespace are permitted. The name of the attribute therefore needs to be known in order to diagnose issues with lsetxattr. Include the name of the extended attribute in the errors returned from the Lsetxattr and Lgetxattr so users and us can more easily troubleshoot xattr-related issues. Include the name in a separate rich-error field to provide code handling the error enough information to determine whether or not the failure can be ignored. Signed-off-by: Cory Snider --- builder/remotecontext/archive.go | 7 +++++-- pkg/system/xattrs.go | 18 ++++++++++++++++++ pkg/system/xattrs_linux.go | 12 +++++------- 3 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 pkg/system/xattrs.go diff --git a/builder/remotecontext/archive.go b/builder/remotecontext/archive.go index 52811e1700..5201feedd3 100644 --- a/builder/remotecontext/archive.go +++ b/builder/remotecontext/archive.go @@ -9,6 +9,7 @@ import ( "github.com/docker/docker/pkg/archive" "github.com/docker/docker/pkg/chrootarchive" "github.com/docker/docker/pkg/longpath" + "github.com/docker/docker/pkg/system" "github.com/docker/docker/pkg/tarsum" "github.com/moby/sys/symlink" "github.com/pkg/errors" @@ -24,9 +25,11 @@ func (c *archiveContext) Close() error { } func convertPathError(err error, cleanpath string) error { - if err, ok := err.(*os.PathError); ok { + switch err := err.(type) { + case *os.PathError: + err.Path = cleanpath + case *system.XattrError: err.Path = cleanpath - return err } return err } diff --git a/pkg/system/xattrs.go b/pkg/system/xattrs.go new file mode 100644 index 0000000000..b3f4e8a21f --- /dev/null +++ b/pkg/system/xattrs.go @@ -0,0 +1,18 @@ +package system // import "github.com/docker/docker/pkg/system" + +type XattrError struct { + Op string + Attr string + Path string + Err error +} + +func (e *XattrError) Error() string { return e.Op + " " + e.Attr + " " + e.Path + ": " + e.Err.Error() } + +func (e *XattrError) Unwrap() error { return e.Err } + +// Timeout reports whether this error represents a timeout. +func (e *XattrError) Timeout() bool { + t, ok := e.Err.(interface{ Timeout() bool }) + return ok && t.Timeout() +} diff --git a/pkg/system/xattrs_linux.go b/pkg/system/xattrs_linux.go index 4196b281b3..facfbb3126 100644 --- a/pkg/system/xattrs_linux.go +++ b/pkg/system/xattrs_linux.go @@ -1,8 +1,6 @@ package system // import "github.com/docker/docker/pkg/system" import ( - "io/fs" - "golang.org/x/sys/unix" ) @@ -10,8 +8,8 @@ import ( // 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} + sysErr := func(err error) ([]byte, error) { + return nil, &XattrError{Op: "lgetxattr", Attr: attr, Path: path, Err: err} } // Start with a 128 length byte array @@ -22,7 +20,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 pathErr(errno) + return sysErr(errno) } dest = make([]byte, sz) sz, errno = unix.Lgetxattr(path, attr, dest) @@ -32,7 +30,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) { case errno == unix.ENODATA: return nil, nil case errno != nil: - return pathErr(errno) + return sysErr(errno) } return dest[:sz], nil @@ -43,7 +41,7 @@ func Lgetxattr(path string, attr string) ([]byte, error) { func Lsetxattr(path string, attr string, data []byte, flags int) error { err := unix.Lsetxattr(path, attr, data, flags) if err != nil { - return &fs.PathError{Op: "lsetxattr", Path: path, Err: err} + return &XattrError{Op: "lsetxattr", Attr: attr, Path: path, Err: err} } return nil }