mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Add ADD/COPY --chown flag support to Windows
This implements chown support on Windows. Built-in accounts as well as accounts included in the SAM database of the container are supported. NOTE: IDPair is now named Identity and IDMappings is now named IdentityMapping. The following are valid examples: ADD --chown=Guest . <some directory> COPY --chown=Administrator . <some directory> COPY --chown=Guests . <some directory> COPY --chown=ContainerUser . <some directory> On Windows an owner is only granted the permission to read the security descriptor and read/write the discretionary access control list. This fix also grants read/write and execute permissions to the owner. Signed-off-by: Salahuddin Khan <salah@docker.com>
This commit is contained in:
		
							parent
							
								
									1fd7e4c28d
								
							
						
					
					
						commit
						763d839261
					
				
					 64 changed files with 610 additions and 301 deletions
				
			
		| 
						 | 
					@ -56,21 +56,21 @@ type SessionGetter interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BuildManager is shared across all Builder objects
 | 
					// BuildManager is shared across all Builder objects
 | 
				
			||||||
type BuildManager struct {
 | 
					type BuildManager struct {
 | 
				
			||||||
	idMappings *idtools.IDMappings
 | 
						idMapping *idtools.IdentityMapping
 | 
				
			||||||
	backend    builder.Backend
 | 
						backend   builder.Backend
 | 
				
			||||||
	pathCache  pathCache // TODO: make this persistent
 | 
						pathCache pathCache // TODO: make this persistent
 | 
				
			||||||
	sg         SessionGetter
 | 
						sg        SessionGetter
 | 
				
			||||||
	fsCache    *fscache.FSCache
 | 
						fsCache   *fscache.FSCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewBuildManager creates a BuildManager
 | 
					// NewBuildManager creates a BuildManager
 | 
				
			||||||
func NewBuildManager(b builder.Backend, sg SessionGetter, fsCache *fscache.FSCache, idMappings *idtools.IDMappings) (*BuildManager, error) {
 | 
					func NewBuildManager(b builder.Backend, sg SessionGetter, fsCache *fscache.FSCache, identityMapping *idtools.IdentityMapping) (*BuildManager, error) {
 | 
				
			||||||
	bm := &BuildManager{
 | 
						bm := &BuildManager{
 | 
				
			||||||
		backend:    b,
 | 
							backend:   b,
 | 
				
			||||||
		pathCache:  &syncmap.Map{},
 | 
							pathCache: &syncmap.Map{},
 | 
				
			||||||
		sg:         sg,
 | 
							sg:        sg,
 | 
				
			||||||
		idMappings: idMappings,
 | 
							idMapping: identityMapping,
 | 
				
			||||||
		fsCache:    fsCache,
 | 
							fsCache:   fsCache,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := fsCache.RegisterTransport(remotecontext.ClientSessionRemote, NewClientSessionTransport()); err != nil {
 | 
						if err := fsCache.RegisterTransport(remotecontext.ClientSessionRemote, NewClientSessionTransport()); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (
 | 
				
			||||||
		ProgressWriter: config.ProgressWriter,
 | 
							ProgressWriter: config.ProgressWriter,
 | 
				
			||||||
		Backend:        bm.backend,
 | 
							Backend:        bm.backend,
 | 
				
			||||||
		PathCache:      bm.pathCache,
 | 
							PathCache:      bm.pathCache,
 | 
				
			||||||
		IDMappings:     bm.idMappings,
 | 
							IDMapping:      bm.idMapping,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	b, err := newBuilder(ctx, builderOptions)
 | 
						b, err := newBuilder(ctx, builderOptions)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -159,7 +159,7 @@ type builderOptions struct {
 | 
				
			||||||
	Backend        builder.Backend
 | 
						Backend        builder.Backend
 | 
				
			||||||
	ProgressWriter backend.ProgressWriter
 | 
						ProgressWriter backend.ProgressWriter
 | 
				
			||||||
	PathCache      pathCache
 | 
						PathCache      pathCache
 | 
				
			||||||
	IDMappings     *idtools.IDMappings
 | 
						IDMapping      *idtools.IdentityMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Builder is a Dockerfile builder
 | 
					// Builder is a Dockerfile builder
 | 
				
			||||||
| 
						 | 
					@ -175,7 +175,7 @@ type Builder struct {
 | 
				
			||||||
	docker    builder.Backend
 | 
						docker    builder.Backend
 | 
				
			||||||
	clientCtx context.Context
 | 
						clientCtx context.Context
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idMappings       *idtools.IDMappings
 | 
						idMapping        *idtools.IdentityMapping
 | 
				
			||||||
	disableCommit    bool
 | 
						disableCommit    bool
 | 
				
			||||||
	imageSources     *imageSources
 | 
						imageSources     *imageSources
 | 
				
			||||||
	pathCache        pathCache
 | 
						pathCache        pathCache
 | 
				
			||||||
| 
						 | 
					@ -199,7 +199,7 @@ func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, er
 | 
				
			||||||
		Aux:              options.ProgressWriter.AuxFormatter,
 | 
							Aux:              options.ProgressWriter.AuxFormatter,
 | 
				
			||||||
		Output:           options.ProgressWriter.Output,
 | 
							Output:           options.ProgressWriter.Output,
 | 
				
			||||||
		docker:           options.Backend,
 | 
							docker:           options.Backend,
 | 
				
			||||||
		idMappings:       options.IDMappings,
 | 
							idMapping:        options.IDMapping,
 | 
				
			||||||
		imageSources:     newImageSources(clientCtx, options),
 | 
							imageSources:     newImageSources(clientCtx, options),
 | 
				
			||||||
		pathCache:        options.PathCache,
 | 
							pathCache:        options.PathCache,
 | 
				
			||||||
		imageProber:      newImageProber(options.Backend, config.CacheFrom, config.NoCache),
 | 
							imageProber:      newImageProber(options.Backend, config.CacheFrom, config.NoCache),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -451,7 +451,7 @@ func downloadSource(output io.Writer, stdout io.Writer, srcURL string) (remote b
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type copyFileOptions struct {
 | 
					type copyFileOptions struct {
 | 
				
			||||||
	decompress bool
 | 
						decompress bool
 | 
				
			||||||
	chownPair  idtools.IDPair
 | 
						identity   idtools.Identity
 | 
				
			||||||
	archiver   Archiver
 | 
						archiver   Archiver
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -481,7 +481,7 @@ func performCopyForInfo(dest copyInfo, source copyInfo, options copyFileOptions)
 | 
				
			||||||
		return errors.Wrapf(err, "source path not found")
 | 
							return errors.Wrapf(err, "source path not found")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if src.IsDir() {
 | 
						if src.IsDir() {
 | 
				
			||||||
		return copyDirectory(archiver, srcEndpoint, destEndpoint, options.chownPair)
 | 
							return copyDirectory(archiver, srcEndpoint, destEndpoint, options.identity)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if options.decompress && isArchivePath(source.root, srcPath) && !source.noDecompress {
 | 
						if options.decompress && isArchivePath(source.root, srcPath) && !source.noDecompress {
 | 
				
			||||||
		return archiver.UntarPath(srcPath, destPath)
 | 
							return archiver.UntarPath(srcPath, destPath)
 | 
				
			||||||
| 
						 | 
					@ -499,7 +499,7 @@ func performCopyForInfo(dest copyInfo, source copyInfo, options copyFileOptions)
 | 
				
			||||||
		destPath = dest.root.Join(destPath, source.root.Base(source.path))
 | 
							destPath = dest.root.Join(destPath, source.root.Base(source.path))
 | 
				
			||||||
		destEndpoint = ©Endpoint{driver: dest.root, path: destPath}
 | 
							destEndpoint = ©Endpoint{driver: dest.root, path: destPath}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return copyFile(archiver, srcEndpoint, destEndpoint, options.chownPair)
 | 
						return copyFile(archiver, srcEndpoint, destEndpoint, options.identity)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func isArchivePath(driver containerfs.ContainerFS, path string) bool {
 | 
					func isArchivePath(driver containerfs.ContainerFS, path string) bool {
 | 
				
			||||||
| 
						 | 
					@ -517,7 +517,7 @@ func isArchivePath(driver containerfs.ContainerFS, path string) bool {
 | 
				
			||||||
	return err == nil
 | 
						return err == nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func copyDirectory(archiver Archiver, source, dest *copyEndpoint, chownPair idtools.IDPair) error {
 | 
					func copyDirectory(archiver Archiver, source, dest *copyEndpoint, identity idtools.Identity) error {
 | 
				
			||||||
	destExists, err := isExistingDirectory(dest)
 | 
						destExists, err := isExistingDirectory(dest)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.Wrapf(err, "failed to query destination path")
 | 
							return errors.Wrapf(err, "failed to query destination path")
 | 
				
			||||||
| 
						 | 
					@ -527,17 +527,17 @@ func copyDirectory(archiver Archiver, source, dest *copyEndpoint, chownPair idto
 | 
				
			||||||
		return errors.Wrapf(err, "failed to copy directory")
 | 
							return errors.Wrapf(err, "failed to copy directory")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: @gupta-ak. Investigate how LCOW permission mappings will work.
 | 
						// TODO: @gupta-ak. Investigate how LCOW permission mappings will work.
 | 
				
			||||||
	return fixPermissions(source.path, dest.path, chownPair, !destExists)
 | 
						return fixPermissions(source.path, dest.path, identity, !destExists)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func copyFile(archiver Archiver, source, dest *copyEndpoint, chownPair idtools.IDPair) error {
 | 
					func copyFile(archiver Archiver, source, dest *copyEndpoint, identity idtools.Identity) error {
 | 
				
			||||||
	if runtime.GOOS == "windows" && dest.driver.OS() == "linux" {
 | 
						if runtime.GOOS == "windows" && dest.driver.OS() == "linux" {
 | 
				
			||||||
		// LCOW
 | 
							// LCOW
 | 
				
			||||||
		if err := dest.driver.MkdirAll(dest.driver.Dir(dest.path), 0755); err != nil {
 | 
							if err := dest.driver.MkdirAll(dest.driver.Dir(dest.path), 0755); err != nil {
 | 
				
			||||||
			return errors.Wrapf(err, "failed to create new directory")
 | 
								return errors.Wrapf(err, "failed to create new directory")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if err := idtools.MkdirAllAndChownNew(filepath.Dir(dest.path), 0755, chownPair); err != nil {
 | 
							if err := idtools.MkdirAllAndChownNew(filepath.Dir(dest.path), 0755, identity); err != nil {
 | 
				
			||||||
			// Normal containers
 | 
								// Normal containers
 | 
				
			||||||
			return errors.Wrapf(err, "failed to create new directory")
 | 
								return errors.Wrapf(err, "failed to create new directory")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -547,7 +547,7 @@ func copyFile(archiver Archiver, source, dest *copyEndpoint, chownPair idtools.I
 | 
				
			||||||
		return errors.Wrapf(err, "failed to copy file")
 | 
							return errors.Wrapf(err, "failed to copy file")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: @gupta-ak. Investigate how LCOW permission mappings will work.
 | 
						// TODO: @gupta-ak. Investigate how LCOW permission mappings will work.
 | 
				
			||||||
	return fixPermissions(source.path, dest.path, chownPair, false)
 | 
						return fixPermissions(source.path, dest.path, identity, false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func endsInSlash(driver containerfs.Driver, path string) bool {
 | 
					func endsInSlash(driver containerfs.Driver, path string) bool {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/pkg/idtools"
 | 
						"github.com/docker/docker/pkg/idtools"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fixPermissions(source, destination string, rootIDs idtools.IDPair, overrideSkip bool) error {
 | 
					func fixPermissions(source, destination string, identity idtools.Identity, overrideSkip bool) error {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		skipChownRoot bool
 | 
							skipChownRoot bool
 | 
				
			||||||
		err           error
 | 
							err           error
 | 
				
			||||||
| 
						 | 
					@ -39,7 +39,7 @@ func fixPermissions(source, destination string, rootIDs idtools.IDPair, override
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		fullpath = filepath.Join(destination, cleaned)
 | 
							fullpath = filepath.Join(destination, cleaned)
 | 
				
			||||||
		return os.Lchown(fullpath, rootIDs.UID, rootIDs.GID)
 | 
							return os.Lchown(fullpath, identity.UID, identity.GID)
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,11 +1,17 @@
 | 
				
			||||||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
 | 
					package dockerfile // import "github.com/docker/docker/builder/dockerfile"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/Microsoft/go-winio"
 | 
				
			||||||
	"github.com/docker/docker/pkg/idtools"
 | 
						"github.com/docker/docker/pkg/idtools"
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/reexec"
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/system"
 | 
				
			||||||
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var pathBlacklist = map[string]bool{
 | 
					var pathBlacklist = map[string]bool{
 | 
				
			||||||
| 
						 | 
					@ -13,9 +19,69 @@ var pathBlacklist = map[string]bool{
 | 
				
			||||||
	"c:\\windows": true,
 | 
						"c:\\windows": true,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func fixPermissions(source, destination string, rootIDs idtools.IDPair, overrideSkip bool) error {
 | 
					func init() {
 | 
				
			||||||
	// chown is not supported on Windows
 | 
						reexec.Register("windows-fix-permissions", fixPermissionsReexec)
 | 
				
			||||||
	return nil
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fixPermissions(source, destination string, identity idtools.Identity, _ bool) error {
 | 
				
			||||||
 | 
						if identity.SID == "" {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd := reexec.Command("windows-fix-permissions", source, destination, identity.SID)
 | 
				
			||||||
 | 
						output, err := cmd.CombinedOutput()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return errors.Wrapf(err, "failed to exec windows-fix-permissions: %s", output)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fixPermissionsReexec() {
 | 
				
			||||||
 | 
						err := fixPermissionsWindows(os.Args[1], os.Args[2], os.Args[3])
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fmt.Fprint(os.Stderr, err)
 | 
				
			||||||
 | 
							os.Exit(1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fixPermissionsWindows(source, destination, SID string) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						privileges := []string{winio.SeRestorePrivilege, system.SeTakeOwnershipPrivilege}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := winio.EnableProcessPrivileges(privileges)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer winio.DisableProcessPrivileges(privileges)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sid, err := windows.StringToSid(SID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Owners on *nix have read/write/delete/read control and write DAC.
 | 
				
			||||||
 | 
						// Add an ACE that grants this to the user/group specified with the
 | 
				
			||||||
 | 
						// chown option. Currently Windows is not honoring the owner change,
 | 
				
			||||||
 | 
						// however, they are aware of this and it should be fixed at some
 | 
				
			||||||
 | 
						// point.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sddlString := system.SddlAdministratorsLocalSystem
 | 
				
			||||||
 | 
						sddlString += "(A;OICI;GRGWGXRCWDSD;;;" + SID + ")"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						securityDescriptor, err := winio.SddlToSecurityDescriptor(sddlString)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var daclPresent uint32
 | 
				
			||||||
 | 
						var daclDefaulted uint32
 | 
				
			||||||
 | 
						var dacl *byte
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = system.GetSecurityDescriptorDacl(&securityDescriptor[0], &daclPresent, &dacl, &daclDefaulted)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return system.SetNamedSecurityInfo(windows.StringToUTF16Ptr(destination), system.SE_FILE_OBJECT, system.OWNER_SECURITY_INFORMATION|system.DACL_SECURITY_INFORMATION, sid, nil, dacl, nil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func validateCopySourcePath(imageSource *imageMount, origPath, platform string) error {
 | 
					func validateCopySourcePath(imageSource *imageMount, origPath, platform string) error {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,7 +37,7 @@ type Archiver interface {
 | 
				
			||||||
	UntarPath(src, dst string) error
 | 
						UntarPath(src, dst string) error
 | 
				
			||||||
	CopyWithTar(src, dst string) error
 | 
						CopyWithTar(src, dst string) error
 | 
				
			||||||
	CopyFileWithTar(src, dst string) error
 | 
						CopyFileWithTar(src, dst string) error
 | 
				
			||||||
	IDMappings() *idtools.IDMappings
 | 
						IdentityMapping() *idtools.IdentityMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The builder will use the following interfaces if the container fs implements
 | 
					// The builder will use the following interfaces if the container fs implements
 | 
				
			||||||
| 
						 | 
					@ -68,11 +68,11 @@ func tarFunc(i interface{}) containerfs.TarFunc {
 | 
				
			||||||
func (b *Builder) getArchiver(src, dst containerfs.Driver) Archiver {
 | 
					func (b *Builder) getArchiver(src, dst containerfs.Driver) Archiver {
 | 
				
			||||||
	t, u := tarFunc(src), untarFunc(dst)
 | 
						t, u := tarFunc(src), untarFunc(dst)
 | 
				
			||||||
	return &containerfs.Archiver{
 | 
						return &containerfs.Archiver{
 | 
				
			||||||
		SrcDriver:     src,
 | 
							SrcDriver: src,
 | 
				
			||||||
		DstDriver:     dst,
 | 
							DstDriver: dst,
 | 
				
			||||||
		Tar:           t,
 | 
							Tar:       t,
 | 
				
			||||||
		Untar:         u,
 | 
							Untar:     u,
 | 
				
			||||||
		IDMappingsVar: b.idMappings,
 | 
							IDMapping: b.idMapping,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -185,14 +185,18 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	chownPair := b.idMappings.RootPair()
 | 
						identity := b.idMapping.RootPair()
 | 
				
			||||||
	// if a chown was requested, perform the steps to get the uid, gid
 | 
						// if a chown was requested, perform the steps to get the uid, gid
 | 
				
			||||||
	// translated (if necessary because of user namespaces), and replace
 | 
						// translated (if necessary because of user namespaces), and replace
 | 
				
			||||||
	// the root pair with the chown pair for copy operations
 | 
						// the root pair with the chown pair for copy operations
 | 
				
			||||||
	if inst.chownStr != "" {
 | 
						if inst.chownStr != "" {
 | 
				
			||||||
		chownPair, err = parseChownFlag(inst.chownStr, destInfo.root.Path(), b.idMappings)
 | 
							identity, err = parseChownFlag(b, state, inst.chownStr, destInfo.root.Path(), b.idMapping)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping")
 | 
								if b.options.Platform != "windows" {
 | 
				
			||||||
 | 
									return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return errors.Wrapf(err, "unable to map container user account name to SID")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +204,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
 | 
				
			||||||
		opts := copyFileOptions{
 | 
							opts := copyFileOptions{
 | 
				
			||||||
			decompress: inst.allowLocalDecompression,
 | 
								decompress: inst.allowLocalDecompression,
 | 
				
			||||||
			archiver:   b.getArchiver(info.root, destInfo.root),
 | 
								archiver:   b.getArchiver(info.root, destInfo.root),
 | 
				
			||||||
			chownPair:  chownPair,
 | 
								identity:   identity,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := performCopyForInfo(destInfo, info, opts); err != nil {
 | 
							if err := performCopyForInfo(destInfo, info, opts); err != nil {
 | 
				
			||||||
			return errors.Wrapf(err, "failed to copy files")
 | 
								return errors.Wrapf(err, "failed to copy files")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,11 +11,11 @@ import (
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
 | 
					func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping *idtools.IdentityMapping) (idtools.Identity, error) {
 | 
				
			||||||
	var userStr, grpStr string
 | 
						var userStr, grpStr string
 | 
				
			||||||
	parts := strings.Split(chown, ":")
 | 
						parts := strings.Split(chown, ":")
 | 
				
			||||||
	if len(parts) > 2 {
 | 
						if len(parts) > 2 {
 | 
				
			||||||
		return idtools.IDPair{}, errors.New("invalid chown string format: " + chown)
 | 
							return idtools.Identity{}, errors.New("invalid chown string format: " + chown)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(parts) == 1 {
 | 
						if len(parts) == 1 {
 | 
				
			||||||
		// if no group specified, use the user spec as group as well
 | 
							// if no group specified, use the user spec as group as well
 | 
				
			||||||
| 
						 | 
					@ -26,25 +26,25 @@ func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
 | 
						passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
 | 
							return idtools.Identity{}, errors.Wrapf(err, "can't resolve /etc/passwd path in container rootfs")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
 | 
						groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return idtools.IDPair{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
 | 
							return idtools.Identity{}, errors.Wrapf(err, "can't resolve /etc/group path in container rootfs")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	uid, err := lookupUser(userStr, passwdPath)
 | 
						uid, err := lookupUser(userStr, passwdPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return idtools.IDPair{}, errors.Wrapf(err, "can't find uid for user "+userStr)
 | 
							return idtools.Identity{}, errors.Wrapf(err, "can't find uid for user "+userStr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	gid, err := lookupGroup(grpStr, groupPath)
 | 
						gid, err := lookupGroup(grpStr, groupPath)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return idtools.IDPair{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
 | 
							return idtools.Identity{}, errors.Wrapf(err, "can't find gid for group "+grpStr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// convert as necessary because of user namespaces
 | 
						// convert as necessary because of user namespaces
 | 
				
			||||||
	chownPair, err := idMappings.ToHost(idtools.IDPair{UID: uid, GID: gid})
 | 
						chownPair, err := identityMapping.ToHost(idtools.Identity{UID: uid, GID: gid})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return idtools.IDPair{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
 | 
							return idtools.Identity{}, errors.Wrapf(err, "unable to convert uid/gid to host mapping")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return chownPair, nil
 | 
						return chownPair, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import (
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/docker/docker/api/types"
 | 
				
			||||||
	"github.com/docker/docker/pkg/idtools"
 | 
						"github.com/docker/docker/pkg/idtools"
 | 
				
			||||||
	"gotest.tools/assert"
 | 
						"gotest.tools/assert"
 | 
				
			||||||
	is "gotest.tools/assert/cmp"
 | 
						is "gotest.tools/assert/cmp"
 | 
				
			||||||
| 
						 | 
					@ -34,7 +35,7 @@ othergrp:x:6666:
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps)
 | 
						remapped := idtools.NewIDMappingsFromMaps(idMaps, idMaps)
 | 
				
			||||||
	unmapped := &idtools.IDMappings{}
 | 
						unmapped := &idtools.IdentityMapping{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
 | 
						contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
 | 
				
			||||||
	defer cleanup()
 | 
						defer cleanup()
 | 
				
			||||||
| 
						 | 
					@ -49,56 +50,72 @@ othergrp:x:6666:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// positive tests
 | 
						// positive tests
 | 
				
			||||||
	for _, testcase := range []struct {
 | 
						for _, testcase := range []struct {
 | 
				
			||||||
 | 
							builder   *Builder
 | 
				
			||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		chownStr  string
 | 
							chownStr  string
 | 
				
			||||||
		idMapping *idtools.IDMappings
 | 
							idMapping *idtools.IdentityMapping
 | 
				
			||||||
		expected  idtools.IDPair
 | 
							state     *dispatchState
 | 
				
			||||||
 | 
							expected  idtools.Identity
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UIDNoMap",
 | 
								name:      "UIDNoMap",
 | 
				
			||||||
			chownStr:  "1",
 | 
								chownStr:  "1",
 | 
				
			||||||
			idMapping: unmapped,
 | 
								idMapping: unmapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 1, GID: 1},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 1, GID: 1},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UIDGIDNoMap",
 | 
								name:      "UIDGIDNoMap",
 | 
				
			||||||
			chownStr:  "0:1",
 | 
								chownStr:  "0:1",
 | 
				
			||||||
			idMapping: unmapped,
 | 
								idMapping: unmapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 0, GID: 1},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 0, GID: 1},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UIDWithMap",
 | 
								name:      "UIDWithMap",
 | 
				
			||||||
			chownStr:  "0",
 | 
								chownStr:  "0",
 | 
				
			||||||
			idMapping: remapped,
 | 
								idMapping: remapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 100000, GID: 100000},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 100000, GID: 100000},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UIDGIDWithMap",
 | 
								name:      "UIDGIDWithMap",
 | 
				
			||||||
			chownStr:  "1:33",
 | 
								chownStr:  "1:33",
 | 
				
			||||||
			idMapping: remapped,
 | 
								idMapping: remapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 100001, GID: 100033},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 100001, GID: 100033},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UserNoMap",
 | 
								name:      "UserNoMap",
 | 
				
			||||||
			chownStr:  "bin:5555",
 | 
								chownStr:  "bin:5555",
 | 
				
			||||||
			idMapping: unmapped,
 | 
								idMapping: unmapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 1, GID: 5555},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 1, GID: 5555},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "GroupWithMap",
 | 
								name:      "GroupWithMap",
 | 
				
			||||||
			chownStr:  "0:unicorn",
 | 
								chownStr:  "0:unicorn",
 | 
				
			||||||
			idMapping: remapped,
 | 
								idMapping: remapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 100000, GID: 101002},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 100000, GID: 101002},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UserOnlyWithMap",
 | 
								name:      "UserOnlyWithMap",
 | 
				
			||||||
			chownStr:  "unicorn",
 | 
								chownStr:  "unicorn",
 | 
				
			||||||
			idMapping: remapped,
 | 
								idMapping: remapped,
 | 
				
			||||||
			expected:  idtools.IDPair{UID: 101001, GID: 101002},
 | 
								state:     &dispatchState{},
 | 
				
			||||||
 | 
								expected:  idtools.Identity{UID: 101001, GID: 101002},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	} {
 | 
						} {
 | 
				
			||||||
		t.Run(testcase.name, func(t *testing.T) {
 | 
							t.Run(testcase.name, func(t *testing.T) {
 | 
				
			||||||
			idPair, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
 | 
								idPair, err := parseChownFlag(testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
 | 
				
			||||||
			assert.NilError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
 | 
								assert.NilError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
 | 
				
			||||||
			assert.Check(t, is.DeepEqual(testcase.expected, idPair), "chown flag mapping failure")
 | 
								assert.Check(t, is.DeepEqual(testcase.expected, idPair), "chown flag mapping failure")
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
| 
						 | 
					@ -106,32 +123,40 @@ othergrp:x:6666:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// error tests
 | 
						// error tests
 | 
				
			||||||
	for _, testcase := range []struct {
 | 
						for _, testcase := range []struct {
 | 
				
			||||||
 | 
							builder   *Builder
 | 
				
			||||||
		name      string
 | 
							name      string
 | 
				
			||||||
		chownStr  string
 | 
							chownStr  string
 | 
				
			||||||
		idMapping *idtools.IDMappings
 | 
							idMapping *idtools.IdentityMapping
 | 
				
			||||||
 | 
							state     *dispatchState
 | 
				
			||||||
		descr     string
 | 
							descr     string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "BadChownFlagFormat",
 | 
								name:      "BadChownFlagFormat",
 | 
				
			||||||
			chownStr:  "bob:1:555",
 | 
								chownStr:  "bob:1:555",
 | 
				
			||||||
			idMapping: unmapped,
 | 
								idMapping: unmapped,
 | 
				
			||||||
 | 
								state:     &dispatchState{},
 | 
				
			||||||
			descr:     "invalid chown string format: bob:1:555",
 | 
								descr:     "invalid chown string format: bob:1:555",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "UserNoExist",
 | 
								name:      "UserNoExist",
 | 
				
			||||||
			chownStr:  "bob",
 | 
								chownStr:  "bob",
 | 
				
			||||||
			idMapping: unmapped,
 | 
								idMapping: unmapped,
 | 
				
			||||||
 | 
								state:     &dispatchState{},
 | 
				
			||||||
			descr:     "can't find uid for user bob: no such user: bob",
 | 
								descr:     "can't find uid for user bob: no such user: bob",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								builder:   &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
 | 
				
			||||||
			name:      "GroupNoExist",
 | 
								name:      "GroupNoExist",
 | 
				
			||||||
			chownStr:  "root:bob",
 | 
								chownStr:  "root:bob",
 | 
				
			||||||
			idMapping: unmapped,
 | 
								idMapping: unmapped,
 | 
				
			||||||
 | 
								state:     &dispatchState{},
 | 
				
			||||||
			descr:     "can't find gid for group bob: no such group: bob",
 | 
								descr:     "can't find gid for group bob: no such group: bob",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	} {
 | 
						} {
 | 
				
			||||||
		t.Run(testcase.name, func(t *testing.T) {
 | 
							t.Run(testcase.name, func(t *testing.T) {
 | 
				
			||||||
			_, err := parseChownFlag(testcase.chownStr, contextDir, testcase.idMapping)
 | 
								_, err := parseChownFlag(testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
 | 
				
			||||||
			assert.Check(t, is.Error(err, testcase.descr), "Expected error string doesn't match")
 | 
								assert.Check(t, is.Error(err, testcase.descr), "Expected error string doesn't match")
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,120 @@
 | 
				
			||||||
package dockerfile // import "github.com/docker/docker/builder/dockerfile"
 | 
					package dockerfile // import "github.com/docker/docker/builder/dockerfile"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import "github.com/docker/docker/pkg/idtools"
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseChownFlag(chown, ctrRootPath string, idMappings *idtools.IDMappings) (idtools.IDPair, error) {
 | 
						"github.com/containerd/containerd/platforms"
 | 
				
			||||||
	return idMappings.RootPair(), nil
 | 
						"github.com/docker/docker/api/types/container"
 | 
				
			||||||
 | 
						"github.com/docker/docker/api/types/mount"
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/idtools"
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/jsonmessage"
 | 
				
			||||||
 | 
						"github.com/docker/docker/pkg/system"
 | 
				
			||||||
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping *idtools.IdentityMapping) (idtools.Identity, error) {
 | 
				
			||||||
 | 
						if builder.options.Platform == "windows" {
 | 
				
			||||||
 | 
							return getAccountIdentity(builder, chown, ctrRootPath, state)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return identityMapping.RootPair(), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getAccountIdentity(builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) {
 | 
				
			||||||
 | 
						// If this is potentially a string SID then attempt to convert it to verify
 | 
				
			||||||
 | 
						// this, otherwise continue looking for the account.
 | 
				
			||||||
 | 
						if strings.HasPrefix(accountName, "S-") || strings.HasPrefix(accountName, "s-") {
 | 
				
			||||||
 | 
							sid, err := windows.StringToSid(accountName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								accountSid, err := sid.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return idtools.Identity{SID: ""}, errors.Wrapf(err, "error converting SID to string")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return idtools.Identity{SID: accountSid}, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Attempt to obtain the SID using the name.
 | 
				
			||||||
 | 
						sid, _, accType, err := windows.LookupSID("", accountName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If this is a SID that is built-in and hence the same across all systems then use that.
 | 
				
			||||||
 | 
						if err == nil && (accType == windows.SidTypeAlias || accType == windows.SidTypeWellKnownGroup) {
 | 
				
			||||||
 | 
							accountSid, err := sid.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return idtools.Identity{SID: ""}, errors.Wrapf(err, "error converting SID to string")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return idtools.Identity{SID: accountSid}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if the account name is one unique to containers.
 | 
				
			||||||
 | 
						if strings.EqualFold(accountName, "ContainerAdministrator") {
 | 
				
			||||||
 | 
							return idtools.Identity{SID: system.ContainerAdministratorSidString}, nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						} else if strings.EqualFold(accountName, "ContainerUser") {
 | 
				
			||||||
 | 
							return idtools.Identity{SID: system.ContainerUserSidString}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// All other lookups failed, so therefore determine if the account in
 | 
				
			||||||
 | 
						// question exists in the container and if so, obtain its SID.
 | 
				
			||||||
 | 
						return lookupNTAccount(builder, accountName, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lookupNTAccount(builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						source, _ := filepath.Split(os.Args[0])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						target := "C:\\Docker"
 | 
				
			||||||
 | 
						targetExecutable := target + "\\containerutility.exe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						optionsPlatform, err := platforms.Parse(builder.options.Platform)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return idtools.Identity{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						runConfig := copyRunConfig(state.runConfig,
 | 
				
			||||||
 | 
							withCmdCommentString("internal run to obtain NT account information.", optionsPlatform.OS))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						runConfig.ArgsEscaped = true
 | 
				
			||||||
 | 
						runConfig.Cmd = []string{targetExecutable, "getaccountsid", accountName}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						hostConfig := &container.HostConfig{Mounts: []mount.Mount{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Type:     mount.TypeBind,
 | 
				
			||||||
 | 
								Source:   source,
 | 
				
			||||||
 | 
								Target:   target,
 | 
				
			||||||
 | 
								ReadOnly: true,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						container, err := builder.containerManager.Create(runConfig, hostConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return idtools.Identity{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stdout := new(bytes.Buffer)
 | 
				
			||||||
 | 
						stderr := new(bytes.Buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := builder.containerManager.Run(builder.clientCtx, container.ID, stdout, stderr); err != nil {
 | 
				
			||||||
 | 
							if err, ok := err.(*statusCodeError); ok {
 | 
				
			||||||
 | 
								return idtools.Identity{}, &jsonmessage.JSONError{
 | 
				
			||||||
 | 
									Message: stderr.String(),
 | 
				
			||||||
 | 
									Code:    err.StatusCode(),
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return idtools.Identity{}, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accountSid := stdout.String()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return idtools.Identity{SID: accountSid}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -267,7 +267,7 @@ func newRouterOptions(config *config.Config, daemon *daemon.Daemon) (routerOptio
 | 
				
			||||||
		return opts, errors.Wrap(err, "failed to create fscache")
 | 
							return opts, errors.Wrap(err, "failed to create fscache")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	manager, err := dockerfile.NewBuildManager(daemon.BuilderBackend(), sm, buildCache, daemon.IDMappings())
 | 
						manager, err := dockerfile.NewBuildManager(daemon.BuilderBackend(), sm, buildCache, daemon.IdentityMapping())
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return opts, err
 | 
							return opts, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -254,7 +254,7 @@ func (container *Container) WriteHostConfig() (*containertypes.HostConfig, error
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// SetupWorkingDirectory sets up the container's working directory as set in container.Config.WorkingDir
 | 
					// SetupWorkingDirectory sets up the container's working directory as set in container.Config.WorkingDir
 | 
				
			||||||
func (container *Container) SetupWorkingDirectory(rootIDs idtools.IDPair) error {
 | 
					func (container *Container) SetupWorkingDirectory(rootIdentity idtools.Identity) error {
 | 
				
			||||||
	// TODO @jhowardmsft, @gupta-ak LCOW Support. This will need revisiting.
 | 
						// TODO @jhowardmsft, @gupta-ak LCOW Support. This will need revisiting.
 | 
				
			||||||
	// We will need to do remote filesystem operations here.
 | 
						// We will need to do remote filesystem operations here.
 | 
				
			||||||
	if container.OS != runtime.GOOS {
 | 
						if container.OS != runtime.GOOS {
 | 
				
			||||||
| 
						 | 
					@ -271,7 +271,7 @@ func (container *Container) SetupWorkingDirectory(rootIDs idtools.IDPair) error
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAllAndChownNew(pth, 0755, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChownNew(pth, 0755, rootIdentity); err != nil {
 | 
				
			||||||
		pthInfo, err2 := os.Stat(pth)
 | 
							pthInfo, err2 := os.Stat(pth)
 | 
				
			||||||
		if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
 | 
							if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
 | 
				
			||||||
			return errors.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
 | 
								return errors.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import (
 | 
				
			||||||
func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions {
 | 
					func (daemon *Daemon) defaultTarCopyOptions(noOverwriteDirNonDir bool) *archive.TarOptions {
 | 
				
			||||||
	return &archive.TarOptions{
 | 
						return &archive.TarOptions{
 | 
				
			||||||
		NoOverwriteDirNonDir: noOverwriteDirNonDir,
 | 
							NoOverwriteDirNonDir: noOverwriteDirNonDir,
 | 
				
			||||||
		UIDMaps:              daemon.idMappings.UIDs(),
 | 
							UIDMaps:              daemon.idMapping.UIDs(),
 | 
				
			||||||
		GIDMaps:              daemon.idMappings.GIDs(),
 | 
							GIDMaps:              daemon.idMapping.GIDs(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,8 +18,10 @@ func (daemon *Daemon) tarCopyOptions(container *container.Container, noOverwrite
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						identity := idtools.Identity{UID: user.Uid, GID: user.Gid}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &archive.TarOptions{
 | 
						return &archive.TarOptions{
 | 
				
			||||||
		NoOverwriteDirNonDir: noOverwriteDirNonDir,
 | 
							NoOverwriteDirNonDir: noOverwriteDirNonDir,
 | 
				
			||||||
		ChownOpts:            &idtools.IDPair{UID: user.Uid, GID: user.Gid},
 | 
							ChownOpts:            &identity,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +132,7 @@ func (daemon *Daemon) setupIpcDirs(c *container.Container) error {
 | 
				
			||||||
		fallthrough
 | 
							fallthrough
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	case ipcMode.IsShareable():
 | 
						case ipcMode.IsShareable():
 | 
				
			||||||
		rootIDs := daemon.idMappings.RootPair()
 | 
							rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
		if !c.HasMountFor("/dev/shm") {
 | 
							if !c.HasMountFor("/dev/shm") {
 | 
				
			||||||
			shmPath, err := c.ShmResourcePath()
 | 
								shmPath, err := c.ShmResourcePath()
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
| 
						 | 
					@ -179,7 +179,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// retrieve possible remapped range start for root UID, GID
 | 
						// retrieve possible remapped range start for root UID, GID
 | 
				
			||||||
	rootIDs := daemon.idMappings.RootPair()
 | 
						rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, s := range c.SecretReferences {
 | 
						for _, s := range c.SecretReferences {
 | 
				
			||||||
		// TODO (ehazlett): use type switch when more are supported
 | 
							// TODO (ehazlett): use type switch when more are supported
 | 
				
			||||||
| 
						 | 
					@ -278,7 +278,7 @@ func (daemon *Daemon) setupSecretDir(c *container.Container) (setupErr error) {
 | 
				
			||||||
// In practice this is using a tmpfs mount and is used for both "configs" and "secrets"
 | 
					// In practice this is using a tmpfs mount and is used for both "configs" and "secrets"
 | 
				
			||||||
func (daemon *Daemon) createSecretsDir(c *container.Container) error {
 | 
					func (daemon *Daemon) createSecretsDir(c *container.Container) error {
 | 
				
			||||||
	// retrieve possible remapped range start for root UID, GID
 | 
						// retrieve possible remapped range start for root UID, GID
 | 
				
			||||||
	rootIDs := daemon.idMappings.RootPair()
 | 
						rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
	dir, err := c.SecretMountPath()
 | 
						dir, err := c.SecretMountPath()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.Wrap(err, "error getting container secrets dir")
 | 
							return errors.Wrap(err, "error getting container secrets dir")
 | 
				
			||||||
| 
						 | 
					@ -304,7 +304,7 @@ func (daemon *Daemon) remountSecretDir(c *container.Container) error {
 | 
				
			||||||
	if err := label.Relabel(dir, c.MountLabel, false); err != nil {
 | 
						if err := label.Relabel(dir, c.MountLabel, false); err != nil {
 | 
				
			||||||
		logrus.WithError(err).WithField("dir", dir).Warn("Error while attempting to set selinux label")
 | 
							logrus.WithError(err).WithField("dir", dir).Warn("Error while attempting to set selinux label")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rootIDs := daemon.idMappings.RootPair()
 | 
						rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
	tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootIDs.UID, rootIDs.GID)
 | 
						tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootIDs.UID, rootIDs.GID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// remount secrets ro
 | 
						// remount secrets ro
 | 
				
			||||||
| 
						 | 
					@ -407,5 +407,5 @@ func (daemon *Daemon) setupContainerMountsRoot(c *container.Container) error {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return idtools.MkdirAllAndChown(p, 0700, daemon.idMappings.RootPair())
 | 
						return idtools.MkdirAllAndChown(p, 0700, daemon.idMapping.RootPair())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -155,13 +155,14 @@ func (daemon *Daemon) create(params types.ContainerCreateConfig, managed bool) (
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set RWLayer for container after mount labels have been set
 | 
						// Set RWLayer for container after mount labels have been set
 | 
				
			||||||
	rwLayer, err := daemon.imageService.CreateLayer(container, setupInitLayer(daemon.idMappings))
 | 
						rwLayer, err := daemon.imageService.CreateLayer(container, setupInitLayer(daemon.idMapping))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, errdefs.System(err)
 | 
							return nil, errdefs.System(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	container.RWLayer = rwLayer
 | 
						container.RWLayer = rwLayer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rootIDs := daemon.idMappings.RootPair()
 | 
						rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAndChown(container.Root, 0700, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAndChown(container.Root, 0700, rootIDs); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Con
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer daemon.Unmount(container)
 | 
						defer daemon.Unmount(container)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rootIDs := daemon.idMappings.RootPair()
 | 
						rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
	if err := container.SetupWorkingDirectory(rootIDs); err != nil {
 | 
						if err := container.SetupWorkingDirectory(rootIDs); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -87,7 +87,7 @@ type Daemon struct {
 | 
				
			||||||
	seccompEnabled    bool
 | 
						seccompEnabled    bool
 | 
				
			||||||
	apparmorEnabled   bool
 | 
						apparmorEnabled   bool
 | 
				
			||||||
	shutdown          bool
 | 
						shutdown          bool
 | 
				
			||||||
	idMappings        *idtools.IDMappings
 | 
						idMapping         *idtools.IdentityMapping
 | 
				
			||||||
	// TODO: move graphDrivers field to an InfoService
 | 
						// TODO: move graphDrivers field to an InfoService
 | 
				
			||||||
	graphDrivers map[string]string // By operating system
 | 
						graphDrivers map[string]string // By operating system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -594,11 +594,11 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idMappings, err := setupRemappedRoot(config)
 | 
						idMapping, err := setupRemappedRoot(config)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rootIDs := idMappings.RootPair()
 | 
						rootIDs := idMapping.RootPair()
 | 
				
			||||||
	if err := setupDaemonProcess(config); err != nil {
 | 
						if err := setupDaemonProcess(config); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -749,7 +749,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
 | 
				
			||||||
			MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
 | 
								MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
 | 
				
			||||||
			GraphDriver:               gd,
 | 
								GraphDriver:               gd,
 | 
				
			||||||
			GraphDriverOptions:        config.GraphOptions,
 | 
								GraphDriverOptions:        config.GraphOptions,
 | 
				
			||||||
			IDMappings:                idMappings,
 | 
								IDMapping:                 idMapping,
 | 
				
			||||||
			PluginGetter:              d.PluginStore,
 | 
								PluginGetter:              d.PluginStore,
 | 
				
			||||||
			ExperimentalEnabled:       config.Experimental,
 | 
								ExperimentalEnabled:       config.Experimental,
 | 
				
			||||||
			OS:                        operatingSystem,
 | 
								OS:                        operatingSystem,
 | 
				
			||||||
| 
						 | 
					@ -856,7 +856,7 @@ func NewDaemon(config *config.Config, registryService registry.Service, containe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d.EventsService = events.New()
 | 
						d.EventsService = events.New()
 | 
				
			||||||
	d.root = config.Root
 | 
						d.root = config.Root
 | 
				
			||||||
	d.idMappings = idMappings
 | 
						d.idMapping = idMapping
 | 
				
			||||||
	d.seccompEnabled = sysInfo.Seccomp
 | 
						d.seccompEnabled = sysInfo.Seccomp
 | 
				
			||||||
	d.apparmorEnabled = sysInfo.AppArmor
 | 
						d.apparmorEnabled = sysInfo.AppArmor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1106,7 +1106,7 @@ func (daemon *Daemon) Subnets() ([]net.IPNet, []net.IPNet) {
 | 
				
			||||||
// prepareTempDir prepares and returns the default directory to use
 | 
					// prepareTempDir prepares and returns the default directory to use
 | 
				
			||||||
// for temporary files.
 | 
					// for temporary files.
 | 
				
			||||||
// If it doesn't exist, it is created. If it exists, its content is removed.
 | 
					// If it doesn't exist, it is created. If it exists, its content is removed.
 | 
				
			||||||
func prepareTempDir(rootDir string, rootIDs idtools.IDPair) (string, error) {
 | 
					func prepareTempDir(rootDir string, rootIdentity idtools.Identity) (string, error) {
 | 
				
			||||||
	var tmpDir string
 | 
						var tmpDir string
 | 
				
			||||||
	if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
 | 
						if tmpDir = os.Getenv("DOCKER_TMPDIR"); tmpDir == "" {
 | 
				
			||||||
		tmpDir = filepath.Join(rootDir, "tmp")
 | 
							tmpDir = filepath.Join(rootDir, "tmp")
 | 
				
			||||||
| 
						 | 
					@ -1126,7 +1126,7 @@ func prepareTempDir(rootDir string, rootIDs idtools.IDPair) (string, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// We don't remove the content of tmpdir if it's not the default,
 | 
						// We don't remove the content of tmpdir if it's not the default,
 | 
				
			||||||
	// it may hold things that do not belong to us.
 | 
						// it may hold things that do not belong to us.
 | 
				
			||||||
	return tmpDir, idtools.MkdirAllAndChown(tmpDir, 0700, rootIDs)
 | 
						return tmpDir, idtools.MkdirAllAndChown(tmpDir, 0700, rootIdentity)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (daemon *Daemon) setGenericResources(conf *config.Config) error {
 | 
					func (daemon *Daemon) setGenericResources(conf *config.Config) error {
 | 
				
			||||||
| 
						 | 
					@ -1274,11 +1274,11 @@ func CreateDaemonRoot(config *config.Config) error {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idMappings, err := setupRemappedRoot(config)
 | 
						idMapping, err := setupRemappedRoot(config)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return setupDaemonRoot(config, realRoot, idMappings.RootPair())
 | 
						return setupDaemonRoot(config, realRoot, idMapping.RootPair())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// checkpointAndSave grabs a container lock to safely call container.CheckpointTo
 | 
					// checkpointAndSave grabs a container lock to safely call container.CheckpointTo
 | 
				
			||||||
| 
						 | 
					@ -1304,9 +1304,9 @@ func (daemon *Daemon) GetAttachmentStore() *network.AttachmentStore {
 | 
				
			||||||
	return &daemon.attachmentStore
 | 
						return &daemon.attachmentStore
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IDMappings returns uid/gid mappings for the builder
 | 
					// IdentityMapping returns uid/gid mapping or a SID (in the case of Windows) for the builder
 | 
				
			||||||
func (daemon *Daemon) IDMappings() *idtools.IDMappings {
 | 
					func (daemon *Daemon) IdentityMapping() *idtools.IdentityMapping {
 | 
				
			||||||
	return daemon.idMappings
 | 
						return daemon.idMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ImageService returns the Daemon's ImageService
 | 
					// ImageService returns the Daemon's ImageService
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -124,7 +124,7 @@ func TestTmpfsDevShmSizeOverride(t *testing.T) {
 | 
				
			||||||
	mnt := "/dev/shm"
 | 
						mnt := "/dev/shm"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d := Daemon{
 | 
						d := Daemon{
 | 
				
			||||||
		idMappings: &idtools.IDMappings{},
 | 
							idMapping: &idtools.IdentityMapping{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c := &container.Container{
 | 
						c := &container.Container{
 | 
				
			||||||
		HostConfig: &containertypes.HostConfig{
 | 
							HostConfig: &containertypes.HostConfig{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -118,7 +118,7 @@ func initDaemonWithVolumeStore(tmp string) (*Daemon, error) {
 | 
				
			||||||
		repository: tmp,
 | 
							repository: tmp,
 | 
				
			||||||
		root:       tmp,
 | 
							root:       tmp,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	daemon.volumes, err = volumesservice.NewVolumeService(tmp, nil, idtools.IDPair{UID: 0, GID: 0}, daemon)
 | 
						daemon.volumes, err = volumesservice.NewVolumeService(tmp, nil, idtools.Identity{UID: 0, GID: 0}, daemon)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1003,9 +1003,9 @@ func removeDefaultBridgeInterface() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupInitLayer(idMappings *idtools.IDMappings) func(containerfs.ContainerFS) error {
 | 
					func setupInitLayer(idMapping *idtools.IdentityMapping) func(containerfs.ContainerFS) error {
 | 
				
			||||||
	return func(initPath containerfs.ContainerFS) error {
 | 
						return func(initPath containerfs.ContainerFS) error {
 | 
				
			||||||
		return initlayer.Setup(initPath, idMappings.RootPair())
 | 
							return initlayer.Setup(initPath, idMapping.RootPair())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1102,7 +1102,7 @@ func parseRemappedRoot(usergrp string) (string, string, error) {
 | 
				
			||||||
	return username, groupname, nil
 | 
						return username, groupname, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) {
 | 
					func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error) {
 | 
				
			||||||
	if runtime.GOOS != "linux" && config.RemappedRoot != "" {
 | 
						if runtime.GOOS != "linux" && config.RemappedRoot != "" {
 | 
				
			||||||
		return nil, fmt.Errorf("User namespaces are only supported on Linux")
 | 
							return nil, fmt.Errorf("User namespaces are only supported on Linux")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1118,22 +1118,22 @@ func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) {
 | 
				
			||||||
			// Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
 | 
								// Cannot setup user namespaces with a 1-to-1 mapping; "--root=0:0" is a no-op
 | 
				
			||||||
			// effectively
 | 
								// effectively
 | 
				
			||||||
			logrus.Warn("User namespaces: root cannot be remapped with itself; user namespaces are OFF")
 | 
								logrus.Warn("User namespaces: root cannot be remapped with itself; user namespaces are OFF")
 | 
				
			||||||
			return &idtools.IDMappings{}, nil
 | 
								return &idtools.IdentityMapping{}, nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		logrus.Infof("User namespaces: ID ranges will be mapped to subuid/subgid ranges of: %s:%s", username, groupname)
 | 
							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
 | 
							// update remapped root setting now that we have resolved them to actual names
 | 
				
			||||||
		config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
 | 
							config.RemappedRoot = fmt.Sprintf("%s:%s", username, groupname)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mappings, err := idtools.NewIDMappings(username, groupname)
 | 
							mappings, err := idtools.NewIdentityMapping(username, groupname)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, errors.Wrap(err, "Can't create ID mappings")
 | 
								return nil, errors.Wrap(err, "Can't create ID mappings")
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return mappings, nil
 | 
							return mappings, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &idtools.IDMappings{}, nil
 | 
						return &idtools.IdentityMapping{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error {
 | 
					func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools.Identity) error {
 | 
				
			||||||
	config.Root = rootDir
 | 
						config.Root = rootDir
 | 
				
			||||||
	// the docker root metadata directory needs to have execute permissions for all users (g+x,o+x)
 | 
						// the docker root metadata directory needs to have execute permissions for all users (g+x,o+x)
 | 
				
			||||||
	// so that syscalls executing as non-root, operating on subdirectories of the graph root
 | 
						// so that syscalls executing as non-root, operating on subdirectories of the graph root
 | 
				
			||||||
| 
						 | 
					@ -1158,10 +1158,10 @@ func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPa
 | 
				
			||||||
	// a new subdirectory with ownership set to the remapped uid/gid (so as to allow
 | 
						// 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)
 | 
						// `chdir()` to work for containers namespaced to that uid/gid)
 | 
				
			||||||
	if config.RemappedRoot != "" {
 | 
						if config.RemappedRoot != "" {
 | 
				
			||||||
		config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootIDs.UID, rootIDs.GID))
 | 
							config.Root = filepath.Join(rootDir, fmt.Sprintf("%d.%d", rootIdentity.UID, rootIdentity.GID))
 | 
				
			||||||
		logrus.Debugf("Creating user namespaced daemon root: %s", config.Root)
 | 
							logrus.Debugf("Creating user namespaced daemon root: %s", config.Root)
 | 
				
			||||||
		// Create the root directory if it doesn't exist
 | 
							// Create the root directory if it doesn't exist
 | 
				
			||||||
		if err := idtools.MkdirAllAndChown(config.Root, 0700, rootIDs); err != nil {
 | 
							if err := idtools.MkdirAllAndChown(config.Root, 0700, rootIdentity); err != nil {
 | 
				
			||||||
			return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err)
 | 
								return fmt.Errorf("Cannot create daemon root: %s: %v", config.Root, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// we also need to verify that any pre-existing directories in the path to
 | 
							// we also need to verify that any pre-existing directories in the path to
 | 
				
			||||||
| 
						 | 
					@ -1174,7 +1174,7 @@ func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPa
 | 
				
			||||||
			if dirPath == "/" {
 | 
								if dirPath == "/" {
 | 
				
			||||||
				break
 | 
									break
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			if !idtools.CanAccess(dirPath, rootIDs) {
 | 
								if !idtools.CanAccess(dirPath, rootIdentity) {
 | 
				
			||||||
				return fmt.Errorf("a subdirectory in your graphroot path (%s) restricts access to the remapped root uid/gid; please fix by allowing 'o+x' permissions on existing directories", config.Root)
 | 
									return fmt.Errorf("a subdirectory in your graphroot path (%s) restricts access to the remapped root uid/gid; please fix by allowing 'o+x' permissions on existing directories", config.Root)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ func parseSecurityOpt(container *container.Container, config *containertypes.Hos
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupInitLayer(idMappings *idtools.IDMappings) func(containerfs.ContainerFS) error {
 | 
					func setupInitLayer(idMapping *idtools.IdentityMapping) func(containerfs.ContainerFS) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -465,11 +465,11 @@ func (daemon *Daemon) cleanupMounts() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupRemappedRoot(config *config.Config) (*idtools.IDMappings, error) {
 | 
					func setupRemappedRoot(config *config.Config) (*idtools.IdentityMapping, error) {
 | 
				
			||||||
	return &idtools.IDMappings{}, nil
 | 
						return &idtools.IdentityMapping{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupDaemonRoot(config *config.Config, rootDir string, rootIDs idtools.IDPair) error {
 | 
					func setupDaemonRoot(config *config.Config, rootDir string, rootIdentity idtools.Identity) error {
 | 
				
			||||||
	config.Root = rootDir
 | 
						config.Root = rootDir
 | 
				
			||||||
	// Create the root directory if it doesn't exists
 | 
						// Create the root directory if it doesn't exists
 | 
				
			||||||
	if err := system.MkdirAllWithACL(config.Root, 0, system.SddlAdministratorsLocalSystem); err != nil {
 | 
						if err := system.MkdirAllWithACL(config.Root, 0, system.SddlAdministratorsLocalSystem); err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,8 +68,8 @@ func (daemon *Daemon) containerExport(container *container.Container) (arch io.R
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	archive, err := archivePath(basefs, basefs.Path(), &archive.TarOptions{
 | 
						archive, err := archivePath(basefs, basefs.Path(), &archive.TarOptions{
 | 
				
			||||||
		Compression: archive.Uncompressed,
 | 
							Compression: archive.Uncompressed,
 | 
				
			||||||
		UIDMaps:     daemon.idMappings.UIDs(),
 | 
							UIDMaps:     daemon.idMapping.UIDs(),
 | 
				
			||||||
		GIDMaps:     daemon.idMappings.GIDs(),
 | 
							GIDMaps:     daemon.idMapping.GIDs(),
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		rwlayer.Unmount()
 | 
							rwlayer.Unmount()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,13 +135,13 @@ func Init(root string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Create the root aufs driver dir
 | 
						// Create the root aufs driver dir
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(root, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(root, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Populate the dir structure
 | 
						// Populate the dir structure
 | 
				
			||||||
	for _, p := range paths {
 | 
						for _, p := range paths {
 | 
				
			||||||
		if err := idtools.MkdirAllAndChown(path.Join(root, p), 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
							if err := idtools.MkdirAllAndChown(path.Join(root, p), 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -289,7 +289,7 @@ func (a *Driver) createDirsFor(id string) error {
 | 
				
			||||||
	// The path of directories are <aufs_root_path>/mnt/<image_id>
 | 
						// The path of directories are <aufs_root_path>/mnt/<image_id>
 | 
				
			||||||
	// and <aufs_root_path>/diff/<image_id>
 | 
						// and <aufs_root_path>/diff/<image_id>
 | 
				
			||||||
	for _, p := range paths {
 | 
						for _, p := range paths {
 | 
				
			||||||
		if err := idtools.MkdirAllAndChown(path.Join(a.rootPath(), p, id), 0755, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
							if err := idtools.MkdirAllAndChown(path.Join(a.rootPath(), p, id), 0755, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -72,7 +72,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(home, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(home, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -502,7 +502,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(subvolumes, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(subvolumes, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if parent == "" {
 | 
						if parent == "" {
 | 
				
			||||||
| 
						 | 
					@ -537,7 +537,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
 | 
				
			||||||
		if err := d.setStorageSize(path.Join(subvolumes, id), driver); err != nil {
 | 
							if err := d.setStorageSize(path.Join(subvolumes, id), driver); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := idtools.MkdirAllAndChown(quotas, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
							if err := idtools.MkdirAllAndChown(quotas, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := ioutil.WriteFile(path.Join(quotas, id), []byte(fmt.Sprint(driver.options.size)), 0644); err != nil {
 | 
							if err := ioutil.WriteFile(path.Join(quotas, id), []byte(fmt.Sprint(driver.options.size)), 0644); err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -268,7 +268,7 @@ func (devices *DeviceSet) ensureImage(name string, size int64) (string, error) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(dirname, 0700, idtools.IDPair{UID: uid, GID: gid}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(dirname, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1691,7 +1691,7 @@ func (devices *DeviceSet) initDevmapper(doInit bool) (retErr error) {
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAndChown(devices.root, 0700, idtools.IDPair{UID: uid, GID: gid}); err != nil {
 | 
						if err := idtools.MkdirAndChown(devices.root, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil {
 | 
						if err := os.MkdirAll(devices.metadataDir(), 0700); err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,11 +200,11 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create the target directories if they don't exist
 | 
						// Create the target directories if they don't exist
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(path.Join(d.home, "mnt"), 0755, idtools.IDPair{UID: uid, GID: gid}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(path.Join(d.home, "mnt"), 0755, idtools.Identity{UID: uid, GID: gid}); err != nil {
 | 
				
			||||||
		d.ctr.Decrement(mp)
 | 
							d.ctr.Decrement(mp)
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAndChown(mp, 0755, idtools.IDPair{UID: uid, GID: gid}); err != nil && !os.IsExist(err) {
 | 
						if err := idtools.MkdirAndChown(mp, 0755, idtools.Identity{UID: uid, GID: gid}); err != nil && !os.IsExist(err) {
 | 
				
			||||||
		d.ctr.Decrement(mp)
 | 
							d.ctr.Decrement(mp)
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -215,7 +215,7 @@ func (d *Driver) Get(id, mountLabel string) (containerfs.ContainerFS, error) {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(rootFs, 0755, idtools.IDPair{UID: uid, GID: gid}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(rootFs, 0755, idtools.Identity{UID: uid, GID: gid}); err != nil {
 | 
				
			||||||
		d.ctr.Decrement(mp)
 | 
							d.ctr.Decrement(mp)
 | 
				
			||||||
		d.DeviceSet.UnmountDevice(id, mp)
 | 
							d.DeviceSet.UnmountDevice(id, mp)
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -183,17 +183,17 @@ func InitDriver(dataRoot string, options []string, _, _ []idtools.IDMap) (graphd
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure the dataRoot directory is created
 | 
						// Make sure the dataRoot directory is created
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(dataRoot, 0700, idtools.IDPair{UID: 0, GID: 0}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(dataRoot, 0700, idtools.Identity{UID: 0, GID: 0}); err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("%s failed to create '%s': %v", title, dataRoot, err)
 | 
							return nil, fmt.Errorf("%s failed to create '%s': %v", title, dataRoot, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure the cache directory is created under dataRoot
 | 
						// Make sure the cache directory is created under dataRoot
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(cd, 0700, idtools.IDPair{UID: 0, GID: 0}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(cd, 0700, idtools.Identity{UID: 0, GID: 0}); err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("%s failed to create '%s': %v", title, cd, err)
 | 
							return nil, fmt.Errorf("%s failed to create '%s': %v", title, cd, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Make sure the scratch directory is created under dataRoot
 | 
						// Make sure the scratch directory is created under dataRoot
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(sd, 0700, idtools.IDPair{UID: 0, GID: 0}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(sd, 0700, idtools.Identity{UID: 0, GID: 0}); err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("%s failed to create '%s': %v", title, sd, err)
 | 
							return nil, fmt.Errorf("%s failed to create '%s': %v", title, sd, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -168,7 +168,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Create the driver home dir
 | 
						// Create the driver home dir
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(home, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(home, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -291,7 +291,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) (retErr
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	root := idtools.IDPair{UID: rootUID, GID: rootGID}
 | 
						root := idtools.Identity{UID: rootUID, GID: rootGID}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -413,7 +413,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, err erro
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -200,7 +200,7 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Create the driver home dir
 | 
						// Create the driver home dir
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(path.Join(home, linkDir), 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -378,7 +378,7 @@ func (d *Driver) create(id, parent string, opts *graphdriver.CreateOpts) (retErr
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	root := idtools.IDPair{UID: rootUID, GID: rootGID}
 | 
						root := idtools.Identity{UID: rootUID, GID: rootGID}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(path.Dir(dir), 0700, root); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
| 
						 | 
					@ -586,7 +586,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAndChown(mergedDir, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,10 +27,10 @@ func init() {
 | 
				
			||||||
// This sets the home directory for the driver and returns NaiveDiffDriver.
 | 
					// This sets the home directory for the driver and returns NaiveDiffDriver.
 | 
				
			||||||
func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
 | 
					func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (graphdriver.Driver, error) {
 | 
				
			||||||
	d := &Driver{
 | 
						d := &Driver{
 | 
				
			||||||
		home:       home,
 | 
							home:      home,
 | 
				
			||||||
		idMappings: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps),
 | 
							idMapping: idtools.NewIDMappingsFromMaps(uidMaps, gidMaps),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	rootIDs := d.idMappings.RootPair()
 | 
						rootIDs := d.idMapping.RootPair()
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(home, 0700, rootIDs); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -46,8 +46,8 @@ func Init(home string, options []string, uidMaps, gidMaps []idtools.IDMap) (grap
 | 
				
			||||||
// Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver
 | 
					// Driver must be wrapped in NaiveDiffDriver to be used as a graphdriver.Driver
 | 
				
			||||||
type Driver struct {
 | 
					type Driver struct {
 | 
				
			||||||
	driverQuota
 | 
						driverQuota
 | 
				
			||||||
	home       string
 | 
						home      string
 | 
				
			||||||
	idMappings *idtools.IDMappings
 | 
						idMapping *idtools.IdentityMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *Driver) String() string {
 | 
					func (d *Driver) String() string {
 | 
				
			||||||
| 
						 | 
					@ -105,7 +105,7 @@ func (d *Driver) Create(id, parent string, opts *graphdriver.CreateOpts) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (d *Driver) create(id, parent string, size uint64) error {
 | 
					func (d *Driver) create(id, parent string, size uint64) error {
 | 
				
			||||||
	dir := d.dir(id)
 | 
						dir := d.dir(id)
 | 
				
			||||||
	rootIDs := d.idMappings.RootPair()
 | 
						rootIDs := d.idMapping.RootPair()
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0700, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(filepath.Dir(dir), 0700, rootIDs); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,7 @@ func InitFilter(home string, options []string, uidMaps, gidMaps []idtools.IDMap)
 | 
				
			||||||
		return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home)
 | 
							return nil, fmt.Errorf("%s is on an ReFS volume - ReFS volumes are not supported", home)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(home, 0700, idtools.IDPair{UID: 0, GID: 0}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(home, 0700, idtools.Identity{UID: 0, GID: 0}); err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("windowsfilter failed to create '%s': %v", home, err)
 | 
							return nil, fmt.Errorf("windowsfilter failed to create '%s': %v", home, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,7 @@ func Init(base string, opt []string, uidMaps, gidMaps []idtools.IDMap) (graphdri
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Failed to get root uid/guid: %v", err)
 | 
							return nil, fmt.Errorf("Failed to get root uid/guid: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(base, 0700, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(base, 0700, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, fmt.Errorf("Failed to create '%s': %v", base, err)
 | 
							return nil, fmt.Errorf("Failed to create '%s': %v", base, err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -385,7 +385,7 @@ func (d *Driver) Get(id, mountLabel string) (_ containerfs.ContainerFS, retErr e
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// Create the target directories if they don't exist
 | 
						// Create the target directories if they don't exist
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(mountpoint, 0755, idtools.IDPair{UID: rootUID, GID: rootGID}); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(mountpoint, 0755, idtools.Identity{UID: rootUID, GID: rootGID}); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -162,7 +162,7 @@ func (daemon *Daemon) fillSecurityOptions(v *types.Info, sysInfo *sysinfo.SysInf
 | 
				
			||||||
	if selinuxEnabled() {
 | 
						if selinuxEnabled() {
 | 
				
			||||||
		securityOptions = append(securityOptions, "name=selinux")
 | 
							securityOptions = append(securityOptions, "name=selinux")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if rootIDs := daemon.idMappings.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
 | 
						if rootIDs := daemon.idMapping.RootPair(); rootIDs.UID != 0 || rootIDs.GID != 0 {
 | 
				
			||||||
		securityOptions = append(securityOptions, "name=userns")
 | 
							securityOptions = append(securityOptions, "name=userns")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	v.SecurityOptions = securityOptions
 | 
						v.SecurityOptions = securityOptions
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,7 @@ import (
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// This extra layer is used by all containers as the top-most ro layer. It protects
 | 
					// This extra layer is used by all containers as the top-most ro layer. It protects
 | 
				
			||||||
// the container from unwanted side-effects on the rw layer.
 | 
					// the container from unwanted side-effects on the rw layer.
 | 
				
			||||||
func Setup(initLayerFs containerfs.ContainerFS, rootIDs idtools.IDPair) error {
 | 
					func Setup(initLayerFs containerfs.ContainerFS, rootIdentity idtools.Identity) error {
 | 
				
			||||||
	// Since all paths are local to the container, we can just extract initLayerFs.Path()
 | 
						// Since all paths are local to the container, we can just extract initLayerFs.Path()
 | 
				
			||||||
	initLayer := initLayerFs.Path()
 | 
						initLayer := initLayerFs.Path()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -42,12 +42,12 @@ func Setup(initLayerFs containerfs.ContainerFS, rootIDs idtools.IDPair) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
 | 
							if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
 | 
				
			||||||
			if os.IsNotExist(err) {
 | 
								if os.IsNotExist(err) {
 | 
				
			||||||
				if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootIDs); err != nil {
 | 
									if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, filepath.Dir(pth)), 0755, rootIdentity); err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				switch typ {
 | 
									switch typ {
 | 
				
			||||||
				case "dir":
 | 
									case "dir":
 | 
				
			||||||
					if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, pth), 0755, rootIDs); err != nil {
 | 
										if err := idtools.MkdirAllAndChownNew(filepath.Join(initLayer, pth), 0755, rootIdentity); err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				case "file":
 | 
									case "file":
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ func Setup(initLayerFs containerfs.ContainerFS, rootIDs idtools.IDPair) error {
 | 
				
			||||||
					if err != nil {
 | 
										if err != nil {
 | 
				
			||||||
						return err
 | 
											return err
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					f.Chown(rootIDs.UID, rootIDs.GID)
 | 
										f.Chown(rootIdentity.UID, rootIdentity.GID)
 | 
				
			||||||
					f.Close()
 | 
										f.Close()
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
					if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
 | 
										if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,6 @@ import (
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// This extra layer is used by all containers as the top-most ro layer. It protects
 | 
					// This extra layer is used by all containers as the top-most ro layer. It protects
 | 
				
			||||||
// the container from unwanted side-effects on the rw layer.
 | 
					// the container from unwanted side-effects on the rw layer.
 | 
				
			||||||
func Setup(initLayer containerfs.ContainerFS, rootIDs idtools.IDPair) error {
 | 
					func Setup(initLayer containerfs.ContainerFS, rootIDs idtools.Identity) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -217,13 +217,13 @@ func setNamespaces(daemon *Daemon, s *specs.Spec, c *container.Container) error
 | 
				
			||||||
	userNS := false
 | 
						userNS := false
 | 
				
			||||||
	// user
 | 
						// user
 | 
				
			||||||
	if c.HostConfig.UsernsMode.IsPrivate() {
 | 
						if c.HostConfig.UsernsMode.IsPrivate() {
 | 
				
			||||||
		uidMap := daemon.idMappings.UIDs()
 | 
							uidMap := daemon.idMapping.UIDs()
 | 
				
			||||||
		if uidMap != nil {
 | 
							if uidMap != nil {
 | 
				
			||||||
			userNS = true
 | 
								userNS = true
 | 
				
			||||||
			ns := specs.LinuxNamespace{Type: "user"}
 | 
								ns := specs.LinuxNamespace{Type: "user"}
 | 
				
			||||||
			setNamespace(s, ns)
 | 
								setNamespace(s, ns)
 | 
				
			||||||
			s.Linux.UIDMappings = specMapping(uidMap)
 | 
								s.Linux.UIDMappings = specMapping(uidMap)
 | 
				
			||||||
			s.Linux.GIDMappings = specMapping(daemon.idMappings.GIDs())
 | 
								s.Linux.GIDMappings = specMapping(daemon.idMapping.GIDs())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// network
 | 
						// network
 | 
				
			||||||
| 
						 | 
					@ -619,7 +619,7 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO: until a kernel/mount solution exists for handling remount in a user namespace,
 | 
						// TODO: until a kernel/mount solution exists for handling remount in a user namespace,
 | 
				
			||||||
	// we must clear the readonly flag for the cgroups mount (@mrunalp concurs)
 | 
						// we must clear the readonly flag for the cgroups mount (@mrunalp concurs)
 | 
				
			||||||
	if uidMap := daemon.idMappings.UIDs(); uidMap != nil || c.HostConfig.Privileged {
 | 
						if uidMap := daemon.idMapping.UIDs(); uidMap != nil || c.HostConfig.Privileged {
 | 
				
			||||||
		for i, m := range s.Mounts {
 | 
							for i, m := range s.Mounts {
 | 
				
			||||||
			if m.Type == "cgroup" {
 | 
								if m.Type == "cgroup" {
 | 
				
			||||||
				clearReadOnly(&s.Mounts[i])
 | 
									clearReadOnly(&s.Mounts[i])
 | 
				
			||||||
| 
						 | 
					@ -642,7 +642,7 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
 | 
				
			||||||
		Path:     c.BaseFS.Path(),
 | 
							Path:     c.BaseFS.Path(),
 | 
				
			||||||
		Readonly: c.HostConfig.ReadonlyRootfs,
 | 
							Readonly: c.HostConfig.ReadonlyRootfs,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := c.SetupWorkingDirectory(daemon.idMappings.RootPair()); err != nil {
 | 
						if err := c.SetupWorkingDirectory(daemon.idMapping.RootPair()); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	cwd := c.Config.WorkingDir
 | 
						cwd := c.Config.WorkingDir
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ func TestTmpfsDevShmNoDupMount(t *testing.T) {
 | 
				
			||||||
	d := Daemon{
 | 
						d := Daemon{
 | 
				
			||||||
		// some empty structs to avoid getting a panic
 | 
							// some empty structs to avoid getting a panic
 | 
				
			||||||
		// caused by a null pointer dereference
 | 
							// caused by a null pointer dereference
 | 
				
			||||||
		idMappings:  &idtools.IDMappings{},
 | 
							idMapping:   &idtools.IdentityMapping{},
 | 
				
			||||||
		configStore: &config.Config{},
 | 
							configStore: &config.Config{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c := &container.Container{
 | 
						c := &container.Container{
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ func TestIpcPrivateVsReadonly(t *testing.T) {
 | 
				
			||||||
	d := Daemon{
 | 
						d := Daemon{
 | 
				
			||||||
		// some empty structs to avoid getting a panic
 | 
							// some empty structs to avoid getting a panic
 | 
				
			||||||
		// caused by a null pointer dereference
 | 
							// caused by a null pointer dereference
 | 
				
			||||||
		idMappings:  &idtools.IDMappings{},
 | 
							idMapping:   &idtools.IdentityMapping{},
 | 
				
			||||||
		configStore: &config.Config{},
 | 
							configStore: &config.Config{},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	c := &container.Container{
 | 
						c := &container.Container{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,7 +47,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		path, err := m.Setup(c.MountLabel, daemon.idMappings.RootPair(), checkfunc)
 | 
							path, err := m.Setup(c.MountLabel, daemon.idMapping.RootPair(), checkfunc)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -77,7 +77,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
 | 
				
			||||||
	// if we are going to mount any of the network files from container
 | 
						// if we are going to mount any of the network files from container
 | 
				
			||||||
	// metadata, the ownership must be set properly for potential container
 | 
						// metadata, the ownership must be set properly for potential container
 | 
				
			||||||
	// remapped root (user namespaces)
 | 
						// remapped root (user namespaces)
 | 
				
			||||||
	rootIDs := daemon.idMappings.RootPair()
 | 
						rootIDs := daemon.idMapping.RootPair()
 | 
				
			||||||
	for _, mount := range netMounts {
 | 
						for _, mount := range netMounts {
 | 
				
			||||||
		// we should only modify ownership of network files within our own container
 | 
							// we should only modify ownership of network files within our own container
 | 
				
			||||||
		// metadata repository. If the user specifies a mount path external, it is
 | 
							// metadata repository. If the user specifies a mount path external, it is
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ func (daemon *Daemon) setupMounts(c *container.Container) ([]container.Mount, er
 | 
				
			||||||
		if err := daemon.lazyInitializeVolume(c.ID, mount); err != nil {
 | 
							if err := daemon.lazyInitializeVolume(c.ID, mount); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		s, err := mount.Setup(c.MountLabel, idtools.IDPair{UID: 0, GID: 0}, nil)
 | 
							s, err := mount.Setup(c.MountLabel, idtools.Identity{}, nil)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,5 +16,5 @@ func (daemon *Daemon) ContainerCreateWorkdir(cID string) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer daemon.Unmount(container)
 | 
						defer daemon.Unmount(container)
 | 
				
			||||||
	return container.SetupWorkingDirectory(daemon.idMappings.RootPair())
 | 
						return container.SetupWorkingDirectory(daemon.idMapping.RootPair())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										20
									
								
								hack/make/containerutility
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								hack/make/containerutility
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,20 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CONTAINER_UTILITY_COMMIT=e004a1415a433447369e315b9d7df357102be0d2 # v0.9.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(
 | 
				
			||||||
 | 
						git clone https://github.com/docker/windows-container-utility.git "$GOPATH/src/github.com/docker/windows-container-utility"
 | 
				
			||||||
 | 
						cd "$GOPATH/src/github.com/docker/windows-container-utility"
 | 
				
			||||||
 | 
						git checkout -q "$CONTAINER_UTILITY_COMMIT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						echo Building: ${DEST}/containerutility.exe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						(
 | 
				
			||||||
 | 
							make
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mkdir -p ${ABS_DEST}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cp containerutility.exe ${ABS_DEST}/containerutility.exe
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -25,5 +25,7 @@ for platform in $DOCKER_CROSSPLATFORMS; do
 | 
				
			||||||
		mkdir -p "$DEST"
 | 
							mkdir -p "$DEST"
 | 
				
			||||||
		ABS_DEST="$(cd "$DEST" && pwd -P)"
 | 
							ABS_DEST="$(cd "$DEST" && pwd -P)"
 | 
				
			||||||
		source "${MAKEDIR}/binary-daemon"
 | 
							source "${MAKEDIR}/binary-daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							source "${MAKEDIR}/cross-platform-dependent"
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
done
 | 
					done
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										6
									
								
								hack/make/cross-platform-dependent
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								hack/make/cross-platform-dependent
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,6 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ $platform == "windows/amd64" ]; then
 | 
				
			||||||
 | 
						source "${MAKEDIR}/containerutility"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
| 
						 | 
					@ -45,7 +45,7 @@ type StoreOptions struct {
 | 
				
			||||||
	MetadataStorePathTemplate string
 | 
						MetadataStorePathTemplate string
 | 
				
			||||||
	GraphDriver               string
 | 
						GraphDriver               string
 | 
				
			||||||
	GraphDriverOptions        []string
 | 
						GraphDriverOptions        []string
 | 
				
			||||||
	IDMappings                *idtools.IDMappings
 | 
						IDMapping                 *idtools.IdentityMapping
 | 
				
			||||||
	PluginGetter              plugingetter.PluginGetter
 | 
						PluginGetter              plugingetter.PluginGetter
 | 
				
			||||||
	ExperimentalEnabled       bool
 | 
						ExperimentalEnabled       bool
 | 
				
			||||||
	OS                        string
 | 
						OS                        string
 | 
				
			||||||
| 
						 | 
					@ -56,8 +56,8 @@ func NewStoreFromOptions(options StoreOptions) (Store, error) {
 | 
				
			||||||
	driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{
 | 
						driver, err := graphdriver.New(options.GraphDriver, options.PluginGetter, graphdriver.Options{
 | 
				
			||||||
		Root:                options.Root,
 | 
							Root:                options.Root,
 | 
				
			||||||
		DriverOptions:       options.GraphDriverOptions,
 | 
							DriverOptions:       options.GraphDriverOptions,
 | 
				
			||||||
		UIDMaps:             options.IDMappings.UIDs(),
 | 
							UIDMaps:             options.IDMapping.UIDs(),
 | 
				
			||||||
		GIDMaps:             options.IDMappings.GIDs(),
 | 
							GIDMaps:             options.IDMapping.GIDs(),
 | 
				
			||||||
		ExperimentalEnabled: options.ExperimentalEnabled,
 | 
							ExperimentalEnabled: options.ExperimentalEnabled,
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,7 @@ func getSpecUser(ociSpec *specs.Spec) (int, int) {
 | 
				
			||||||
func prepareBundleDir(bundleDir string, ociSpec *specs.Spec) (string, error) {
 | 
					func prepareBundleDir(bundleDir string, ociSpec *specs.Spec) (string, error) {
 | 
				
			||||||
	uid, gid := getSpecUser(ociSpec)
 | 
						uid, gid := getSpecUser(ociSpec)
 | 
				
			||||||
	if uid == 0 && gid == 0 {
 | 
						if uid == 0 && gid == 0 {
 | 
				
			||||||
		return bundleDir, idtools.MkdirAllAndChownNew(bundleDir, 0755, idtools.IDPair{UID: 0, GID: 0})
 | 
							return bundleDir, idtools.MkdirAllAndChownNew(bundleDir, 0755, idtools.Identity{UID: 0, GID: 0})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	p := string(filepath.Separator)
 | 
						p := string(filepath.Separator)
 | 
				
			||||||
| 
						 | 
					@ -71,7 +71,7 @@ func prepareBundleDir(bundleDir string, ociSpec *specs.Spec) (string, error) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if os.IsNotExist(err) || fi.Mode()&1 == 0 {
 | 
							if os.IsNotExist(err) || fi.Mode()&1 == 0 {
 | 
				
			||||||
			p = fmt.Sprintf("%s.%d.%d", p, uid, gid)
 | 
								p = fmt.Sprintf("%s.%d.%d", p, uid, gid)
 | 
				
			||||||
			if err := idtools.MkdirAndChown(p, 0700, idtools.IDPair{UID: uid, GID: gid}); err != nil && !os.IsExist(err) {
 | 
								if err := idtools.MkdirAndChown(p, 0700, idtools.Identity{UID: uid, GID: gid}); err != nil && !os.IsExist(err) {
 | 
				
			||||||
				return "", err
 | 
									return "", err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,7 @@ type (
 | 
				
			||||||
		NoLchown         bool
 | 
							NoLchown         bool
 | 
				
			||||||
		UIDMaps          []idtools.IDMap
 | 
							UIDMaps          []idtools.IDMap
 | 
				
			||||||
		GIDMaps          []idtools.IDMap
 | 
							GIDMaps          []idtools.IDMap
 | 
				
			||||||
		ChownOpts        *idtools.IDPair
 | 
							ChownOpts        *idtools.Identity
 | 
				
			||||||
		IncludeSourceDir bool
 | 
							IncludeSourceDir bool
 | 
				
			||||||
		// WhiteoutFormat is the expected on disk format for whiteout files.
 | 
							// WhiteoutFormat is the expected on disk format for whiteout files.
 | 
				
			||||||
		// This format will be converted to the standard format on pack
 | 
							// This format will be converted to the standard format on pack
 | 
				
			||||||
| 
						 | 
					@ -72,13 +72,13 @@ type (
 | 
				
			||||||
// this package with a pluggable Untar function. Also, to facilitate the passing of specific id
 | 
					// this package with a pluggable Untar function. Also, to facilitate the passing of specific id
 | 
				
			||||||
// mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations.
 | 
					// mappings for untar, an Archiver can be created with maps which will then be passed to Untar operations.
 | 
				
			||||||
type Archiver struct {
 | 
					type Archiver struct {
 | 
				
			||||||
	Untar         func(io.Reader, string, *TarOptions) error
 | 
						Untar     func(io.Reader, string, *TarOptions) error
 | 
				
			||||||
	IDMappingsVar *idtools.IDMappings
 | 
						IDMapping *idtools.IdentityMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewDefaultArchiver returns a new Archiver without any IDMappings
 | 
					// NewDefaultArchiver returns a new Archiver without any IdentityMapping
 | 
				
			||||||
func NewDefaultArchiver() *Archiver {
 | 
					func NewDefaultArchiver() *Archiver {
 | 
				
			||||||
	return &Archiver{Untar: Untar, IDMappingsVar: &idtools.IDMappings{}}
 | 
						return &Archiver{Untar: Untar, IDMapping: &idtools.IdentityMapping{}}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// breakoutError is used to differentiate errors related to breaking out
 | 
					// breakoutError is used to differentiate errors related to breaking out
 | 
				
			||||||
| 
						 | 
					@ -420,9 +420,9 @@ type tarAppender struct {
 | 
				
			||||||
	Buffer    *bufio.Writer
 | 
						Buffer    *bufio.Writer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// for hardlink mapping
 | 
						// for hardlink mapping
 | 
				
			||||||
	SeenFiles  map[uint64]string
 | 
						SeenFiles       map[uint64]string
 | 
				
			||||||
	IDMappings *idtools.IDMappings
 | 
						IdentityMapping *idtools.IdentityMapping
 | 
				
			||||||
	ChownOpts  *idtools.IDPair
 | 
						ChownOpts       *idtools.Identity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// For packing and unpacking whiteout files in the
 | 
						// For packing and unpacking whiteout files in the
 | 
				
			||||||
	// non standard format. The whiteout files defined
 | 
						// non standard format. The whiteout files defined
 | 
				
			||||||
| 
						 | 
					@ -431,13 +431,13 @@ type tarAppender struct {
 | 
				
			||||||
	WhiteoutConverter tarWhiteoutConverter
 | 
						WhiteoutConverter tarWhiteoutConverter
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newTarAppender(idMapping *idtools.IDMappings, writer io.Writer, chownOpts *idtools.IDPair) *tarAppender {
 | 
					func newTarAppender(idMapping *idtools.IdentityMapping, writer io.Writer, chownOpts *idtools.Identity) *tarAppender {
 | 
				
			||||||
	return &tarAppender{
 | 
						return &tarAppender{
 | 
				
			||||||
		SeenFiles:  make(map[uint64]string),
 | 
							SeenFiles:       make(map[uint64]string),
 | 
				
			||||||
		TarWriter:  tar.NewWriter(writer),
 | 
							TarWriter:       tar.NewWriter(writer),
 | 
				
			||||||
		Buffer:     pools.BufioWriter32KPool.Get(nil),
 | 
							Buffer:          pools.BufioWriter32KPool.Get(nil),
 | 
				
			||||||
		IDMappings: idMapping,
 | 
							IdentityMapping: idMapping,
 | 
				
			||||||
		ChownOpts:  chownOpts,
 | 
							ChownOpts:       chownOpts,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -502,14 +502,12 @@ func (ta *tarAppender) addTarFile(path, name string) error {
 | 
				
			||||||
	//handle re-mapping container ID mappings back to host ID mappings before
 | 
						//handle re-mapping container ID mappings back to host ID mappings before
 | 
				
			||||||
	//writing tar headers/files. We skip whiteout files because they were written
 | 
						//writing tar headers/files. We skip whiteout files because they were written
 | 
				
			||||||
	//by the kernel and already have proper ownership relative to the host
 | 
						//by the kernel and already have proper ownership relative to the host
 | 
				
			||||||
	if !isOverlayWhiteout &&
 | 
						if !isOverlayWhiteout && !strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) && !ta.IdentityMapping.Empty() {
 | 
				
			||||||
		!strings.HasPrefix(filepath.Base(hdr.Name), WhiteoutPrefix) &&
 | 
					 | 
				
			||||||
		!ta.IDMappings.Empty() {
 | 
					 | 
				
			||||||
		fileIDPair, err := getFileUIDGID(fi.Sys())
 | 
							fileIDPair, err := getFileUIDGID(fi.Sys())
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		hdr.Uid, hdr.Gid, err = ta.IDMappings.ToContainer(fileIDPair)
 | 
							hdr.Uid, hdr.Gid, err = ta.IdentityMapping.ToContainer(fileIDPair)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -572,7 +570,7 @@ func (ta *tarAppender) addTarFile(path, name string) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.IDPair, inUserns bool) error {
 | 
					func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, Lchown bool, chownOpts *idtools.Identity, inUserns bool) error {
 | 
				
			||||||
	// hdr.Mode is in linux format, which we can use for sycalls,
 | 
						// hdr.Mode is in linux format, which we can use for sycalls,
 | 
				
			||||||
	// but for os.Foo() calls we need the mode converted to os.FileMode,
 | 
						// but for os.Foo() calls we need the mode converted to os.FileMode,
 | 
				
			||||||
	// so use hdrInfo.Mode() (they differ for e.g. setuid bits)
 | 
						// so use hdrInfo.Mode() (they differ for e.g. setuid bits)
 | 
				
			||||||
| 
						 | 
					@ -652,7 +650,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
 | 
				
			||||||
	// Lchown is not supported on Windows.
 | 
						// Lchown is not supported on Windows.
 | 
				
			||||||
	if Lchown && runtime.GOOS != "windows" {
 | 
						if Lchown && runtime.GOOS != "windows" {
 | 
				
			||||||
		if chownOpts == nil {
 | 
							if chownOpts == nil {
 | 
				
			||||||
			chownOpts = &idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid}
 | 
								chownOpts = &idtools.Identity{UID: hdr.Uid, GID: hdr.Gid}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil {
 | 
							if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
| 
						 | 
					@ -901,8 +899,8 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
 | 
				
			||||||
	defer pools.BufioReader32KPool.Put(trBuf)
 | 
						defer pools.BufioReader32KPool.Put(trBuf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var dirs []*tar.Header
 | 
						var dirs []*tar.Header
 | 
				
			||||||
	idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
 | 
						idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
 | 
				
			||||||
	rootIDs := idMappings.RootPair()
 | 
						rootIDs := idMapping.RootPair()
 | 
				
			||||||
	whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat)
 | 
						whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Iterate through the files in the archive.
 | 
						// Iterate through the files in the archive.
 | 
				
			||||||
| 
						 | 
					@ -981,7 +979,7 @@ loop:
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		trBuf.Reset(tr)
 | 
							trBuf.Reset(tr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := remapIDs(idMappings, hdr); err != nil {
 | 
							if err := remapIDs(idMapping, hdr); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1068,8 +1066,8 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer archive.Close()
 | 
						defer archive.Close()
 | 
				
			||||||
	options := &TarOptions{
 | 
						options := &TarOptions{
 | 
				
			||||||
		UIDMaps: archiver.IDMappingsVar.UIDs(),
 | 
							UIDMaps: archiver.IDMapping.UIDs(),
 | 
				
			||||||
		GIDMaps: archiver.IDMappingsVar.GIDs(),
 | 
							GIDMaps: archiver.IDMapping.GIDs(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return archiver.Untar(archive, dst, options)
 | 
						return archiver.Untar(archive, dst, options)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1082,8 +1080,8 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer archive.Close()
 | 
						defer archive.Close()
 | 
				
			||||||
	options := &TarOptions{
 | 
						options := &TarOptions{
 | 
				
			||||||
		UIDMaps: archiver.IDMappingsVar.UIDs(),
 | 
							UIDMaps: archiver.IDMapping.UIDs(),
 | 
				
			||||||
		GIDMaps: archiver.IDMappingsVar.GIDs(),
 | 
							GIDMaps: archiver.IDMapping.GIDs(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return archiver.Untar(archive, dst, options)
 | 
						return archiver.Untar(archive, dst, options)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1104,7 +1102,7 @@ func (archiver *Archiver) CopyWithTar(src, dst string) error {
 | 
				
			||||||
	// if this Archiver is set up with ID mapping we need to create
 | 
						// if this Archiver is set up with ID mapping we need to create
 | 
				
			||||||
	// the new destination directory with the remapped root UID/GID pair
 | 
						// the new destination directory with the remapped root UID/GID pair
 | 
				
			||||||
	// as owner
 | 
						// as owner
 | 
				
			||||||
	rootIDs := archiver.IDMappingsVar.RootPair()
 | 
						rootIDs := archiver.IDMapping.RootPair()
 | 
				
			||||||
	// Create dst, copy src's content into it
 | 
						// Create dst, copy src's content into it
 | 
				
			||||||
	logrus.Debugf("Creating dest directory: %s", dst)
 | 
						logrus.Debugf("Creating dest directory: %s", dst)
 | 
				
			||||||
	if err := idtools.MkdirAllAndChownNew(dst, 0755, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChownNew(dst, 0755, rootIDs); err != nil {
 | 
				
			||||||
| 
						 | 
					@ -1164,7 +1162,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
 | 
				
			||||||
			hdr.Name = filepath.Base(dst)
 | 
								hdr.Name = filepath.Base(dst)
 | 
				
			||||||
			hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
 | 
								hdr.Mode = int64(chmodTarEntry(os.FileMode(hdr.Mode)))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil {
 | 
								if err := remapIDs(archiver.IDMapping, hdr); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1192,13 +1190,13 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IDMappings returns the IDMappings of the archiver.
 | 
					// IdentityMapping returns the IdentityMapping of the archiver.
 | 
				
			||||||
func (archiver *Archiver) IDMappings() *idtools.IDMappings {
 | 
					func (archiver *Archiver) IdentityMapping() *idtools.IdentityMapping {
 | 
				
			||||||
	return archiver.IDMappingsVar
 | 
						return archiver.IDMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func remapIDs(idMappings *idtools.IDMappings, hdr *tar.Header) error {
 | 
					func remapIDs(idMapping *idtools.IdentityMapping, hdr *tar.Header) error {
 | 
				
			||||||
	ids, err := idMappings.ToHost(idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid})
 | 
						ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid})
 | 
				
			||||||
	hdr.Uid, hdr.Gid = ids.UID, ids.GID
 | 
						hdr.Uid, hdr.Gid = ids.UID, ids.GID
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -755,11 +755,11 @@ func TestTarWithOptionsChownOptsAlwaysOverridesIdPair(t *testing.T) {
 | 
				
			||||||
		expectedUID int
 | 
							expectedUID int
 | 
				
			||||||
		expectedGID int
 | 
							expectedGID int
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{&TarOptions{ChownOpts: &idtools.IDPair{UID: 1337, GID: 42}}, 1337, 42},
 | 
							{&TarOptions{ChownOpts: &idtools.Identity{UID: 1337, GID: 42}}, 1337, 42},
 | 
				
			||||||
		{&TarOptions{ChownOpts: &idtools.IDPair{UID: 100001, GID: 100001}, UIDMaps: idMaps, GIDMaps: idMaps}, 100001, 100001},
 | 
							{&TarOptions{ChownOpts: &idtools.Identity{UID: 100001, GID: 100001}, UIDMaps: idMaps, GIDMaps: idMaps}, 100001, 100001},
 | 
				
			||||||
		{&TarOptions{ChownOpts: &idtools.IDPair{UID: 0, GID: 0}, NoLchown: false}, 0, 0},
 | 
							{&TarOptions{ChownOpts: &idtools.Identity{UID: 0, GID: 0}, NoLchown: false}, 0, 0},
 | 
				
			||||||
		{&TarOptions{ChownOpts: &idtools.IDPair{UID: 1, GID: 1}, NoLchown: true}, 1, 1},
 | 
							{&TarOptions{ChownOpts: &idtools.Identity{UID: 1, GID: 1}, NoLchown: true}, 1, 1},
 | 
				
			||||||
		{&TarOptions{ChownOpts: &idtools.IDPair{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000},
 | 
							{&TarOptions{ChownOpts: &idtools.Identity{UID: 1000, GID: 1000}, NoLchown: true}, 1000, 1000},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, testCase := range cases {
 | 
						for _, testCase := range cases {
 | 
				
			||||||
		reader, err := TarWithOptions(filePath, testCase.opts)
 | 
							reader, err := TarWithOptions(filePath, testCase.opts)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -68,13 +68,13 @@ func getInodeFromStat(stat interface{}) (inode uint64, err error) {
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getFileUIDGID(stat interface{}) (idtools.IDPair, error) {
 | 
					func getFileUIDGID(stat interface{}) (idtools.Identity, error) {
 | 
				
			||||||
	s, ok := stat.(*syscall.Stat_t)
 | 
						s, ok := stat.(*syscall.Stat_t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return idtools.IDPair{}, errors.New("cannot convert stat value to syscall.Stat_t")
 | 
							return idtools.Identity{}, errors.New("cannot convert stat value to syscall.Stat_t")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return idtools.IDPair{UID: int(s.Uid), GID: int(s.Gid)}, nil
 | 
						return idtools.Identity{UID: int(s.Uid), GID: int(s.Gid)}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// handleTarTypeBlockCharFifo is an OS-specific helper function used by
 | 
					// handleTarTypeBlockCharFifo is an OS-specific helper function used by
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,7 +61,7 @@ func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getFileUIDGID(stat interface{}) (idtools.IDPair, error) {
 | 
					func getFileUIDGID(stat interface{}) (idtools.Identity, error) {
 | 
				
			||||||
	// no notion of file ownership mapping yet on Windows
 | 
						// no notion of file ownership mapping yet on Windows
 | 
				
			||||||
	return idtools.IDPair{UID: 0, GID: 0}, nil
 | 
						return idtools.Identity{UID: 0, GID: 0}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,7 +33,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
 | 
				
			||||||
	if options.ExcludePatterns == nil {
 | 
						if options.ExcludePatterns == nil {
 | 
				
			||||||
		options.ExcludePatterns = []string{}
 | 
							options.ExcludePatterns = []string{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
 | 
						idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	aufsTempdir := ""
 | 
						aufsTempdir := ""
 | 
				
			||||||
	aufsHardlinks := make(map[string]*tar.Header)
 | 
						aufsHardlinks := make(map[string]*tar.Header)
 | 
				
			||||||
| 
						 | 
					@ -192,7 +192,7 @@ func UnpackLayer(dest string, layer io.Reader, options *TarOptions) (size int64,
 | 
				
			||||||
				srcData = tmpFile
 | 
									srcData = tmpFile
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := remapIDs(idMappings, srcHdr); err != nil {
 | 
								if err := remapIDs(idMapping, srcHdr); err != nil {
 | 
				
			||||||
				return 0, err
 | 
									return 0, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,13 +12,13 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewArchiver returns a new Archiver which uses chrootarchive.Untar
 | 
					// NewArchiver returns a new Archiver which uses chrootarchive.Untar
 | 
				
			||||||
func NewArchiver(idMappings *idtools.IDMappings) *archive.Archiver {
 | 
					func NewArchiver(idMapping *idtools.IdentityMapping) *archive.Archiver {
 | 
				
			||||||
	if idMappings == nil {
 | 
						if idMapping == nil {
 | 
				
			||||||
		idMappings = &idtools.IDMappings{}
 | 
							idMapping = &idtools.IdentityMapping{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return &archive.Archiver{
 | 
						return &archive.Archiver{
 | 
				
			||||||
		Untar:         Untar,
 | 
							Untar:     Untar,
 | 
				
			||||||
		IDMappingsVar: idMappings,
 | 
							IDMapping: idMapping,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -49,8 +49,8 @@ func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions
 | 
				
			||||||
		options.ExcludePatterns = []string{}
 | 
							options.ExcludePatterns = []string{}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idMappings := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
 | 
						idMapping := idtools.NewIDMappingsFromMaps(options.UIDMaps, options.GIDMaps)
 | 
				
			||||||
	rootIDs := idMappings.RootPair()
 | 
						rootIDs := idMapping.RootPair()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dest = filepath.Clean(dest)
 | 
						dest = filepath.Clean(dest)
 | 
				
			||||||
	if _, err := os.Stat(dest); os.IsNotExist(err) {
 | 
						if _, err := os.Stat(dest); os.IsNotExist(err) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,11 +22,11 @@ type UntarFunc func(io.Reader, string, *archive.TarOptions) error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Archiver provides a similar implementation of the archive.Archiver package with the rootfs abstraction
 | 
					// Archiver provides a similar implementation of the archive.Archiver package with the rootfs abstraction
 | 
				
			||||||
type Archiver struct {
 | 
					type Archiver struct {
 | 
				
			||||||
	SrcDriver     Driver
 | 
						SrcDriver Driver
 | 
				
			||||||
	DstDriver     Driver
 | 
						DstDriver Driver
 | 
				
			||||||
	Tar           TarFunc
 | 
						Tar       TarFunc
 | 
				
			||||||
	Untar         UntarFunc
 | 
						Untar     UntarFunc
 | 
				
			||||||
	IDMappingsVar *idtools.IDMappings
 | 
						IDMapping *idtools.IdentityMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
 | 
					// TarUntar is a convenience function which calls Tar and Untar, with the output of one piped into the other.
 | 
				
			||||||
| 
						 | 
					@ -39,8 +39,8 @@ func (archiver *Archiver) TarUntar(src, dst string) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer tarArchive.Close()
 | 
						defer tarArchive.Close()
 | 
				
			||||||
	options := &archive.TarOptions{
 | 
						options := &archive.TarOptions{
 | 
				
			||||||
		UIDMaps: archiver.IDMappingsVar.UIDs(),
 | 
							UIDMaps: archiver.IDMapping.UIDs(),
 | 
				
			||||||
		GIDMaps: archiver.IDMappingsVar.GIDs(),
 | 
							GIDMaps: archiver.IDMapping.GIDs(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return archiver.Untar(tarArchive, dst, options)
 | 
						return archiver.Untar(tarArchive, dst, options)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -53,8 +53,8 @@ func (archiver *Archiver) UntarPath(src, dst string) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer tarArchive.Close()
 | 
						defer tarArchive.Close()
 | 
				
			||||||
	options := &archive.TarOptions{
 | 
						options := &archive.TarOptions{
 | 
				
			||||||
		UIDMaps: archiver.IDMappingsVar.UIDs(),
 | 
							UIDMaps: archiver.IDMapping.UIDs(),
 | 
				
			||||||
		GIDMaps: archiver.IDMappingsVar.GIDs(),
 | 
							GIDMaps: archiver.IDMapping.GIDs(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return archiver.Untar(tarArchive, dst, options)
 | 
						return archiver.Untar(tarArchive, dst, options)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -75,9 +75,11 @@ func (archiver *Archiver) CopyWithTar(src, dst string) error {
 | 
				
			||||||
	// if this archiver is set up with ID mapping we need to create
 | 
						// if this archiver is set up with ID mapping we need to create
 | 
				
			||||||
	// the new destination directory with the remapped root UID/GID pair
 | 
						// the new destination directory with the remapped root UID/GID pair
 | 
				
			||||||
	// as owner
 | 
						// as owner
 | 
				
			||||||
	rootIDs := archiver.IDMappingsVar.RootPair()
 | 
					
 | 
				
			||||||
 | 
						identity := idtools.Identity{UID: archiver.IDMapping.RootPair().UID, GID: archiver.IDMapping.RootPair().GID}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Create dst, copy src's content into it
 | 
						// Create dst, copy src's content into it
 | 
				
			||||||
	if err := idtools.MkdirAllAndChownNew(dst, 0755, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChownNew(dst, 0755, identity); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	logrus.Debugf("Calling TarUntar(%s, %s)", src, dst)
 | 
						logrus.Debugf("Calling TarUntar(%s, %s)", src, dst)
 | 
				
			||||||
| 
						 | 
					@ -150,7 +152,7 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
 | 
				
			||||||
				hdr.Mode = int64(os.FileMode(hdr.Mode))
 | 
									hdr.Mode = int64(os.FileMode(hdr.Mode))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if err := remapIDs(archiver.IDMappingsVar, hdr); err != nil {
 | 
								if err := remapIDs(archiver.IDMapping, hdr); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,13 +180,13 @@ func (archiver *Archiver) CopyFileWithTar(src, dst string) (err error) {
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IDMappings returns the IDMappings of the archiver.
 | 
					// IdentityMapping returns the IdentityMapping of the archiver.
 | 
				
			||||||
func (archiver *Archiver) IDMappings() *idtools.IDMappings {
 | 
					func (archiver *Archiver) IdentityMapping() *idtools.IdentityMapping {
 | 
				
			||||||
	return archiver.IDMappingsVar
 | 
						return archiver.IDMapping
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func remapIDs(idMappings *idtools.IDMappings, hdr *tar.Header) error {
 | 
					func remapIDs(idMapping *idtools.IdentityMapping, hdr *tar.Header) error {
 | 
				
			||||||
	ids, err := idMappings.ToHost(idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid})
 | 
						ids, err := idMapping.ToHost(idtools.Identity{UID: hdr.Uid, GID: hdr.Gid})
 | 
				
			||||||
	hdr.Uid, hdr.Gid = ids.UID, ids.GID
 | 
						hdr.Uid, hdr.Gid = ids.UID, ids.GID
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,23 +37,23 @@ const (
 | 
				
			||||||
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
 | 
					// MkdirAllAndChown creates a directory (include any along the path) and then modifies
 | 
				
			||||||
// ownership to the requested uid/gid.  If the directory already exists, this
 | 
					// ownership to the requested uid/gid.  If the directory already exists, this
 | 
				
			||||||
// function will still change ownership to the requested uid/gid pair.
 | 
					// function will still change ownership to the requested uid/gid pair.
 | 
				
			||||||
func MkdirAllAndChown(path string, mode os.FileMode, owner IDPair) error {
 | 
					func MkdirAllAndChown(path string, mode os.FileMode, owner Identity) error {
 | 
				
			||||||
	return mkdirAs(path, mode, owner.UID, owner.GID, true, true)
 | 
						return mkdirAs(path, mode, owner, true, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
 | 
					// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
 | 
				
			||||||
// If the directory already exists, this function still changes ownership.
 | 
					// If the directory already exists, this function still changes ownership.
 | 
				
			||||||
// Note that unlike os.Mkdir(), this function does not return IsExist error
 | 
					// Note that unlike os.Mkdir(), this function does not return IsExist error
 | 
				
			||||||
// in case path already exists.
 | 
					// in case path already exists.
 | 
				
			||||||
func MkdirAndChown(path string, mode os.FileMode, owner IDPair) error {
 | 
					func MkdirAndChown(path string, mode os.FileMode, owner Identity) error {
 | 
				
			||||||
	return mkdirAs(path, mode, owner.UID, owner.GID, false, true)
 | 
						return mkdirAs(path, mode, owner, false, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
 | 
					// MkdirAllAndChownNew creates a directory (include any along the path) and then modifies
 | 
				
			||||||
// ownership ONLY of newly created directories to the requested uid/gid. If the
 | 
					// ownership ONLY of newly created directories to the requested uid/gid. If the
 | 
				
			||||||
// directories along the path exist, no change of ownership will be performed
 | 
					// directories along the path exist, no change of ownership will be performed
 | 
				
			||||||
func MkdirAllAndChownNew(path string, mode os.FileMode, owner IDPair) error {
 | 
					func MkdirAllAndChownNew(path string, mode os.FileMode, owner Identity) error {
 | 
				
			||||||
	return mkdirAs(path, mode, owner.UID, owner.GID, true, false)
 | 
						return mkdirAs(path, mode, owner, true, false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
 | 
					// GetRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
 | 
				
			||||||
| 
						 | 
					@ -102,22 +102,23 @@ func toHost(contID int, idMap []IDMap) (int, error) {
 | 
				
			||||||
	return -1, fmt.Errorf("Container ID %d cannot be mapped to a host ID", contID)
 | 
						return -1, fmt.Errorf("Container ID %d cannot be mapped to a host ID", contID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IDPair is a UID and GID pair
 | 
					// Identity is either a UID and GID pair or a SID (but not both)
 | 
				
			||||||
type IDPair struct {
 | 
					type Identity struct {
 | 
				
			||||||
	UID int
 | 
						UID int
 | 
				
			||||||
	GID int
 | 
						GID int
 | 
				
			||||||
 | 
						SID string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IDMappings contains a mappings of UIDs and GIDs
 | 
					// IdentityMapping contains a mappings of UIDs and GIDs
 | 
				
			||||||
type IDMappings struct {
 | 
					type IdentityMapping struct {
 | 
				
			||||||
	uids []IDMap
 | 
						uids []IDMap
 | 
				
			||||||
	gids []IDMap
 | 
						gids []IDMap
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewIDMappings takes a requested user and group name and
 | 
					// NewIdentityMapping takes a requested user and group name and
 | 
				
			||||||
// using the data from /etc/sub{uid,gid} ranges, creates the
 | 
					// using the data from /etc/sub{uid,gid} ranges, creates the
 | 
				
			||||||
// proper uid and gid remapping ranges for that user/group pair
 | 
					// proper uid and gid remapping ranges for that user/group pair
 | 
				
			||||||
func NewIDMappings(username, groupname string) (*IDMappings, error) {
 | 
					func NewIdentityMapping(username, groupname string) (*IdentityMapping, error) {
 | 
				
			||||||
	subuidRanges, err := parseSubuid(username)
 | 
						subuidRanges, err := parseSubuid(username)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					@ -133,7 +134,7 @@ func NewIDMappings(username, groupname string) (*IDMappings, error) {
 | 
				
			||||||
		return nil, fmt.Errorf("No subgid ranges found for group %q", groupname)
 | 
							return nil, fmt.Errorf("No subgid ranges found for group %q", groupname)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &IDMappings{
 | 
						return &IdentityMapping{
 | 
				
			||||||
		uids: createIDMap(subuidRanges),
 | 
							uids: createIDMap(subuidRanges),
 | 
				
			||||||
		gids: createIDMap(subgidRanges),
 | 
							gids: createIDMap(subgidRanges),
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
| 
						 | 
					@ -141,21 +142,21 @@ func NewIDMappings(username, groupname string) (*IDMappings, error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewIDMappingsFromMaps creates a new mapping from two slices
 | 
					// NewIDMappingsFromMaps creates a new mapping from two slices
 | 
				
			||||||
// Deprecated: this is a temporary shim while transitioning to IDMapping
 | 
					// Deprecated: this is a temporary shim while transitioning to IDMapping
 | 
				
			||||||
func NewIDMappingsFromMaps(uids []IDMap, gids []IDMap) *IDMappings {
 | 
					func NewIDMappingsFromMaps(uids []IDMap, gids []IDMap) *IdentityMapping {
 | 
				
			||||||
	return &IDMappings{uids: uids, gids: gids}
 | 
						return &IdentityMapping{uids: uids, gids: gids}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RootPair returns a uid and gid pair for the root user. The error is ignored
 | 
					// RootPair returns a uid and gid pair for the root user. The error is ignored
 | 
				
			||||||
// because a root user always exists, and the defaults are correct when the uid
 | 
					// because a root user always exists, and the defaults are correct when the uid
 | 
				
			||||||
// and gid maps are empty.
 | 
					// and gid maps are empty.
 | 
				
			||||||
func (i *IDMappings) RootPair() IDPair {
 | 
					func (i *IdentityMapping) RootPair() Identity {
 | 
				
			||||||
	uid, gid, _ := GetRootUIDGID(i.uids, i.gids)
 | 
						uid, gid, _ := GetRootUIDGID(i.uids, i.gids)
 | 
				
			||||||
	return IDPair{UID: uid, GID: gid}
 | 
						return Identity{UID: uid, GID: gid}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToHost returns the host UID and GID for the container uid, gid.
 | 
					// ToHost returns the host UID and GID for the container uid, gid.
 | 
				
			||||||
// Remapping is only performed if the ids aren't already the remapped root ids
 | 
					// Remapping is only performed if the ids aren't already the remapped root ids
 | 
				
			||||||
func (i *IDMappings) ToHost(pair IDPair) (IDPair, error) {
 | 
					func (i *IdentityMapping) ToHost(pair Identity) (Identity, error) {
 | 
				
			||||||
	var err error
 | 
						var err error
 | 
				
			||||||
	target := i.RootPair()
 | 
						target := i.RootPair()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -173,7 +174,7 @@ func (i *IDMappings) ToHost(pair IDPair) (IDPair, error) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToContainer returns the container UID and GID for the host uid and gid
 | 
					// ToContainer returns the container UID and GID for the host uid and gid
 | 
				
			||||||
func (i *IDMappings) ToContainer(pair IDPair) (int, int, error) {
 | 
					func (i *IdentityMapping) ToContainer(pair Identity) (int, int, error) {
 | 
				
			||||||
	uid, err := toContainer(pair.UID, i.uids)
 | 
						uid, err := toContainer(pair.UID, i.uids)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return -1, -1, err
 | 
							return -1, -1, err
 | 
				
			||||||
| 
						 | 
					@ -183,19 +184,19 @@ func (i *IDMappings) ToContainer(pair IDPair) (int, int, error) {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Empty returns true if there are no id mappings
 | 
					// Empty returns true if there are no id mappings
 | 
				
			||||||
func (i *IDMappings) Empty() bool {
 | 
					func (i *IdentityMapping) Empty() bool {
 | 
				
			||||||
	return len(i.uids) == 0 && len(i.gids) == 0
 | 
						return len(i.uids) == 0 && len(i.gids) == 0
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// UIDs return the UID mapping
 | 
					// UIDs return the UID mapping
 | 
				
			||||||
// TODO: remove this once everything has been refactored to use pairs
 | 
					// TODO: remove this once everything has been refactored to use pairs
 | 
				
			||||||
func (i *IDMappings) UIDs() []IDMap {
 | 
					func (i *IdentityMapping) UIDs() []IDMap {
 | 
				
			||||||
	return i.uids
 | 
						return i.uids
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GIDs return the UID mapping
 | 
					// GIDs return the UID mapping
 | 
				
			||||||
// TODO: remove this once everything has been refactored to use pairs
 | 
					// TODO: remove this once everything has been refactored to use pairs
 | 
				
			||||||
func (i *IDMappings) GIDs() []IDMap {
 | 
					func (i *IdentityMapping) GIDs() []IDMap {
 | 
				
			||||||
	return i.gids
 | 
						return i.gids
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,11 +21,12 @@ var (
 | 
				
			||||||
	getentCmd string
 | 
						getentCmd string
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error {
 | 
					func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
 | 
				
			||||||
	// make an array containing the original path asked for, plus (for mkAll == true)
 | 
						// make an array containing the original path asked for, plus (for mkAll == true)
 | 
				
			||||||
	// all path components leading up to the complete path that don't exist before we MkdirAll
 | 
						// all path components leading up to the complete path that don't exist before we MkdirAll
 | 
				
			||||||
	// so that we can chown all of them properly at the end.  If chownExisting is false, we won't
 | 
						// so that we can chown all of them properly at the end.  If chownExisting is false, we won't
 | 
				
			||||||
	// chown the full directory path if it exists
 | 
						// chown the full directory path if it exists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var paths []string
 | 
						var paths []string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	stat, err := system.Stat(path)
 | 
						stat, err := system.Stat(path)
 | 
				
			||||||
| 
						 | 
					@ -38,7 +39,7 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// short-circuit--we were called with an existing directory and chown was requested
 | 
							// short-circuit--we were called with an existing directory and chown was requested
 | 
				
			||||||
		return lazyChown(path, ownerUID, ownerGID, stat)
 | 
							return lazyChown(path, owner.UID, owner.GID, stat)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if os.IsNotExist(err) {
 | 
						if os.IsNotExist(err) {
 | 
				
			||||||
| 
						 | 
					@ -69,7 +70,7 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown
 | 
				
			||||||
	// even if it existed, we will chown the requested path + any subpaths that
 | 
						// even if it existed, we will chown the requested path + any subpaths that
 | 
				
			||||||
	// didn't exist when we called MkdirAll
 | 
						// didn't exist when we called MkdirAll
 | 
				
			||||||
	for _, pathComponent := range paths {
 | 
						for _, pathComponent := range paths {
 | 
				
			||||||
		if err := lazyChown(pathComponent, ownerUID, ownerGID, nil); err != nil {
 | 
							if err := lazyChown(pathComponent, owner.UID, owner.GID, nil); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -78,7 +79,7 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
 | 
					// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
 | 
				
			||||||
// if that uid, gid pair has access (execute bit) to the directory
 | 
					// if that uid, gid pair has access (execute bit) to the directory
 | 
				
			||||||
func CanAccess(path string, pair IDPair) bool {
 | 
					func CanAccess(path string, pair Identity) bool {
 | 
				
			||||||
	statInfo, err := system.Stat(path)
 | 
						statInfo, err := system.Stat(path)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ func TestMkdirAllAndChown(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test adding a directory to a pre-existing dir; only the new dir is owned by the uid/gid
 | 
						// test adding a directory to a pre-existing dir; only the new dir is owned by the uid/gid
 | 
				
			||||||
	if err := MkdirAllAndChown(filepath.Join(dirName, "usr", "share"), 0755, IDPair{UID: 99, GID: 99}); err != nil {
 | 
						if err := MkdirAllAndChown(filepath.Join(dirName, "usr", "share"), 0755, Identity{UID: 99, GID: 99}); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testTree["usr/share"] = node{99, 99}
 | 
						testTree["usr/share"] = node{99, 99}
 | 
				
			||||||
| 
						 | 
					@ -59,7 +59,7 @@ func TestMkdirAllAndChown(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test 2-deep new directories--both should be owned by the uid/gid pair
 | 
						// test 2-deep new directories--both should be owned by the uid/gid pair
 | 
				
			||||||
	if err := MkdirAllAndChown(filepath.Join(dirName, "lib", "some", "other"), 0755, IDPair{UID: 101, GID: 101}); err != nil {
 | 
						if err := MkdirAllAndChown(filepath.Join(dirName, "lib", "some", "other"), 0755, Identity{UID: 101, GID: 101}); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testTree["lib/some"] = node{101, 101}
 | 
						testTree["lib/some"] = node{101, 101}
 | 
				
			||||||
| 
						 | 
					@ -73,7 +73,7 @@ func TestMkdirAllAndChown(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test a directory that already exists; should be chowned, but nothing else
 | 
						// test a directory that already exists; should be chowned, but nothing else
 | 
				
			||||||
	if err := MkdirAllAndChown(filepath.Join(dirName, "usr"), 0755, IDPair{UID: 102, GID: 102}); err != nil {
 | 
						if err := MkdirAllAndChown(filepath.Join(dirName, "usr"), 0755, Identity{UID: 102, GID: 102}); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testTree["usr"] = node{102, 102}
 | 
						testTree["usr"] = node{102, 102}
 | 
				
			||||||
| 
						 | 
					@ -102,7 +102,7 @@ func TestMkdirAllAndChownNew(t *testing.T) {
 | 
				
			||||||
	assert.NilError(t, buildTree(dirName, testTree))
 | 
						assert.NilError(t, buildTree(dirName, testTree))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test adding a directory to a pre-existing dir; only the new dir is owned by the uid/gid
 | 
						// test adding a directory to a pre-existing dir; only the new dir is owned by the uid/gid
 | 
				
			||||||
	err = MkdirAllAndChownNew(filepath.Join(dirName, "usr", "share"), 0755, IDPair{UID: 99, GID: 99})
 | 
						err = MkdirAllAndChownNew(filepath.Join(dirName, "usr", "share"), 0755, Identity{UID: 99, GID: 99})
 | 
				
			||||||
	assert.NilError(t, err)
 | 
						assert.NilError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	testTree["usr/share"] = node{99, 99}
 | 
						testTree["usr/share"] = node{99, 99}
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,7 @@ func TestMkdirAllAndChownNew(t *testing.T) {
 | 
				
			||||||
	assert.NilError(t, compareTrees(testTree, verifyTree))
 | 
						assert.NilError(t, compareTrees(testTree, verifyTree))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test 2-deep new directories--both should be owned by the uid/gid pair
 | 
						// test 2-deep new directories--both should be owned by the uid/gid pair
 | 
				
			||||||
	err = MkdirAllAndChownNew(filepath.Join(dirName, "lib", "some", "other"), 0755, IDPair{UID: 101, GID: 101})
 | 
						err = MkdirAllAndChownNew(filepath.Join(dirName, "lib", "some", "other"), 0755, Identity{UID: 101, GID: 101})
 | 
				
			||||||
	assert.NilError(t, err)
 | 
						assert.NilError(t, err)
 | 
				
			||||||
	testTree["lib/some"] = node{101, 101}
 | 
						testTree["lib/some"] = node{101, 101}
 | 
				
			||||||
	testTree["lib/some/other"] = node{101, 101}
 | 
						testTree["lib/some/other"] = node{101, 101}
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ func TestMkdirAllAndChownNew(t *testing.T) {
 | 
				
			||||||
	assert.NilError(t, compareTrees(testTree, verifyTree))
 | 
						assert.NilError(t, compareTrees(testTree, verifyTree))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test a directory that already exists; should NOT be chowned
 | 
						// test a directory that already exists; should NOT be chowned
 | 
				
			||||||
	err = MkdirAllAndChownNew(filepath.Join(dirName, "usr"), 0755, IDPair{UID: 102, GID: 102})
 | 
						err = MkdirAllAndChownNew(filepath.Join(dirName, "usr"), 0755, Identity{UID: 102, GID: 102})
 | 
				
			||||||
	assert.NilError(t, err)
 | 
						assert.NilError(t, err)
 | 
				
			||||||
	verifyTree, err = readTree(dirName, "")
 | 
						verifyTree, err = readTree(dirName, "")
 | 
				
			||||||
	assert.NilError(t, err)
 | 
						assert.NilError(t, err)
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,7 @@ func TestMkdirAndChown(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// test a directory that already exists; should just chown to the requested uid/gid
 | 
						// test a directory that already exists; should just chown to the requested uid/gid
 | 
				
			||||||
	if err := MkdirAndChown(filepath.Join(dirName, "usr"), 0755, IDPair{UID: 99, GID: 99}); err != nil {
 | 
						if err := MkdirAndChown(filepath.Join(dirName, "usr"), 0755, Identity{UID: 99, GID: 99}); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testTree["usr"] = node{99, 99}
 | 
						testTree["usr"] = node{99, 99}
 | 
				
			||||||
| 
						 | 
					@ -156,12 +156,12 @@ func TestMkdirAndChown(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// create a subdir under a dir which doesn't exist--should fail
 | 
						// create a subdir under a dir which doesn't exist--should fail
 | 
				
			||||||
	if err := MkdirAndChown(filepath.Join(dirName, "usr", "bin", "subdir"), 0755, IDPair{UID: 102, GID: 102}); err == nil {
 | 
						if err := MkdirAndChown(filepath.Join(dirName, "usr", "bin", "subdir"), 0755, Identity{UID: 102, GID: 102}); err == nil {
 | 
				
			||||||
		t.Fatalf("Trying to create a directory with Mkdir where the parent doesn't exist should have failed")
 | 
							t.Fatalf("Trying to create a directory with Mkdir where the parent doesn't exist should have failed")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// create a subdir under an existing dir; should only change the ownership of the new subdir
 | 
						// create a subdir under an existing dir; should only change the ownership of the new subdir
 | 
				
			||||||
	if err := MkdirAndChown(filepath.Join(dirName, "usr", "bin"), 0755, IDPair{UID: 102, GID: 102}); err != nil {
 | 
						if err := MkdirAndChown(filepath.Join(dirName, "usr", "bin"), 0755, Identity{UID: 102, GID: 102}); err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	testTree["usr/bin"] = node{102, 102}
 | 
						testTree["usr/bin"] = node{102, 102}
 | 
				
			||||||
| 
						 | 
					@ -326,19 +326,19 @@ func TestNewIDMappings(t *testing.T) {
 | 
				
			||||||
	group, err := user.LookupGroupId(string(gids[0]))
 | 
						group, err := user.LookupGroupId(string(gids[0]))
 | 
				
			||||||
	assert.Check(t, err)
 | 
						assert.Check(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	idMappings, err := NewIDMappings(tempUser.Username, group.Name)
 | 
						idMapping, err := NewIdentityMapping(tempUser.Username, group.Name)
 | 
				
			||||||
	assert.Check(t, err)
 | 
						assert.Check(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rootUID, rootGID, err := GetRootUIDGID(idMappings.UIDs(), idMappings.GIDs())
 | 
						rootUID, rootGID, err := GetRootUIDGID(idMapping.UIDs(), idMapping.GIDs())
 | 
				
			||||||
	assert.Check(t, err)
 | 
						assert.Check(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dirName, err := ioutil.TempDir("", "mkdirall")
 | 
						dirName, err := ioutil.TempDir("", "mkdirall")
 | 
				
			||||||
	assert.Check(t, err, "Couldn't create temp directory")
 | 
						assert.Check(t, err, "Couldn't create temp directory")
 | 
				
			||||||
	defer os.RemoveAll(dirName)
 | 
						defer os.RemoveAll(dirName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = MkdirAllAndChown(dirName, 0700, IDPair{UID: rootUID, GID: rootGID})
 | 
						err = MkdirAllAndChown(dirName, 0700, Identity{UID: rootUID, GID: rootGID})
 | 
				
			||||||
	assert.Check(t, err, "Couldn't change ownership of file path. Got error")
 | 
						assert.Check(t, err, "Couldn't change ownership of file path. Got error")
 | 
				
			||||||
	assert.Check(t, CanAccess(dirName, idMappings.RootPair()), fmt.Sprintf("Unable to access %s directory with user UID:%d and GID:%d", dirName, rootUID, rootGID))
 | 
						assert.Check(t, CanAccess(dirName, idMapping.RootPair()), fmt.Sprintf("Unable to access %s directory with user UID:%d and GID:%d", dirName, rootUID, rootGID))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestLookupUserAndGroup(t *testing.T) {
 | 
					func TestLookupUserAndGroup(t *testing.T) {
 | 
				
			||||||
| 
						 | 
					@ -388,7 +388,7 @@ func TestMkdirIsNotDir(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer os.Remove(file.Name())
 | 
						defer os.Remove(file.Name())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = mkdirAs(file.Name(), 0755, 0, 0, false, false)
 | 
						err = mkdirAs(file.Name(), 0755, Identity{UID: 0, GID: 0}, false, false)
 | 
				
			||||||
	assert.Check(t, is.Error(err, "mkdir "+file.Name()+": not a directory"))
 | 
						assert.Check(t, is.Error(err, "mkdir "+file.Name()+": not a directory"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,9 +6,11 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/pkg/system"
 | 
						"github.com/docker/docker/pkg/system"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Platforms such as Windows do not support the UID/GID concept. So make this
 | 
					// This is currently a wrapper around MkdirAll, however, since currently
 | 
				
			||||||
// just a wrapper around system.MkdirAll.
 | 
					// permissions aren't set through this path, the identity isn't utilized.
 | 
				
			||||||
func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chownExisting bool) error {
 | 
					// Ownership is handled elsewhere, but in the future could be support here
 | 
				
			||||||
 | 
					// too.
 | 
				
			||||||
 | 
					func mkdirAs(path string, mode os.FileMode, owner Identity, mkAll, chownExisting bool) error {
 | 
				
			||||||
	if err := system.MkdirAll(path, mode, ""); err != nil {
 | 
						if err := system.MkdirAll(path, mode, ""); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -18,6 +20,6 @@ func mkdirAs(path string, mode os.FileMode, ownerUID, ownerGID int, mkAll, chown
 | 
				
			||||||
// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
 | 
					// CanAccess takes a valid (existing) directory and a uid, gid pair and determines
 | 
				
			||||||
// if that uid, gid pair has access (execute bit) to the directory
 | 
					// if that uid, gid pair has access (execute bit) to the directory
 | 
				
			||||||
// Windows does not require/support this function, so always return true
 | 
					// Windows does not require/support this function, so always return true
 | 
				
			||||||
func CanAccess(path string, pair IDPair) bool {
 | 
					func CanAccess(path string, identity Identity) bool {
 | 
				
			||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,16 +2,62 @@ package system // import "github.com/docker/docker/pkg/system"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/sirupsen/logrus"
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
	"golang.org/x/sys/windows"
 | 
						"golang.org/x/sys/windows"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						OWNER_SECURITY_INFORMATION               = 0x00000001
 | 
				
			||||||
 | 
						GROUP_SECURITY_INFORMATION               = 0x00000002
 | 
				
			||||||
 | 
						DACL_SECURITY_INFORMATION                = 0x00000004
 | 
				
			||||||
 | 
						SACL_SECURITY_INFORMATION                = 0x00000008
 | 
				
			||||||
 | 
						LABEL_SECURITY_INFORMATION               = 0x00000010
 | 
				
			||||||
 | 
						ATTRIBUTE_SECURITY_INFORMATION           = 0x00000020
 | 
				
			||||||
 | 
						SCOPE_SECURITY_INFORMATION               = 0x00000040
 | 
				
			||||||
 | 
						PROCESS_TRUST_LABEL_SECURITY_INFORMATION = 0x00000080
 | 
				
			||||||
 | 
						ACCESS_FILTER_SECURITY_INFORMATION       = 0x00000100
 | 
				
			||||||
 | 
						BACKUP_SECURITY_INFORMATION              = 0x00010000
 | 
				
			||||||
 | 
						PROTECTED_DACL_SECURITY_INFORMATION      = 0x80000000
 | 
				
			||||||
 | 
						PROTECTED_SACL_SECURITY_INFORMATION      = 0x40000000
 | 
				
			||||||
 | 
						UNPROTECTED_DACL_SECURITY_INFORMATION    = 0x20000000
 | 
				
			||||||
 | 
						UNPROTECTED_SACL_SECURITY_INFORMATION    = 0x10000000
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						SE_UNKNOWN_OBJECT_TYPE = iota
 | 
				
			||||||
 | 
						SE_FILE_OBJECT
 | 
				
			||||||
 | 
						SE_SERVICE
 | 
				
			||||||
 | 
						SE_PRINTER
 | 
				
			||||||
 | 
						SE_REGISTRY_KEY
 | 
				
			||||||
 | 
						SE_LMSHARE
 | 
				
			||||||
 | 
						SE_KERNEL_OBJECT
 | 
				
			||||||
 | 
						SE_WINDOW_OBJECT
 | 
				
			||||||
 | 
						SE_DS_OBJECT
 | 
				
			||||||
 | 
						SE_DS_OBJECT_ALL
 | 
				
			||||||
 | 
						SE_PROVIDER_DEFINED_OBJECT
 | 
				
			||||||
 | 
						SE_WMIGUID_OBJECT
 | 
				
			||||||
 | 
						SE_REGISTRY_WOW64_32KEY
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						SeTakeOwnershipPrivilege = "SeTakeOwnershipPrivilege"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ContainerAdministratorSidString = "S-1-5-93-2-1"
 | 
				
			||||||
 | 
						ContainerUserSidString          = "S-1-5-93-2-2"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	ntuserApiset       = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
 | 
						ntuserApiset                  = windows.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
 | 
				
			||||||
	procGetVersionExW  = modkernel32.NewProc("GetVersionExW")
 | 
						modadvapi32                   = windows.NewLazySystemDLL("advapi32.dll")
 | 
				
			||||||
	procGetProductInfo = modkernel32.NewProc("GetProductInfo")
 | 
						procGetVersionExW             = modkernel32.NewProc("GetVersionExW")
 | 
				
			||||||
 | 
						procGetProductInfo            = modkernel32.NewProc("GetProductInfo")
 | 
				
			||||||
 | 
						procSetNamedSecurityInfo      = modadvapi32.NewProc("SetNamedSecurityInfoW")
 | 
				
			||||||
 | 
						procGetSecurityDescriptorDacl = modadvapi32.NewProc("GetSecurityDescriptorDacl")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// OSVersion is a wrapper for Windows version information
 | 
					// OSVersion is a wrapper for Windows version information
 | 
				
			||||||
| 
						 | 
					@ -125,3 +171,23 @@ func HasWin32KSupport() bool {
 | 
				
			||||||
	// APIs.
 | 
						// APIs.
 | 
				
			||||||
	return ntuserApiset.Load() == nil
 | 
						return ntuserApiset.Load() == nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SetNamedSecurityInfo(objectName *uint16, objectType uint32, securityInformation uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *byte, sacl *byte) (result error) {
 | 
				
			||||||
 | 
						r0, _, _ := syscall.Syscall9(procSetNamedSecurityInfo.Addr(), 7, uintptr(unsafe.Pointer(objectName)), uintptr(objectType), uintptr(securityInformation), uintptr(unsafe.Pointer(sidOwner)), uintptr(unsafe.Pointer(sidGroup)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(sacl)), 0, 0)
 | 
				
			||||||
 | 
						if r0 != 0 {
 | 
				
			||||||
 | 
							result = syscall.Errno(r0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetSecurityDescriptorDacl(securityDescriptor *byte, daclPresent *uint32, dacl **byte, daclDefaulted *uint32) (result error) {
 | 
				
			||||||
 | 
						r1, _, e1 := syscall.Syscall6(procGetSecurityDescriptorDacl.Addr(), 4, uintptr(unsafe.Pointer(securityDescriptor)), uintptr(unsafe.Pointer(daclPresent)), uintptr(unsafe.Pointer(dacl)), uintptr(unsafe.Pointer(daclDefaulted)), 0, 0)
 | 
				
			||||||
 | 
						if r1 == 0 {
 | 
				
			||||||
 | 
							if e1 != 0 {
 | 
				
			||||||
 | 
								result = syscall.Errno(e1)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								result = syscall.EINVAL
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,7 +53,7 @@ func (pm *Manager) enable(p *v2.Plugin, c *controller, force bool) error {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rootFS := containerfs.NewLocalContainerFS(filepath.Join(pm.config.Root, p.PluginObj.ID, rootFSFileName))
 | 
						rootFS := containerfs.NewLocalContainerFS(filepath.Join(pm.config.Root, p.PluginObj.ID, rootFSFileName))
 | 
				
			||||||
	if err := initlayer.Setup(rootFS, idtools.IDPair{UID: 0, GID: 0}); err != nil {
 | 
						if err := initlayer.Setup(rootFS, idtools.Identity{UID: 0, GID: 0}); err != nil {
 | 
				
			||||||
		return errors.WithStack(err)
 | 
							return errors.WithStack(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,18 +46,18 @@ type activeMount struct {
 | 
				
			||||||
// New instantiates a new Root instance with the provided scope. Scope
 | 
					// New instantiates a new Root instance with the provided scope. Scope
 | 
				
			||||||
// is the base path that the Root instance uses to store its
 | 
					// is the base path that the Root instance uses to store its
 | 
				
			||||||
// volumes. The base path is created here if it does not exist.
 | 
					// volumes. The base path is created here if it does not exist.
 | 
				
			||||||
func New(scope string, rootIDs idtools.IDPair) (*Root, error) {
 | 
					func New(scope string, rootIdentity idtools.Identity) (*Root, error) {
 | 
				
			||||||
	rootDirectory := filepath.Join(scope, volumesPathName)
 | 
						rootDirectory := filepath.Join(scope, volumesPathName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(rootDirectory, 0700, rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(rootDirectory, 0700, rootIdentity); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r := &Root{
 | 
						r := &Root{
 | 
				
			||||||
		scope:   scope,
 | 
							scope:        scope,
 | 
				
			||||||
		path:    rootDirectory,
 | 
							path:         rootDirectory,
 | 
				
			||||||
		volumes: make(map[string]*localVolume),
 | 
							volumes:      make(map[string]*localVolume),
 | 
				
			||||||
		rootIDs: rootIDs,
 | 
							rootIdentity: rootIdentity,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dirs, err := ioutil.ReadDir(rootDirectory)
 | 
						dirs, err := ioutil.ReadDir(rootDirectory)
 | 
				
			||||||
| 
						 | 
					@ -101,11 +101,11 @@ func New(scope string, rootIDs idtools.IDPair) (*Root, error) {
 | 
				
			||||||
// manages the creation/removal of volumes. It uses only standard vfs
 | 
					// manages the creation/removal of volumes. It uses only standard vfs
 | 
				
			||||||
// commands to create/remove dirs within its provided scope.
 | 
					// commands to create/remove dirs within its provided scope.
 | 
				
			||||||
type Root struct {
 | 
					type Root struct {
 | 
				
			||||||
	m       sync.Mutex
 | 
						m            sync.Mutex
 | 
				
			||||||
	scope   string
 | 
						scope        string
 | 
				
			||||||
	path    string
 | 
						path         string
 | 
				
			||||||
	volumes map[string]*localVolume
 | 
						volumes      map[string]*localVolume
 | 
				
			||||||
	rootIDs idtools.IDPair
 | 
						rootIdentity idtools.Identity
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// List lists all the volumes
 | 
					// List lists all the volumes
 | 
				
			||||||
| 
						 | 
					@ -146,7 +146,7 @@ func (r *Root) Create(name string, opts map[string]string) (volume.Volume, error
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	path := r.DataPath(name)
 | 
						path := r.DataPath(name)
 | 
				
			||||||
	if err := idtools.MkdirAllAndChown(path, 0755, r.rootIDs); err != nil {
 | 
						if err := idtools.MkdirAllAndChown(path, 0755, r.rootIdentity); err != nil {
 | 
				
			||||||
		return nil, errors.Wrapf(errdefs.System(err), "error while creating volume path '%s'", path)
 | 
							return nil, errors.Wrapf(errdefs.System(err), "error while creating volume path '%s'", path)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ func TestRemove(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer os.RemoveAll(rootDir)
 | 
						defer os.RemoveAll(rootDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err := New(rootDir, idtools.IDPair{UID: os.Geteuid(), GID: os.Getegid()})
 | 
						r, err := New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -80,7 +80,7 @@ func TestInitializeWithVolumes(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer os.RemoveAll(rootDir)
 | 
						defer os.RemoveAll(rootDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err := New(rootDir, idtools.IDPair{UID: os.Geteuid(), GID: os.Getegid()})
 | 
						r, err := New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,7 @@ func TestInitializeWithVolumes(t *testing.T) {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err = New(rootDir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						r, err = New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -112,7 +112,7 @@ func TestCreate(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer os.RemoveAll(rootDir)
 | 
						defer os.RemoveAll(rootDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err := New(rootDir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						r, err := New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -149,7 +149,7 @@ func TestCreate(t *testing.T) {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err = New(rootDir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						r, err = New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -186,7 +186,7 @@ func TestCreateWithOpts(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer os.RemoveAll(rootDir)
 | 
						defer os.RemoveAll(rootDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err := New(rootDir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						r, err := New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -261,7 +261,7 @@ func TestCreateWithOpts(t *testing.T) {
 | 
				
			||||||
		t.Fatal("expected mount to still be active")
 | 
							t.Fatal("expected mount to still be active")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err = New(rootDir, idtools.IDPair{UID: 0, GID: 0})
 | 
						r, err = New(rootDir, idtools.Identity{UID: 0, GID: 0})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -283,7 +283,7 @@ func TestRelaodNoOpts(t *testing.T) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	defer os.RemoveAll(rootDir)
 | 
						defer os.RemoveAll(rootDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err := New(rootDir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						r, err := New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -311,7 +311,7 @@ func TestRelaodNoOpts(t *testing.T) {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r, err = New(rootDir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						r, err = New(rootDir, idtools.Identity{UID: os.Geteuid(), GID: os.Getegid()})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		t.Fatal(err)
 | 
							t.Fatal(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -95,7 +95,7 @@ func (m *MountPoint) Cleanup() error {
 | 
				
			||||||
// configured, or creating the source directory if supplied.
 | 
					// configured, or creating the source directory if supplied.
 | 
				
			||||||
// The, optional, checkFun parameter allows doing additional checking
 | 
					// The, optional, checkFun parameter allows doing additional checking
 | 
				
			||||||
// before creating the source directory on the host.
 | 
					// before creating the source directory on the host.
 | 
				
			||||||
func (m *MountPoint) Setup(mountLabel string, rootIDs idtools.IDPair, checkFun func(m *MountPoint) error) (path string, err error) {
 | 
					func (m *MountPoint) Setup(mountLabel string, rootIDs idtools.Identity, checkFun func(m *MountPoint) error) (path string, err error) {
 | 
				
			||||||
	if m.SkipMountpointCreation {
 | 
						if m.SkipMountpointCreation {
 | 
				
			||||||
		return m.Source, nil
 | 
							return m.Source, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ import (
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupDefaultDriver(store *drivers.Store, root string, rootIDs idtools.IDPair) error {
 | 
					func setupDefaultDriver(store *drivers.Store, root string, rootIDs idtools.Identity) error {
 | 
				
			||||||
	d, err := local.New(root, rootIDs)
 | 
						d, err := local.New(root, rootIDs)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errors.Wrap(err, "error setting up default driver")
 | 
							return errors.Wrap(err, "error setting up default driver")
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,4 +7,4 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/volume/drivers"
 | 
						"github.com/docker/docker/volume/drivers"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupDefaultDriver(_ *drivers.Store, _ string, _ idtools.IDPair) error { return nil }
 | 
					func setupDefaultDriver(_ *drivers.Store, _ string, _ idtools.Identity) error { return nil }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,7 @@ type VolumesService struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewVolumeService creates a new volume service
 | 
					// NewVolumeService creates a new volume service
 | 
				
			||||||
func NewVolumeService(root string, pg plugingetter.PluginGetter, rootIDs idtools.IDPair, logger volumeEventLogger) (*VolumesService, error) {
 | 
					func NewVolumeService(root string, pg plugingetter.PluginGetter, rootIDs idtools.Identity, logger volumeEventLogger) (*VolumesService, error) {
 | 
				
			||||||
	ds := drivers.NewStore(pg)
 | 
						ds := drivers.NewStore(pg)
 | 
				
			||||||
	if err := setupDefaultDriver(ds, root, rootIDs); err != nil {
 | 
						if err := setupDefaultDriver(ds, root, rootIDs); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ func TestLocalVolumeSize(t *testing.T) {
 | 
				
			||||||
	assert.Assert(t, err)
 | 
						assert.Assert(t, err)
 | 
				
			||||||
	defer os.RemoveAll(dir)
 | 
						defer os.RemoveAll(dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	l, err := local.New(dir, idtools.IDPair{UID: os.Getuid(), GID: os.Getegid()})
 | 
						l, err := local.New(dir, idtools.Identity{UID: os.Getuid(), GID: os.Getegid()})
 | 
				
			||||||
	assert.Assert(t, err)
 | 
						assert.Assert(t, err)
 | 
				
			||||||
	assert.Assert(t, ds.Register(l, volume.DefaultDriverName))
 | 
						assert.Assert(t, ds.Register(l, volume.DefaultDriverName))
 | 
				
			||||||
	assert.Assert(t, ds.Register(testutils.NewFakeDriver("fake"), "fake"))
 | 
						assert.Assert(t, ds.Register(testutils.NewFakeDriver("fake"), "fake"))
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue