github.com/gondor/docker@v1.9.0-rc1/daemon/daemon_experimental.go (about) 1 // +build experimental 2 3 package daemon 4 5 import ( 6 "fmt" 7 "os" 8 "path/filepath" 9 "runtime" 10 11 "github.com/Sirupsen/logrus" 12 "github.com/docker/docker/pkg/directory" 13 "github.com/docker/docker/pkg/idtools" 14 "github.com/docker/docker/runconfig" 15 ) 16 17 func setupRemappedRoot(config *Config) ([]idtools.IDMap, []idtools.IDMap, error) { 18 if config.ExecDriver != "native" && config.RemappedRoot != "" { 19 return nil, nil, fmt.Errorf("User namespace remapping is only supported with the native execdriver") 20 } 21 if runtime.GOOS == "windows" && config.RemappedRoot != "" { 22 return nil, nil, fmt.Errorf("User namespaces are not supported on Windows") 23 } 24 25 // if the daemon was started with remapped root option, parse 26 // the config option to the int uid,gid values 27 var ( 28 uidMaps, gidMaps []idtools.IDMap 29 ) 30 if config.RemappedRoot != "" { 31 username, groupname, err := parseRemappedRoot(config.RemappedRoot) 32 if err != nil { 33 return nil, nil, err 34 } 35 if username == "root" { 36 // Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op 37 // effectively 38 logrus.Warnf("User namespaces: root cannot be remapped with itself; user namespaces are OFF") 39 return uidMaps, gidMaps, nil 40 } 41 logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname) 42 // update remapped root setting now that we have resolved them to actual names 43 config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname) 44 45 uidMaps, gidMaps, err = idtools.CreateIDMappings(username, groupname) 46 if err != nil { 47 return nil, nil, fmt.Errorf("Can't create ID mappings: %v", err) 48 } 49 } 50 return uidMaps, gidMaps, nil 51 } 52 53 func setupDaemonRoot(config *Config, rootDir string, rootUID, rootGID int) error { 54 // the main docker root needs to be accessible by all users, as user namespace support 55 // will create subdirectories owned by either a) the real system root (when no remapping 56 // is setup) or b) the remapped root host ID (when --root=uid:gid is used) 57 // for "first time" users of user namespaces, we need to migrate the current directory 58 // contents to the "0.0" (root == root "namespace" daemon root) 59 nsRoot := "0.0" 60 if _, err := os.Stat(rootDir); err == nil { 61 // root current exists; we need to check for a prior migration 62 if _, err := os.Stat(filepath.Join(rootDir, nsRoot)); err != nil && os.IsNotExist(err) { 63 // need to migrate current root to "0.0" subroot 64 // 1. create non-usernamespaced root as "0.0" 65 if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil { 66 return fmt.Errorf("Cannot create daemon root %q: %v", filepath.Join(rootDir, nsRoot), err) 67 } 68 // 2. move current root content to "0.0" new subroot 69 if err := directory.MoveToSubdir(rootDir, nsRoot); err != nil { 70 return fmt.Errorf("Cannot migrate current daemon root %q for user namespaces: %v", rootDir, err) 71 } 72 // 3. chmod outer root to 755 73 if chmodErr := os.Chmod(rootDir, 0755); chmodErr != nil { 74 return chmodErr 75 } 76 } 77 } else if os.IsNotExist(err) { 78 // no root exists yet, create it 0755 with root:root ownership 79 if err := os.MkdirAll(rootDir, 0755); err != nil { 80 return err 81 } 82 // create the "0.0" subroot (so no future "migration" happens of the root) 83 if err := os.Mkdir(filepath.Join(rootDir, nsRoot), 0700); err != nil { 84 return err 85 } 86 } 87 88 // for user namespaces we will create a subtree underneath the specified root 89 // with any/all specified remapped root uid/gid options on the daemon creating 90 // a new subdirectory with ownership set to the remapped uid/gid (so as to allow 91 // `chdir()` to work for containers namespaced to that uid/gid) 92 if config.RemappedRoot != "" { 93 nsRoot = fmt.Sprintf("%d.%d", rootUID, rootGID) 94 } 95 config.Root = filepath.Join(rootDir, nsRoot) 96 logrus.Debugf("Creating actual daemon root: %s", config.Root) 97 98 // Create the root directory if it doesn't exists 99 if err := idtools.MkdirAllAs(config.Root, 0700, rootUID, rootGID); err != nil { 100 return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err) 101 } 102 return nil 103 } 104 105 func (daemon *Daemon) verifyExperimentalContainerSettings(hostConfig *runconfig.HostConfig, config *runconfig.Config) ([]string, error) { 106 if hostConfig.Privileged && daemon.config().RemappedRoot != "" { 107 return nil, fmt.Errorf("Privileged mode is incompatible with user namespace mappings") 108 } 109 return nil, nil 110 }