From a345ccfd0e0b5fcc6543419e24067c9149a5e28f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 19 Feb 2019 16:00:50 +0100 Subject: [PATCH] Graphdriver: fix "device" mode not being detected if "character-device" bit is set Due to a bug in Golang (github.com/golang#27640), the "character device" bit was omitted when checking file-modes with `os.ModeType`. This bug was resolved in Go 1.12, but as a result, graphdrivers would no longer recognize "device" files, causing pulling of images that have a file with this filemode to fail; failed to register layer: unknown file type for /var/lib/docker/vfs/dir/.../dev/console The current code checked for an exact match of Modes to be set. The `os.ModeCharDevice` and `os.ModeDevice` bits will always be set in tandem, however, because the code was only looking for an exact match, this detection broke now that `os.ModeCharDevice` was added. This patch changes the code to be more defensive, and instead check if the `os.ModeDevice` bit is set (either with, or without the `os.ModeCharDevice` bit). In addition, some information was added to the error-message if no type was matched, to assist debugging in case additional types are added in future. Signed-off-by: Sebastiaan van Stijn (cherry picked from commit c7a38c2c06f7ab844a48c6c447942913131b83d6) Signed-off-by: Sebastiaan van Stijn Upstream-commit: 3744b45ba8ad93f1a21cbc80420856b04efc4593 Component: engine --- .../engine/daemon/graphdriver/copy/copy.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/components/engine/daemon/graphdriver/copy/copy.go b/components/engine/daemon/graphdriver/copy/copy.go index 86316fdfe7..70ae9ce230 100644 --- a/components/engine/daemon/graphdriver/copy/copy.go +++ b/components/engine/daemon/graphdriver/copy/copy.go @@ -152,8 +152,8 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error { isHardlink := false - switch f.Mode() & os.ModeType { - case 0: // Regular file + switch mode := f.Mode(); { + case mode.IsRegular(): id := fileID{dev: stat.Dev, ino: stat.Ino} if copyMode == Hardlink { isHardlink = true @@ -171,12 +171,12 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error { copiedFiles[id] = dstPath } - case os.ModeDir: + case mode.IsDir(): if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) { return err } - case os.ModeSymlink: + case mode&os.ModeSymlink != 0: link, err := os.Readlink(srcPath) if err != nil { return err @@ -186,14 +186,14 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error { return err } - case os.ModeNamedPipe: + case mode&os.ModeNamedPipe != 0: fallthrough - case os.ModeSocket: + case mode&os.ModeSocket != 0: if err := unix.Mkfifo(dstPath, stat.Mode); err != nil { return err } - case os.ModeDevice: + case mode&os.ModeDevice != 0: if rsystem.RunningInUserNS() { // cannot create a device if running in user namespace return nil @@ -203,7 +203,7 @@ func DirCopy(srcDir, dstDir string, copyMode Mode, copyXattrs bool) error { } default: - return fmt.Errorf("unknown file type for %s", srcPath) + return fmt.Errorf("unknown file type (%d / %s) for %s", f.Mode(), f.Mode().String(), srcPath) } // Everything below is copying metadata from src to dst. All this metadata