diff --git a/daemon/archive.go b/daemon/archive.go index 1999f1243b..4dc43344d1 100644 --- a/daemon/archive.go +++ b/daemon/archive.go @@ -34,6 +34,11 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err res = res[1:] } + // Make sure an online file-system operation is permitted. + if err := daemon.isOnlineFSOperationPermitted(container); err != nil { + return nil, err + } + return daemon.containerCopy(container, res) } @@ -45,6 +50,11 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C return nil, err } + // Make sure an online file-system operation is permitted. + if err := daemon.isOnlineFSOperationPermitted(container); err != nil { + return nil, err + } + return daemon.containerStatPath(container, path) } @@ -57,6 +67,11 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io return nil, nil, err } + // Make sure an online file-system operation is permitted. + if err := daemon.isOnlineFSOperationPermitted(container); err != nil { + return nil, nil, err + } + return daemon.containerArchivePath(container, path) } @@ -72,6 +87,11 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNon return err } + // Make sure an online file-system operation is permitted. + if err := daemon.isOnlineFSOperationPermitted(container); err != nil { + return err + } + return daemon.containerExtractToDir(container, path, noOverwriteDirNonDir, content) } diff --git a/daemon/archive_unix.go b/daemon/archive_unix.go index 47666fe5e8..8806e2e198 100644 --- a/daemon/archive_unix.go +++ b/daemon/archive_unix.go @@ -56,3 +56,9 @@ func fixPermissions(source, destination string, uid, gid int, destExisted bool) return os.Lchown(fullpath, uid, gid) }) } + +// isOnlineFSOperationPermitted returns an error if an online filesystem operation +// is not permitted. +func (daemon *Daemon) isOnlineFSOperationPermitted(container *container.Container) error { + return nil +} diff --git a/daemon/archive_windows.go b/daemon/archive_windows.go index b3a1045341..1c5a894f7c 100644 --- a/daemon/archive_windows.go +++ b/daemon/archive_windows.go @@ -1,6 +1,11 @@ package daemon -import "github.com/docker/docker/container" +import ( + "errors" + + containertypes "github.com/docker/docker/api/types/container" + "github.com/docker/docker/container" +) // checkIfPathIsInAVolume checks if the path is in a volume. If it is, it // cannot be in a read-only volume. If it is not in a volume, the container @@ -16,3 +21,24 @@ func fixPermissions(source, destination string, uid, gid int, destExisted bool) // chown is not supported on Windows return nil } + +// isOnlineFSOperationPermitted returns an error if an online filesystem operation +// is not permitted (such as stat or for copying). Running Hyper-V containers +// cannot have their file-system interrogated from the host as the filter is +// loaded inside the utility VM, not the host. +// IMPORTANT: The container lock must NOT be held when calling this function. +func (daemon *Daemon) isOnlineFSOperationPermitted(container *container.Container) error { + if !container.IsRunning() { + return nil + } + + // Determine isolation. If not specified in the hostconfig, use daemon default. + actualIsolation := container.HostConfig.Isolation + if containertypes.Isolation.IsDefault(containertypes.Isolation(actualIsolation)) { + actualIsolation = daemon.defaultIsolation + } + if containertypes.Isolation.IsHyperV(actualIsolation) { + return errors.New("filesystem operations against a running Hyper-V container are not supported") + } + return nil +}