1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00
moby--moby/daemon/daemon_experimental.go
Phil Estes e8532023f2 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)
2016-01-05 11:51:14 -05:00

89 lines
3.4 KiB
Go

// +build experimental
package daemon
import (
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/idtools"
)
func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) {
if runtime.GOOS != "linux" && config.RemappedRoot != "" {
return nil, nil, fmt.Errorf("User namespaces are only supported on Linux")
}
// if the daemon was started with remapped root option, parse
// the config option to the int uid,gid values
var (
uidMaps, gidMaps []idtools.IDMap
)
if config.RemappedRoot != "" {
username, groupname, err := parseRemappedRoot(config.RemappedRoot)
if err != nil {
return nil, nil, err
}
if username == "root" {
// Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
// effectively
logrus.Warnf("User namespaces: root cannot be remapped with itself; user namespaces are OFF")
return uidMaps, gidMaps, nil
}
logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname)
// update remapped root setting now that we have resolved them to actual names
config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
uidMaps, gidMaps, err = idtools.CreateIDMappings(username, groupname)
if err != nil {
return nil, nil, fmt.Errorf("Can't create ID mappings: %v", err)
}
}
return uidMaps, gidMaps, nil
}
func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error {
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; verify the access bits are correct by setting them
if err = os.Chmod(rootDir, 0701); err != nil {
return err
}
} 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
}
}
// 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 != "" {
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
}
func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *container.HostConfig, config *container.Config) ([]string, error) {
if hostConfig.Privileged && daemon.configStore.RemappedRoot != "" {
return nil, fmt.Errorf("Privileged mode is incompatible with user namespace mappings")
}
return nil, nil
}