Browse code

Allow root non-userns metadata backwards compatibility

Instead of creating a "0.0" subdirectory and migrating graphroot
metadata into it when user namespaces are available in the daemon
(currently only in experimental), change the graphroot dir permissions
to only include the execute bit for "other" users.

This allows easy migration to and from user namespaces and will allow
easier integration of user namespace support into the master build.

Docker-DCO-1.1-Signed-off-by: Phil Estes <estesp@linux.vnet.ibm.com> (github: estesp)

Phil Estes authored on 2016/01/06 01:51:14
Showing 3 changed files
... ...
@@ -10,7 +10,6 @@ import (
10 10
 
11 11
 	"github.com/Sirupsen/logrus"
12 12
 	"github.com/docker/docker/api/types/container"
13
-	"github.com/docker/docker/pkg/directory"
14 13
 	"github.com/docker/docker/pkg/idtools"
15 14
 )
16 15
 
... ...
@@ -48,53 +47,36 @@ func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error)
48 48
 }
49 49
 
50 50
 func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error {
51
-	// the main docker root needs to be accessible by all users, as user namespace support
52
-	// will create subdirectories owned by either a) the real system root (when no remapping
53
-	// is setup) or b) the remapped root host ID (when --root=uid:gid is used)
54
-	// for "first time" users of user namespaces, we need to migrate the current directory
55
-	// contents to the "0.0" (root == root "namespace" daemon root)
56
-	nsRoot := "0.0"
51
+	config.Root = rootDir
52
+	// the docker root metadata directory needs to have execute permissions for all users (o+x)
53
+	// so that syscalls executing as non-root, operating on subdirectories of the graph root
54
+	// (e.g. mounted layers of a container) can traverse this path.
55
+	// The user namespace support will create subdirectories for the remapped root host uid:gid
56
+	// pair owned by that same uid:gid pair for proper write access to those needed metadata and
57
+	// layer content subtrees.
57 58
 	if _, err := os.Stat(rootDir); err == nil {
58
-		// root current exists; we need to check for a prior migration
59
-		if _, err := os.Stat(filepath.Join(rootDir, nsRoot)); err != nil && os.IsNotExist(err) {
60
-			// need to migrate current root to "0.0" subroot
61
-			// 1. create non-usernamespaced root as "0.0"
62
-			if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil {
63
-				return fmt.Errorf("Cannot create daemon root %q: %v", filepath.Join(rootDir, nsRoot), err)
64
-			}
65
-			// 2. move current root content to "0.0" new subroot
66
-			if err := directory.MoveToSubdir(rootDir, nsRoot); err != nil {
67
-				return fmt.Errorf("Cannot migrate current daemon root %q for user namespaces: %v", rootDir, err)
68
-			}
69
-			// 3. chmod outer root to 755
70
-			if chmodErr := os.Chmod(rootDir, 0755); chmodErr != nil {
71
-				return chmodErr
72
-			}
73
-		}
74
-	} else if os.IsNotExist(err) {
75
-		// no root exists yet, create it 0755 with root:root ownership
76
-		if err := os.MkdirAll(rootDir, 0755); err != nil {
59
+		// root current exists; verify the access bits are correct by setting them
60
+		if err = os.Chmod(rootDir, 0701); err != nil {
77 61
 			return err
78 62
 		}
79
-		// create the "0.0" subroot (so no future "migration" happens of the root)
80
-		if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil {
63
+	} else if os.IsNotExist(err) {
64
+		// no root exists yet, create it 0701 with root:root ownership
65
+		if err := os.MkdirAll(rootDir, 0701); err != nil {
81 66
 			return err
82 67
 		}
83 68
 	}
84 69
 
85
-	// for user namespaces we will create a subtree underneath the specified root
70
+	// if user namespaces are enabled we will create a subtree underneath the specified root
86 71
 	// with any/all specified remapped root uid/gid options on the daemon creating
87 72
 	// a new subdirectory with ownership set to the remapped uid/gid (so as to allow
88 73
 	// `chdir()` to work for containers namespaced to that uid/gid)
89 74
 	if config.RemappedRoot != "" {
90
-		nsRoot = fmt.Sprintf("%d.%d", rootUID, rootGID)
91
-	}
92
-	config.Root = filepath.Join(rootDir, nsRoot)
93
-	logrus.Debugf("Creating actual daemon root: %s", config.Root)
94
-
95
-	// Create the root directory if it doesn't exists
96
-	if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil {
97
-		return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err)
75
+		config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootUID, rootGID))
76
+		logrus.Debugf("Creating user namespaced daemon root: %s", config.Root)
77
+		// Create the root directory if it doesn't exists
78
+		if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil {
79
+			return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err)
80
+		}
98 81
 	}
99 82
 	return nil
100 83
 }
... ...
@@ -123,7 +123,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
123 123
 	// Create the root aufs driver dir and return
124 124
 	// if it already exists
125 125
 	// If not populate the dir structure
126
-	if err := idtools.MkdirAllAs(root, 0755, rootUID, rootGID); err != nil {
126
+	if err := idtools.MkdirAllAs(root, 0700, rootUID, rootGID); err != nil {
127 127
 		if os.IsExist(err) {
128 128
 			return a, nil
129 129
 		}
... ...
@@ -136,7 +136,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
136 136
 
137 137
 	// Populate the dir structure
138 138
 	for _, p := range paths {
139
-		if err := idtools.MkdirAllAs(path.Join(root, p), 0755, rootUID, rootGID); err != nil {
139
+		if err := idtools.MkdirAllAs(path.Join(root, p), 0700, rootUID, rootGID); err != nil {
140 140
 			return nil, err
141 141
 		}
142 142
 	}
... ...
@@ -146,7 +146,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
146 146
 		return nil, err
147 147
 	}
148 148
 	// Create the driver home dir
149
-	if err := idtools.MkdirAllAs(home, 0755, rootUID, rootGID); err != nil && !os.IsExist(err) {
149
+	if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) {
150 150
 		return nil, err
151 151
 	}
152 152