From e8532023f20498e6eb1ce5c079dc8a09aeae3061 Mon Sep 17 00:00:00 2001 From: Phil Estes Date: Tue, 5 Jan 2016 11:51:14 -0500 Subject: [PATCH] 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 (github: estesp) --- daemon/daemon_experimental.go | 56 +++++++++------------------ daemon/graphdriver/aufs/aufs.go | 4 +- daemon/graphdriver/overlay/overlay.go | 2 +- 3 files changed, 22 insertions(+), 40 deletions(-) diff --git a/daemon/daemon_experimental.go b/daemon/daemon_experimental.go index d50a8fb283..9ff05271a1 100644 --- a/daemon/daemon_experimental.go +++ b/daemon/daemon_experimental.go @@ -10,7 +10,6 @@ import ( "github.com/Sirupsen/logrus" "github.com/docker/docker/api/types/container" - "github.com/docker/docker/pkg/directory" "github.com/docker/docker/pkg/idtools" ) @@ -48,53 +47,36 @@ func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) } func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { - // the main docker root needs to be accessible by all users, as user namespace support - // will create subdirectories owned by either a) the real system root (when no remapping - // is setup) or b) the remapped root host ID (when --root=uid:gid is used) - // for "first time" users of user namespaces, we need to migrate the current directory - // contents to the "0.0" (root == root "namespace" daemon root) - nsRoot := "0.0" + config.Root = rootDir + // the docker root metadata directory needs to have execute permissions for all users (o+x) + // so that syscalls executing as non-root, operating on subdirectories of the graph root + // (e.g. mounted layers of a container) can traverse this path. + // The user namespace support will create subdirectories for the remapped root host uid:gid + // pair owned by that same uid:gid pair for proper write access to those needed metadata and + // layer content subtrees. if _, err := os.Stat(rootDir); err == nil { - // root current exists; we need to check for a prior migration - if _, err := os.Stat(filepath.Join(rootDir, nsRoot)); err != nil && os.IsNotExist(err) { - // need to migrate current root to "0.0" subroot - // 1. create non-usernamespaced root as "0.0" - if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil { - return fmt.Errorf("Cannot create daemon root %q: %v", filepath.Join(rootDir, nsRoot), err) - } - // 2. move current root content to "0.0" new subroot - if err := directory.MoveToSubdir(rootDir, nsRoot); err != nil { - return fmt.Errorf("Cannot migrate current daemon root %q for user namespaces: %v", rootDir, err) - } - // 3. chmod outer root to 755 - if chmodErr := os.Chmod(rootDir, 0755); chmodErr != nil { - return chmodErr - } - } - } else if os.IsNotExist(err) { - // no root exists yet, create it 0755 with root:root ownership - if err := os.MkdirAll(rootDir, 0755); err != nil { + // root current exists; verify the access bits are correct by setting them + if err = os.Chmod(rootDir, 0701); err != nil { return err } - // create the "0.0" subroot (so no future "migration" happens of the root) - if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil { + } else if os.IsNotExist(err) { + // no root exists yet, create it 0701 with root:root ownership + if err := os.MkdirAll(rootDir, 0701); err != nil { return err } } - // for user namespaces we will create a subtree underneath the specified root + // if user namespaces are enabled we will create a subtree underneath the specified root // with any/all specified remapped root uid/gid options on the daemon creating // a new subdirectory with ownership set to the remapped uid/gid (so as to allow // `chdir()` to work for containers namespaced to that uid/gid) if config.RemappedRoot != "" { - nsRoot = fmt.Sprintf("%d.%d", rootUID, rootGID) - } - config.Root = filepath.Join(rootDir, nsRoot) - logrus.Debugf("Creating actual daemon root: %s", config.Root) - - // Create the root directory if it doesn't exists - if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil { - return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err) + config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootUID, rootGID)) + logrus.Debugf("Creating user namespaced daemon root: %s", config.Root) + // Create the root directory if it doesn't exists + if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil { + return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err) + } } return nil } diff --git a/daemon/graphdriver/aufs/aufs.go b/daemon/graphdriver/aufs/aufs.go index aa24185ff4..26b3cef65c 100644 --- a/daemon/graphdriver/aufs/aufs.go +++ b/daemon/graphdriver/aufs/aufs.go @@ -123,7 +123,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap // Create the root aufs driver dir and return // if it already exists // If not populate the dir structure - if err := idtools.MkdirAllAs(root, 0755, rootUID, rootGID); err != nil { + if err := idtools.MkdirAllAs(root, 0700, rootUID, rootGID); err != nil { if os.IsExist(err) { return a, nil } @@ -136,7 +136,7 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap // Populate the dir structure for _, p := range paths { - if err := idtools.MkdirAllAs(path.Join(root, p), 0755, rootUID, rootGID); err != nil { + if err := idtools.MkdirAllAs(path.Join(root, p), 0700, rootUID, rootGID); err != nil { return nil, err } } diff --git a/daemon/graphdriver/overlay/overlay.go b/daemon/graphdriver/overlay/overlay.go index 201d5f65fa..59131bba08 100644 --- a/daemon/graphdriver/overlay/overlay.go +++ b/daemon/graphdriver/overlay/overlay.go @@ -146,7 +146,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap return nil, err } // Create the driver home dir - if err := idtools.MkdirAllAs(home, 0755, rootUID, rootGID); err != nil && !os.IsExist(err) { + if err := idtools.MkdirAllAs(home, 0700, rootUID, rootGID); err != nil && !os.IsExist(err) { return nil, err }