Browse code

Don't start daemon in userns mode if graphdir inaccessible

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>

Phil Estes authored on 2016/08/24 01:49:13
Showing 3 changed files
... ...
@@ -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
+}