1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Merge pull request #29001 from darrenstahlmsft/WindowsOnLinux

Block pulling Windows images on non-Windows daemons
This commit is contained in:
Vincent Demeester 2017-02-16 19:57:54 +01:00 committed by GitHub
commit c31f73abfd
3 changed files with 55 additions and 30 deletions

View file

@ -142,9 +142,12 @@ func (s *imageConfigStore) RootFSFromConfig(c []byte) (*image.RootFS, error) {
return nil, err return nil, err
} }
// fail immediately on windows // fail immediately on Windows when downloading a non-Windows image
// and vice versa
if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" { if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" {
return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS) return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
} else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" {
return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
} }
return unmarshalledConfig.RootFS, nil return unmarshalledConfig.RootFS, nil

View file

@ -534,15 +534,18 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
} }
configChan := make(chan []byte, 1) configChan := make(chan []byte, 1)
errChan := make(chan error, 1) configErrChan := make(chan error, 1)
layerErrChan := make(chan error, 1)
downloadsDone := make(chan struct{})
var cancel func() var cancel func()
ctx, cancel = context.WithCancel(ctx) ctx, cancel = context.WithCancel(ctx)
defer cancel()
// Pull the image config // Pull the image config
go func() { go func() {
configJSON, err := p.pullSchema2Config(ctx, target.Digest) configJSON, err := p.pullSchema2Config(ctx, target.Digest)
if err != nil { if err != nil {
errChan <- ImageConfigPullError{Err: err} configErrChan <- ImageConfigPullError{Err: err}
cancel() cancel()
return return
} }
@ -553,6 +556,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
configJSON []byte // raw serialized image config configJSON []byte // raw serialized image config
downloadedRootFS *image.RootFS // rootFS from registered layers downloadedRootFS *image.RootFS // rootFS from registered layers
configRootFS *image.RootFS // rootFS from configuration configRootFS *image.RootFS // rootFS from configuration
release func() // release resources from rootFS download
) )
// https://github.com/docker/docker/issues/24766 - Err on the side of caution, // https://github.com/docker/docker/issues/24766 - Err on the side of caution,
@ -564,7 +568,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
// check to block Windows images being pulled on Linux is implemented, it // check to block Windows images being pulled on Linux is implemented, it
// may be necessary to perform the same type of serialisation. // may be necessary to perform the same type of serialisation.
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, errChan) configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, configErrChan)
if err != nil { if err != nil {
return "", "", err return "", "", err
} }
@ -575,41 +579,52 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
} }
if p.config.DownloadManager != nil { if p.config.DownloadManager != nil {
go func() {
var (
err error
rootFS image.RootFS
)
downloadRootFS := *image.NewRootFS() downloadRootFS := *image.NewRootFS()
rootFS, release, err := p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput) rootFS, release, err = p.config.DownloadManager.Download(ctx, downloadRootFS, descriptors, p.config.ProgressOutput)
if err != nil { if err != nil {
if configJSON != nil { // Intentionally do not cancel the config download here
// Already received the config // as the error from config download (if there is one)
return "", "", err // is more interesting than the layer download error
} layerErrChan <- err
select { return
case err = <-errChan:
return "", "", err
default:
cancel()
select {
case <-configChan:
case <-errChan:
}
return "", "", err
}
}
if release != nil {
defer release()
} }
downloadedRootFS = &rootFS downloadedRootFS = &rootFS
close(downloadsDone)
}()
} else {
// We have nothing to download
close(downloadsDone)
} }
if configJSON == nil { if configJSON == nil {
configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, errChan) configJSON, configRootFS, err = receiveConfig(p.config.ImageStore, configChan, configErrChan)
if err == nil && configRootFS == nil {
err = errRootFSInvalid
}
if err != nil { if err != nil {
cancel()
select {
case <-downloadsDone:
case <-layerErrChan:
}
return "", "", err
}
}
select {
case <-downloadsDone:
case err = <-layerErrChan:
return "", "", err return "", "", err
} }
if configRootFS == nil { if release != nil {
return "", "", errRootFSInvalid defer release()
}
} }
if downloadedRootFS != nil { if downloadedRootFS != nil {

View file

@ -272,3 +272,10 @@ func (s *DockerSuite) TestPullLinuxImageFailsOnWindows(c *check.C) {
_, _, err := dockerCmdWithError("pull", "ubuntu") _, _, err := dockerCmdWithError("pull", "ubuntu")
c.Assert(err.Error(), checker.Contains, "cannot be used on this platform") c.Assert(err.Error(), checker.Contains, "cannot be used on this platform")
} }
// Regression test for https://github.com/docker/docker/issues/28892
func (s *DockerSuite) TestPullWindowsImageFailsOnLinux(c *check.C) {
testRequires(c, DaemonIsLinux, Network)
_, _, err := dockerCmdWithError("pull", "microsoft/nanoserver")
c.Assert(err.Error(), checker.Contains, "cannot be used on this platform")
}