Warn the user and fail daemon start if the graphdir path has any
elements which will deny access to the remapped root uid/gid.
Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com>
... | ... |
@@ -1004,6 +1004,20 @@ func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error |
1004 | 1004 |
if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil { |
1005 | 1005 |
return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err) |
1006 | 1006 |
} |
1007 |
+ // we also need to verify that any pre-existing directories in the path to |
|
1008 |
+ // the graphroot won't block access to remapped root--if any pre-existing directory |
|
1009 |
+ // has strict permissions that don't allow "x", container start will fail, so |
|
1010 |
+ // better to warn and fail now |
|
1011 |
+ dirPath := config.Root |
|
1012 |
+ for { |
|
1013 |
+ dirPath = filepath.Dir(dirPath) |
|
1014 |
+ if dirPath == "/" { |
|
1015 |
+ break |
|
1016 |
+ } |
|
1017 |
+ if !idtools.CanAccess(dirPath, rootUID, rootGID) { |
|
1018 |
+ return fmt.Errorf("A subdirectory in your graphroot path (%s) restricts access to the remapped root uid/gid; please fix by allowing 'o+x' permissions on existing directories.", config.Root) |
|
1019 |
+ } |
|
1020 |
+ } |
|
1007 | 1021 |
} |
1008 | 1022 |
return nil |
1009 | 1023 |
} |
... | ... |
@@ -58,3 +58,29 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown |
58 | 58 |
} |
59 | 59 |
return nil |
60 | 60 |
} |
61 |
+ |
|
62 |
+// CanAccess takes a valid (existing) directory and a uid, gid pair and determines |
|
63 |
+// if that uid, gid pair has access (execute bit) to the directory |
|
64 |
+func CanAccess(path string, uid, gid int) bool { |
|
65 |
+ statInfo, err := system.Stat(path) |
|
66 |
+ if err != nil { |
|
67 |
+ return false |
|
68 |
+ } |
|
69 |
+ fileMode := os.FileMode(statInfo.Mode()) |
|
70 |
+ permBits := fileMode.Perm() |
|
71 |
+ return accessible(statInfo.UID() == uint32(uid), |
|
72 |
+ statInfo.GID() == uint32(gid), permBits) |
|
73 |
+} |
|
74 |
+ |
|
75 |
+func accessible(isOwner, isGroup bool, perms os.FileMode) bool { |
|
76 |
+ if isOwner && (perms&0100 == 0100) { |
|
77 |
+ return true |
|
78 |
+ } |
|
79 |
+ if isGroup && (perms&0010 == 0010) { |
|
80 |
+ return true |
|
81 |
+ } |
|
82 |
+ if perms&0001 == 0001 { |
|
83 |
+ return true |
|
84 |
+ } |
|
85 |
+ return false |
|
86 |
+} |
... | ... |
@@ -16,3 +16,10 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown |
16 | 16 |
} |
17 | 17 |
return nil |
18 | 18 |
} |
19 |
+ |
|
20 |
+// CanAccess takes a valid (existing) directory and a uid, gid pair and determines |
|
21 |
+// if that uid, gid pair has access (execute bit) to the directory |
|
22 |
+// Windows does not require/support this function, so always return true |
|
23 |
+func CanAccess(path string, uid, gid int) bool { |
|
24 |
+ return true |
|
25 |
+} |