daemon_experimental.go 4.1 KB

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