diff --git a/cmd/podman/containers/cp.go b/cmd/podman/containers/cp.go index ae42eac7b46..abc311bb83b 100644 --- a/cmd/podman/containers/cp.go +++ b/cmd/podman/containers/cp.go @@ -58,7 +58,7 @@ var ( func cpFlags(cmd *cobra.Command) { flags := cmd.Flags() flags.BoolVar(&cpOpts.OverwriteDirNonDir, "overwrite", false, "Allow to overwrite directories with non-directories and vice versa") - flags.BoolVarP(&chown, "archive", "a", true, `Chown copied files to the primary uid/gid of the destination container.`) + flags.BoolVarP(&chown, "archive", "a", false, `Chown copied files to the primary uid/gid of the destination container.`) // Deprecated flags (both are NOPs): exist for backwards compat flags.BoolVar(&cpOpts.Extract, "extract", false, "Deprecated...") diff --git a/libpod/container_copy_common.go b/libpod/container_copy_common.go index 66b66e8c924..ba76d7406a3 100644 --- a/libpod/container_copy_common.go +++ b/libpod/container_copy_common.go @@ -188,6 +188,7 @@ func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir boo } var idPair *idtools.IDPair + var userlessContainer bool if chown { // Make sure we chown the files to the container's main user and group ID. user, err := getContainerUser(c, mountPoint) @@ -196,6 +197,7 @@ func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir boo return nil, err } idPair = &idtools.IDPair{UID: int(user.UID), GID: int(user.GID)} + userlessContainer = user.UserlessContainer } decompressed, err := archive.DecompressStream(reader) @@ -219,6 +221,7 @@ func (c *Container) copyFromArchive(path string, chown, noOverwriteDirNonDir boo NoOverwriteDirNonDir: noOverwriteDirNonDir, NoOverwriteNonDirDir: noOverwriteDirNonDir, Rename: rename, + UserlessContainer: userlessContainer, } return c.joinMountAndExec( @@ -311,9 +314,15 @@ func getContainerUser(container *Container, mountPoint string) (specs.User, erro uid, gid, _, err := chrootuser.GetUser(mountPoint, userspec) u := specs.User{ - UID: uid, - GID: gid, - Username: userspec, + UID: uid, + GID: gid, + Username: userspec, + UserlessContainer: false, + } + + if errors.Is(err, chrootuser.ErrUserlessContainer) { + u.UserlessContainer = true + err = nil } if !strings.Contains(userspec, ":") { diff --git a/vendor/github.com/containers/buildah/copier/copier.go b/vendor/github.com/containers/buildah/copier/copier.go index 6ffe52d86f6..3f5208cb514 100644 --- a/vendor/github.com/containers/buildah/copier/copier.go +++ b/vendor/github.com/containers/buildah/copier/copier.go @@ -451,6 +451,7 @@ type PutOptions struct { NoOverwriteDirNonDir bool // instead of quietly overwriting directories with non-directories, return an error NoOverwriteNonDirDir bool // instead of quietly overwriting non-directories with directories, return an error Rename map[string]string // rename items with the specified names, or under the specified names + UserlessContainer bool // indicates userless container } // Put extracts an archive from the bulkReader at the specified directory. @@ -1943,7 +1944,7 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM hdr.Name = handleRename(req.PutOptions.Rename, hdr.Name) } // figure out who should own this new item - if idMappings != nil && !idMappings.Empty() { + if idMappings != nil && !idMappings.Empty() && !req.PutOptions.UserlessContainer { containerPair := idtools.IDPair{UID: hdr.Uid, GID: hdr.Gid} hostPair, err := idMappings.ToHost(containerPair) if err != nil { @@ -1956,7 +1957,7 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM hdr.Uid, hdr.Gid = dirUID, dirGID } } else { - if req.PutOptions.ChownFiles != nil { + if req.PutOptions.ChownFiles != nil && !req.PutOptions.UserlessContainer { hdr.Uid, hdr.Gid = *fileUID, *fileGID } } diff --git a/vendor/github.com/containers/buildah/pkg/chrootuser/user.go b/vendor/github.com/containers/buildah/pkg/chrootuser/user.go index e81e01d4335..dd1bf0ad675 100644 --- a/vendor/github.com/containers/buildah/pkg/chrootuser/user.go +++ b/vendor/github.com/containers/buildah/pkg/chrootuser/user.go @@ -11,6 +11,7 @@ import ( // ErrNoSuchUser indicates that the user provided by the caller does not // exist in /etc/passws var ErrNoSuchUser = errors.New("user does not exist in /etc/passwd") +var ErrUserlessContainer = errors.New("userless container") // GetUser will return the uid, gid of the user specified in the userspec // it will use the /etc/passwd and /etc/group files inside of the rootdir @@ -70,6 +71,10 @@ func GetUser(rootdir, userspec string) (uint32, uint32, string, error) { homedir = "/" } + if spec[0] == "" { + return 0, 0, homedir, ErrUserlessContainer + } + if uerr == nil && gerr == nil { return uint32(uid64), uint32(gid64), homedir, nil } diff --git a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go index 1aa0693b57d..51fcf2a5466 100644 --- a/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go +++ b/vendor/github.com/opencontainers/runtime-spec/specs-go/config.go @@ -155,6 +155,8 @@ type User struct { AdditionalGids []uint32 `json:"additionalGids,omitempty" platform:"linux,solaris"` // Username is the user name. Username string `json:"username,omitempty" platform:"windows"` + // Userless container. + UserlessContainer bool `json:"userless,omitempty"` } // Root contains information about the container's root filesystem on the host.